1 /*
2  * Copyright (C) 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "aidl_language.h"
18 #include "aidl_typenames.h"
19 #include "logging.h"
20 
21 #include <stdlib.h>
22 #include <algorithm>
23 #include <iostream>
24 #include <memory>
25 
26 #include <android-base/parsedouble.h>
27 #include <android-base/parseint.h>
28 #include <android-base/strings.h>
29 
30 using android::base::ConsumeSuffix;
31 using android::base::EndsWith;
32 using android::base::Join;
33 using android::base::StartsWith;
34 using std::string;
35 using std::unique_ptr;
36 using std::vector;
37 
38 #define SHOULD_NOT_REACH() CHECK(false) << LOG(FATAL) << ": should not reach here: "
39 #define OPEQ(__y__) (string(op_) == string(__y__))
40 #define COMPUTE_UNARY(__op__)  \
41   if (op == string(#__op__)) { \
42     *out = __op__ val;         \
43     return true;               \
44   }
45 #define COMPUTE_BINARY(__op__) \
46   if (op == string(#__op__)) { \
47     *out = lval __op__ rval;   \
48     return true;               \
49   }
50 #define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
51 #define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
52 #define OP_IS_BIN_COMP \
53   (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
54 #define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
55 #define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
56 
57 // NOLINT to suppress missing parentheses warnings about __def__.
58 #define SWITCH_KIND(__cond__, __action__, __def__) \
59   switch (__cond__) {                              \
60     case Type::BOOLEAN:                            \
61       __action__(bool);                            \
62     case Type::INT8:                               \
63       __action__(int8_t);                          \
64     case Type::INT32:                              \
65       __action__(int32_t);                         \
66     case Type::INT64:                              \
67       __action__(int64_t);                         \
68     default:                                       \
69       __def__; /* NOLINT */                        \
70   }
71 
72 template <class T>
handleUnary(const AidlConstantValue & context,const string & op,T val,int64_t * out)73 bool handleUnary(const AidlConstantValue& context, const string& op, T val, int64_t* out) {
74   COMPUTE_UNARY(+)
75   COMPUTE_UNARY(-)
76   COMPUTE_UNARY(!)
77   COMPUTE_UNARY(~)
78   AIDL_FATAL(context) << "Could not handleUnary for " << op << " " << val;
79   return false;
80 }
81 template <>
handleUnary(const AidlConstantValue & context,const string & op,bool val,int64_t * out)82 bool handleUnary<bool>(const AidlConstantValue& context, const string& op, bool val, int64_t* out) {
83   COMPUTE_UNARY(+)
84   COMPUTE_UNARY(-)
85   COMPUTE_UNARY(!)
86 
87   if (op == "~") {
88     AIDL_ERROR(context) << "Bitwise negation of a boolean expression is always true.";
89     return false;
90   }
91   AIDL_FATAL(context) << "Could not handleUnary for " << op << " " << val;
92   return false;
93 }
94 
95 template <class T>
handleBinaryCommon(const AidlConstantValue & context,T lval,const string & op,T rval,int64_t * out)96 bool handleBinaryCommon(const AidlConstantValue& context, T lval, const string& op, T rval,
97                         int64_t* out) {
98   COMPUTE_BINARY(+)
99   COMPUTE_BINARY(-)
100   COMPUTE_BINARY(*)
101   COMPUTE_BINARY(/)
102   COMPUTE_BINARY(%)
103   COMPUTE_BINARY(|)
104   COMPUTE_BINARY(^)
105   COMPUTE_BINARY(&)
106   // comparison operators: return 0 or 1 by nature.
107   COMPUTE_BINARY(==)
108   COMPUTE_BINARY(!=)
109   COMPUTE_BINARY(<)
110   COMPUTE_BINARY(>)
111   COMPUTE_BINARY(<=)
112   COMPUTE_BINARY(>=)
113 
114   AIDL_FATAL(context) << "Could not handleBinaryCommon for " << lval << " " << op << " " << rval;
115   return false;
116 }
117 
118 template <class T>
handleShift(const AidlConstantValue & context,T lval,const string & op,int64_t rval,int64_t * out)119 bool handleShift(const AidlConstantValue& context, T lval, const string& op, int64_t rval,
120                  int64_t* out) {
121   // just cast rval to int64_t and it should fit.
122   COMPUTE_BINARY(>>)
123   COMPUTE_BINARY(<<)
124 
125   AIDL_FATAL(context) << "Could not handleShift for " << lval << " " << op << " " << rval;
126   return false;
127 }
128 
handleLogical(const AidlConstantValue & context,bool lval,const string & op,bool rval,int64_t * out)129 bool handleLogical(const AidlConstantValue& context, bool lval, const string& op, bool rval,
130                    int64_t* out) {
131   COMPUTE_BINARY(||);
132   COMPUTE_BINARY(&&);
133 
134   AIDL_FATAL(context) << "Could not handleLogical for " << lval << " " << op << " " << rval;
135   return false;
136 }
137 
isValidLiteralChar(char c)138 static bool isValidLiteralChar(char c) {
139   return !(c <= 0x1f ||  // control characters are < 0x20
140            c >= 0x7f ||  // DEL is 0x7f
141            c == '\\');   // Disallow backslashes for future proofing.
142 }
143 
IsCompatibleType(Type type,const string & op)144 bool AidlUnaryConstExpression::IsCompatibleType(Type type, const string& op) {
145   // Verify the unary type here
146   switch (type) {
147     case Type::BOOLEAN:  // fall-through
148     case Type::INT8:     // fall-through
149     case Type::INT32:    // fall-through
150     case Type::INT64:
151       return true;
152     case Type::FLOATING:
153       return (op == "+" || op == "-");
154     default:
155       return false;
156   }
157 }
158 
AreCompatibleTypes(Type t1,Type t2)159 bool AidlBinaryConstExpression::AreCompatibleTypes(Type t1, Type t2) {
160   switch (t1) {
161     case Type::STRING:
162       if (t2 == Type::STRING) {
163         return true;
164       }
165       break;
166     case Type::BOOLEAN:  // fall-through
167     case Type::INT8:     // fall-through
168     case Type::INT32:    // fall-through
169     case Type::INT64:
170       switch (t2) {
171         case Type::BOOLEAN:  // fall-through
172         case Type::INT8:     // fall-through
173         case Type::INT32:    // fall-through
174         case Type::INT64:
175           return true;
176           break;
177         default:
178           break;
179       }
180       break;
181     default:
182       break;
183   }
184 
185   return false;
186 }
187 
188 // Returns the promoted kind for both operands
UsualArithmeticConversion(Type left,Type right)189 AidlConstantValue::Type AidlBinaryConstExpression::UsualArithmeticConversion(Type left,
190                                                                              Type right) {
191   // These are handled as special cases
192   CHECK(left != Type::STRING && right != Type::STRING);
193   CHECK(left != Type::FLOATING && right != Type::FLOATING);
194 
195   // Kinds in concern: bool, (u)int[8|32|64]
196   if (left == right) return left;  // easy case
197   if (left == Type::BOOLEAN) return right;
198   if (right == Type::BOOLEAN) return left;
199 
200   return left < right ? right : left;
201 }
202 
203 // Returns the promoted integral type where INT32 is the smallest type
IntegralPromotion(Type in)204 AidlConstantValue::Type AidlBinaryConstExpression::IntegralPromotion(Type in) {
205   return (Type::INT32 < in) ? in : Type::INT32;
206 }
207 
208 template <typename T>
cast() const209 T AidlConstantValue::cast() const {
210   CHECK(is_evaluated_ == true);
211 
212 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(final_value_));
213 
214   SWITCH_KIND(final_type_, CASE_CAST_T, SHOULD_NOT_REACH(); return 0;);
215 }
216 
Default(const AidlTypeSpecifier & specifier)217 AidlConstantValue* AidlConstantValue::Default(const AidlTypeSpecifier& specifier) {
218   AidlLocation location = specifier.GetLocation();
219 
220   // allocation of int[0] is a bit wasteful in Java
221   if (specifier.IsArray()) {
222     return nullptr;
223   }
224 
225   const std::string name = specifier.GetName();
226   if (name == "boolean") {
227     return Boolean(location, false);
228   }
229   if (name == "byte" || name == "int" || name == "long") {
230     return Integral(location, "0");
231   }
232   if (name == "float") {
233     return Floating(location, "0.0f");
234   }
235   if (name == "double") {
236     return Floating(location, "0.0");
237   }
238   return nullptr;
239 }
240 
Boolean(const AidlLocation & location,bool value)241 AidlConstantValue* AidlConstantValue::Boolean(const AidlLocation& location, bool value) {
242   return new AidlConstantValue(location, Type::BOOLEAN, value ? "true" : "false");
243 }
244 
Character(const AidlLocation & location,char value)245 AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location, char value) {
246   const std::string explicit_value = string("'") + value + "'";
247   if (!isValidLiteralChar(value)) {
248     AIDL_ERROR(location) << "Invalid character literal " << value;
249     return new AidlConstantValue(location, Type::ERROR, explicit_value);
250   }
251   return new AidlConstantValue(location, Type::CHARACTER, explicit_value);
252 }
253 
Floating(const AidlLocation & location,const std::string & value)254 AidlConstantValue* AidlConstantValue::Floating(const AidlLocation& location,
255                                                const std::string& value) {
256   return new AidlConstantValue(location, Type::FLOATING, value);
257 }
258 
IsHex(const string & value)259 bool AidlConstantValue::IsHex(const string& value) {
260   return StartsWith(value, "0x") || StartsWith(value, "0X");
261 }
262 
ParseIntegral(const string & value,int64_t * parsed_value,Type * parsed_type)263 bool AidlConstantValue::ParseIntegral(const string& value, int64_t* parsed_value,
264                                       Type* parsed_type) {
265   if (parsed_value == nullptr || parsed_type == nullptr) {
266     return false;
267   }
268 
269   const bool isLong = EndsWith(value, 'l') || EndsWith(value, 'L');
270   const std::string value_substr = isLong ? value.substr(0, value.size() - 1) : value;
271 
272   if (IsHex(value)) {
273     // AIDL considers 'const int foo = 0xffffffff' as -1, but if we want to
274     // handle that when computing constant expressions, then we need to
275     // represent 0xffffffff as a uint32_t. However, AIDL only has signed types;
276     // so we parse as an unsigned int when possible and then cast to a signed
277     // int. One example of this is in ICameraService.aidl where a constant int
278     // is used for bit manipulations which ideally should be handled with an
279     // unsigned int.
280     //
281     // Note, for historical consistency, we need to consider small hex values
282     // as an integral type. Recognizing them as INT8 could break some files,
283     // even though it would simplify this code.
284     if (uint32_t rawValue32;
285         !isLong && android::base::ParseUint<uint32_t>(value_substr, &rawValue32)) {
286       *parsed_value = static_cast<int32_t>(rawValue32);
287       *parsed_type = Type::INT32;
288     } else if (uint64_t rawValue64; android::base::ParseUint<uint64_t>(value_substr, &rawValue64)) {
289       *parsed_value = static_cast<int64_t>(rawValue64);
290       *parsed_type = Type::INT64;
291     } else {
292       *parsed_value = 0;
293       *parsed_type = Type::ERROR;
294       return false;
295     }
296     return true;
297   }
298 
299   if (!android::base::ParseInt<int64_t>(value_substr, parsed_value)) {
300     *parsed_value = 0;
301     *parsed_type = Type::ERROR;
302     return false;
303   }
304 
305   if (isLong) {
306     *parsed_type = Type::INT64;
307   } else {
308     // guess literal type.
309     if (*parsed_value <= INT8_MAX && *parsed_value >= INT8_MIN) {
310       *parsed_type = Type::INT8;
311     } else if (*parsed_value <= INT32_MAX && *parsed_value >= INT32_MIN) {
312       *parsed_type = Type::INT32;
313     } else {
314       *parsed_type = Type::INT64;
315     }
316   }
317   return true;
318 }
319 
Integral(const AidlLocation & location,const string & value)320 AidlConstantValue* AidlConstantValue::Integral(const AidlLocation& location, const string& value) {
321   CHECK(!value.empty());
322 
323   Type parsed_type;
324   int64_t parsed_value = 0;
325   bool success = ParseIntegral(value, &parsed_value, &parsed_type);
326   if (!success) {
327     return nullptr;
328   }
329 
330   return new AidlConstantValue(location, parsed_type, parsed_value, value);
331 }
332 
Array(const AidlLocation & location,std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values)333 AidlConstantValue* AidlConstantValue::Array(
334     const AidlLocation& location, std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values) {
335   CHECK(values != nullptr) << location;
336   return new AidlConstantValue(location, Type::ARRAY, std::move(values));
337 }
338 
String(const AidlLocation & location,const string & value)339 AidlConstantValue* AidlConstantValue::String(const AidlLocation& location, const string& value) {
340   for (size_t i = 0; i < value.length(); ++i) {
341     if (!isValidLiteralChar(value[i])) {
342       AIDL_ERROR(location) << "Found invalid character at index " << i << " in string constant '"
343                            << value << "'";
344       return new AidlConstantValue(location, Type::ERROR, value);
345     }
346   }
347 
348   return new AidlConstantValue(location, Type::STRING, value);
349 }
350 
ShallowIntegralCopy(const AidlConstantValue & other)351 AidlConstantValue* AidlConstantValue::ShallowIntegralCopy(const AidlConstantValue& other) {
352   // TODO(b/141313220) Perform a full copy instead of parsing+unparsing
353   AidlTypeSpecifier type = AidlTypeSpecifier(AIDL_LOCATION_HERE, "long", false, nullptr, "");
354   // TODO(b/142722772) CheckValid() should be called before ValueString()
355   if (!other.CheckValid() || !other.evaluate(type)) {
356     AIDL_ERROR(other) << "Failed to parse expression as integer: " << other.value_;
357     return nullptr;
358   }
359   const std::string& value = other.ValueString(type, AidlConstantValueDecorator);
360   if (value.empty()) {
361     return nullptr;  // error already logged
362   }
363 
364   AidlConstantValue* result = Integral(AIDL_LOCATION_HERE, value);
365   if (result == nullptr) {
366     AIDL_FATAL(other) << "Unable to perform ShallowIntegralCopy.";
367   }
368   return result;
369 }
370 
ValueString(const AidlTypeSpecifier & type,const ConstantValueDecorator & decorator) const371 string AidlConstantValue::ValueString(const AidlTypeSpecifier& type,
372                                       const ConstantValueDecorator& decorator) const {
373   if (type.IsGeneric()) {
374     AIDL_ERROR(type) << "Generic type cannot be specified with a constant literal.";
375     return "";
376   }
377   if (!is_evaluated_) {
378     // TODO(b/142722772) CheckValid() should be called before ValueString()
379     bool success = CheckValid();
380     success &= evaluate(type);
381     if (!success) {
382       // the detailed error message shall be printed in evaluate
383       return "";
384     }
385   }
386   if (!is_valid_) {
387     AIDL_ERROR(this) << "Invalid constant value: " + value_;
388     return "";
389   }
390   const string& type_string = type.GetName();
391   int err = 0;
392 
393   switch (final_type_) {
394     case Type::CHARACTER:
395       if (type_string == "char") {
396         return decorator(type, final_string_value_);
397       }
398       err = -1;
399       break;
400     case Type::STRING:
401       if (type_string == "String") {
402         return decorator(type, final_string_value_);
403       }
404       err = -1;
405       break;
406     case Type::BOOLEAN:  // fall-through
407     case Type::INT8:     // fall-through
408     case Type::INT32:    // fall-through
409     case Type::INT64:
410       if (type_string == "byte") {
411         if (final_value_ > INT8_MAX || final_value_ < INT8_MIN) {
412           err = -1;
413           break;
414         }
415         return decorator(type, std::to_string(static_cast<int8_t>(final_value_)));
416       } else if (type_string == "int") {
417         if (final_value_ > INT32_MAX || final_value_ < INT32_MIN) {
418           err = -1;
419           break;
420         }
421         return decorator(type, std::to_string(static_cast<int32_t>(final_value_)));
422       } else if (type_string == "long") {
423         return decorator(type, std::to_string(final_value_));
424       } else if (type_string == "boolean") {
425         return decorator(type, final_value_ ? "true" : "false");
426       }
427       err = -1;
428       break;
429     case Type::ARRAY: {
430       if (!type.IsArray()) {
431         err = -1;
432         break;
433       }
434       vector<string> value_strings;
435       value_strings.reserve(values_.size());
436       bool success = true;
437 
438       for (const auto& value : values_) {
439         const AidlTypeSpecifier& array_base = type.ArrayBase();
440         const string value_string = value->ValueString(array_base, decorator);
441         if (value_string.empty()) {
442           success = false;
443           break;
444         }
445         value_strings.push_back(value_string);
446       }
447       if (!success) {
448         err = -1;
449         break;
450       }
451 
452       return decorator(type, "{" + Join(value_strings, ", ") + "}");
453     }
454     case Type::FLOATING: {
455       std::string_view raw_view(value_.c_str());
456       bool is_float_literal = ConsumeSuffix(&raw_view, "f");
457       std::string stripped_value = std::string(raw_view);
458 
459       if (type_string == "double") {
460         double parsed_value;
461         if (!android::base::ParseDouble(stripped_value, &parsed_value)) {
462           AIDL_ERROR(this) << "Could not parse " << value_;
463           err = -1;
464           break;
465         }
466         return decorator(type, std::to_string(parsed_value));
467       }
468       if (is_float_literal && type_string == "float") {
469         float parsed_value;
470         if (!android::base::ParseFloat(stripped_value, &parsed_value)) {
471           AIDL_ERROR(this) << "Could not parse " << value_;
472           err = -1;
473           break;
474         }
475         return decorator(type, std::to_string(parsed_value) + "f");
476       }
477       err = -1;
478       break;
479     }
480     default:
481       err = -1;
482       break;
483   }
484 
485   CHECK(err != 0);
486   AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string;
487   return "";
488 }
489 
CheckValid() const490 bool AidlConstantValue::CheckValid() const {
491   // Nothing needs to be checked here. The constant value will be validated in
492   // the constructor or in the evaluate() function.
493   if (is_evaluated_) return is_valid_;
494 
495   switch (type_) {
496     case Type::BOOLEAN:    // fall-through
497     case Type::INT8:       // fall-through
498     case Type::INT32:      // fall-through
499     case Type::INT64:      // fall-through
500     case Type::ARRAY:      // fall-through
501     case Type::CHARACTER:  // fall-through
502     case Type::STRING:     // fall-through
503     case Type::FLOATING:   // fall-through
504     case Type::UNARY:      // fall-through
505     case Type::BINARY:
506       is_valid_ = true;
507       break;
508     case Type::ERROR:
509       return false;
510     default:
511       AIDL_FATAL(this) << "Unrecognized constant value type: " << ToString(type_);
512       return false;
513   }
514 
515   return true;
516 }
517 
evaluate(const AidlTypeSpecifier & type) const518 bool AidlConstantValue::evaluate(const AidlTypeSpecifier& type) const {
519   if (is_evaluated_) {
520     return is_valid_;
521   }
522   int err = 0;
523   is_evaluated_ = true;
524 
525   switch (type_) {
526     case Type::ARRAY: {
527       if (!type.IsArray()) {
528         AIDL_ERROR(this) << "Invalid constant array type: " << type.GetName();
529         err = -1;
530         break;
531       }
532       Type array_type = Type::ERROR;
533       bool success = true;
534       for (const auto& value : values_) {
535         success = value->CheckValid();
536         if (success) {
537           success = value->evaluate(type.ArrayBase());
538           if (!success) {
539             AIDL_ERROR(this) << "Invalid array element: " << value->value_;
540             break;
541           }
542           if (array_type == Type::ERROR) {
543             array_type = value->final_type_;
544           } else if (!AidlBinaryConstExpression::AreCompatibleTypes(array_type,
545                                                                     value->final_type_)) {
546             AIDL_ERROR(this) << "Incompatible array element type: " << ToString(value->final_type_)
547                              << ". Expecting type compatible with " << ToString(array_type);
548             success = false;
549             break;
550           }
551         } else {
552           break;
553         }
554       }
555       if (!success) {
556         err = -1;
557         break;
558       }
559       final_type_ = type_;
560       break;
561     }
562     case Type::BOOLEAN:
563       if ((value_ != "true") && (value_ != "false")) {
564         AIDL_ERROR(this) << "Invalid constant boolean value: " << value_;
565         err = -1;
566         break;
567       }
568       final_value_ = (value_ == "true") ? 1 : 0;
569       final_type_ = type_;
570       break;
571     case Type::INT8:   // fall-through
572     case Type::INT32:  // fall-through
573     case Type::INT64:
574       // Parsing happens in the constructor
575       final_type_ = type_;
576       break;
577     case Type::CHARACTER:  // fall-through
578     case Type::STRING:
579       final_string_value_ = value_;
580       final_type_ = type_;
581       break;
582     case Type::FLOATING:
583       // Just parse on the fly in ValueString
584       final_type_ = type_;
585       break;
586     default:
587       AIDL_FATAL(this) << "Unrecognized constant value type: " << ToString(type_);
588       err = -1;
589   }
590 
591   return (err == 0) ? true : false;
592 }
593 
ToString(Type type)594 string AidlConstantValue::ToString(Type type) {
595   switch (type) {
596     case Type::BOOLEAN:
597       return "a literal boolean";
598     case Type::INT8:
599       return "an int8 literal";
600     case Type::INT32:
601       return "an int32 literal";
602     case Type::INT64:
603       return "an int64 literal";
604     case Type::ARRAY:
605       return "a literal array";
606     case Type::CHARACTER:
607       return "a literal char";
608     case Type::STRING:
609       return "a literal string";
610     case Type::FLOATING:
611       return "a literal float";
612     case Type::UNARY:
613       return "a unary expression";
614     case Type::BINARY:
615       return "a binary expression";
616     case Type::ERROR:
617       LOG(FATAL) << "aidl internal error: error type failed to halt program";
618       return "";
619     default:
620       LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
621       return "";  // not reached
622   }
623 }
624 
CheckValid() const625 bool AidlUnaryConstExpression::CheckValid() const {
626   if (is_evaluated_) return is_valid_;
627   CHECK(unary_ != nullptr);
628 
629   is_valid_ = unary_->CheckValid();
630   if (!is_valid_) {
631     final_type_ = Type::ERROR;
632     return false;
633   }
634 
635   return AidlConstantValue::CheckValid();
636 }
637 
evaluate(const AidlTypeSpecifier & type) const638 bool AidlUnaryConstExpression::evaluate(const AidlTypeSpecifier& type) const {
639   if (is_evaluated_) {
640     return is_valid_;
641   }
642   is_evaluated_ = true;
643 
644   // Recursively evaluate the expression tree
645   if (!unary_->is_evaluated_) {
646     // TODO(b/142722772) CheckValid() should be called before ValueString()
647     bool success = CheckValid();
648     success &= unary_->evaluate(type);
649     if (!success) {
650       is_valid_ = false;
651       return false;
652     }
653   }
654   if (!IsCompatibleType(unary_->final_type_, op_)) {
655     AIDL_ERROR(unary_) << "'" << op_ << "'"
656                        << " is not compatible with " << ToString(unary_->final_type_)
657                        << ": " + value_;
658     is_valid_ = false;
659     return false;
660   }
661   if (!unary_->is_valid_) {
662     AIDL_ERROR(unary_) << "Invalid constant unary expression: " + value_;
663     is_valid_ = false;
664     return false;
665   }
666   final_type_ = unary_->final_type_;
667 
668   if (final_type_ == Type::FLOATING) {
669     // don't do anything here. ValueString() will handle everything.
670     is_valid_ = true;
671     return true;
672   }
673 
674 #define CASE_UNARY(__type__) \
675   return handleUnary(*this, op_, static_cast<__type__>(unary_->final_value_), &final_value_);
676 
677   SWITCH_KIND(final_type_, CASE_UNARY, SHOULD_NOT_REACH(); final_type_ = Type::ERROR;
678               is_valid_ = false; return false;)
679 }
680 
CheckValid() const681 bool AidlBinaryConstExpression::CheckValid() const {
682   bool success = false;
683   if (is_evaluated_) return is_valid_;
684   CHECK(left_val_ != nullptr);
685   CHECK(right_val_ != nullptr);
686 
687   success = left_val_->CheckValid();
688   if (!success) {
689     final_type_ = Type::ERROR;
690     AIDL_ERROR(this) << "Invalid left operand in binary expression: " + value_;
691   }
692 
693   success = right_val_->CheckValid();
694   if (!success) {
695     AIDL_ERROR(this) << "Invalid right operand in binary expression: " + value_;
696     final_type_ = Type::ERROR;
697   }
698 
699   if (final_type_ == Type::ERROR) {
700     is_valid_ = false;
701     return false;
702   }
703 
704   is_valid_ = true;
705   return AidlConstantValue::CheckValid();
706 }
707 
evaluate(const AidlTypeSpecifier & type) const708 bool AidlBinaryConstExpression::evaluate(const AidlTypeSpecifier& type) const {
709   if (is_evaluated_) {
710     return is_valid_;
711   }
712   is_evaluated_ = true;
713   CHECK(left_val_ != nullptr);
714   CHECK(right_val_ != nullptr);
715 
716   // Recursively evaluate the binary expression tree
717   if (!left_val_->is_evaluated_ || !right_val_->is_evaluated_) {
718     // TODO(b/142722772) CheckValid() should be called before ValueString()
719     bool success = CheckValid();
720     success &= left_val_->evaluate(type);
721     success &= right_val_->evaluate(type);
722     if (!success) {
723       is_valid_ = false;
724       return false;
725     }
726   }
727   if (!left_val_->is_valid_ || !right_val_->is_valid_) {
728     is_valid_ = false;
729     return false;
730   }
731   is_valid_ = AreCompatibleTypes(left_val_->final_type_, right_val_->final_type_);
732   if (!is_valid_) {
733     return false;
734   }
735 
736   bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
737 
738   // Handle String case first
739   if (left_val_->final_type_ == Type::STRING) {
740     if (!OPEQ("+")) {
741       // invalid operation on strings
742       final_type_ = Type::ERROR;
743       is_valid_ = false;
744       return false;
745     }
746 
747     // Remove trailing " from lhs
748     const string& lhs = left_val_->final_string_value_;
749     if (lhs.back() != '"') {
750       AIDL_ERROR(this) << "'" << lhs << "' is missing a trailing quote.";
751       final_type_ = Type::ERROR;
752       is_valid_ = false;
753       return false;
754     }
755     const string& rhs = right_val_->final_string_value_;
756     // Remove starting " from rhs
757     if (rhs.front() != '"') {
758       AIDL_ERROR(this) << "'" << rhs << "' is missing a leading quote.";
759       final_type_ = Type::ERROR;
760       is_valid_ = false;
761       return false;
762     }
763 
764     final_string_value_ = string(lhs.begin(), lhs.end() - 1).append(rhs.begin() + 1, rhs.end());
765     final_type_ = Type::STRING;
766     return true;
767   }
768 
769   // CASE: + - *  / % | ^ & < > <= >= == !=
770   if (isArithmeticOrBitflip || OP_IS_BIN_COMP) {
771     if ((op_ == "/" || op_ == "%") && right_val_->final_value_ == 0) {
772       final_type_ = Type::ERROR;
773       is_valid_ = false;
774       AIDL_ERROR(this) << "Cannot do division operation with zero for expression: " + value_;
775       return false;
776     }
777 
778     // promoted kind for both operands.
779     Type promoted = UsualArithmeticConversion(IntegralPromotion(left_val_->final_type_),
780                                               IntegralPromotion(right_val_->final_type_));
781     // result kind.
782     final_type_ = isArithmeticOrBitflip
783                       ? promoted        // arithmetic or bitflip operators generates promoted type
784                       : Type::BOOLEAN;  // comparison operators generates bool
785 
786 #define CASE_BINARY_COMMON(__type__)                                                    \
787   return handleBinaryCommon(*this, static_cast<__type__>(left_val_->final_value_), op_, \
788                             static_cast<__type__>(right_val_->final_value_), &final_value_);
789 
790     SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); final_type_ = Type::ERROR;
791                 is_valid_ = false; return false;)
792   }
793 
794   // CASE: << >>
795   string newOp = op_;
796   if (OP_IS_BIN_SHIFT) {
797     final_type_ = IntegralPromotion(left_val_->final_type_);
798     // instead of promoting rval, simply casting it to int64 should also be good.
799     int64_t numBits = right_val_->cast<int64_t>();
800     if (numBits < 0) {
801       // shifting with negative number of bits is undefined in C. In AIDL it
802       // is defined as shifting into the other direction.
803       newOp = OPEQ("<<") ? ">>" : "<<";
804       numBits = -numBits;
805     }
806 
807 #define CASE_SHIFT(__type__)                                                                \
808   return handleShift(*this, static_cast<__type__>(left_val_->final_value_), newOp, numBits, \
809                      &final_value_);
810 
811     SWITCH_KIND(final_type_, CASE_SHIFT, SHOULD_NOT_REACH(); final_type_ = Type::ERROR;
812                 is_valid_ = false; return false;)
813   }
814 
815   // CASE: && ||
816   if (OP_IS_BIN_LOGICAL) {
817     final_type_ = Type::BOOLEAN;
818     // easy; everything is bool.
819     return handleLogical(*this, left_val_->final_value_, op_, right_val_->final_value_,
820                          &final_value_);
821   }
822 
823   SHOULD_NOT_REACH();
824   is_valid_ = false;
825   return false;
826 }
827 
AidlConstantValue(const AidlLocation & location,Type parsed_type,int64_t parsed_value,const string & checked_value)828 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type parsed_type,
829                                      int64_t parsed_value, const string& checked_value)
830     : AidlNode(location),
831       type_(parsed_type),
832       value_(checked_value),
833       final_type_(parsed_type),
834       final_value_(parsed_value) {
835   CHECK(!value_.empty() || type_ == Type::ERROR) << location;
836   CHECK(type_ == Type::INT8 || type_ == Type::INT32 || type_ == Type::INT64) << location;
837 }
838 
AidlConstantValue(const AidlLocation & location,Type type,const string & checked_value)839 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
840                                      const string& checked_value)
841     : AidlNode(location),
842       type_(type),
843       value_(checked_value),
844       final_type_(type) {
845   CHECK(!value_.empty() || type_ == Type::ERROR) << location;
846   switch (type_) {
847     case Type::INT8:
848     case Type::INT32:
849     case Type::INT64:
850     case Type::ARRAY:
851       AIDL_FATAL(this) << "Invalid type: " << ToString(type_);
852       break;
853     default:
854       break;
855   }
856 }
857 
AidlConstantValue(const AidlLocation & location,Type type,std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values)858 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
859                                      std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values)
860     : AidlNode(location),
861       type_(type),
862       values_(std::move(*values)),
863       is_valid_(false),
864       is_evaluated_(false),
865       final_type_(type) {
866   CHECK(type_ == Type::ARRAY);
867 }
868 
AidlUnaryConstExpression(const AidlLocation & location,const string & op,std::unique_ptr<AidlConstantValue> rval)869 AidlUnaryConstExpression::AidlUnaryConstExpression(const AidlLocation& location, const string& op,
870                                                    std::unique_ptr<AidlConstantValue> rval)
871     : AidlConstantValue(location, Type::UNARY, op + rval->value_),
872       unary_(std::move(rval)),
873       op_(op) {
874   final_type_ = Type::UNARY;
875 }
876 
AidlBinaryConstExpression(const AidlLocation & location,std::unique_ptr<AidlConstantValue> lval,const string & op,std::unique_ptr<AidlConstantValue> rval)877 AidlBinaryConstExpression::AidlBinaryConstExpression(const AidlLocation& location,
878                                                      std::unique_ptr<AidlConstantValue> lval,
879                                                      const string& op,
880                                                      std::unique_ptr<AidlConstantValue> rval)
881     : AidlConstantValue(location, Type::BINARY, lval->value_ + op + rval->value_),
882       left_val_(std::move(lval)),
883       right_val_(std::move(rval)),
884       op_(op) {
885   final_type_ = Type::BINARY;
886 }
887