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