Resolve constant expressions for external constants.

* Allow constant expressions to be used as array sizes
  and as annotation values.

Bug: 31592132 allow constant expressions to be used as array sizes.
Bug: 31628863 Autofill values for enum type

Test: `make android.hardware.tests.expression@1.0` compiles
  and generates enum class Color with autofilled values.
Test: `make hidl_test_java` succeeds.
Test: `make hidl_test && adb sync && adb shell hidl_test` succeeds.
Test: `mma`

Change-Id: I57377ec608503d4741d305e98144264b07973055
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index ce6a49a..5efe93c 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -22,6 +22,7 @@
 #include "CompoundType.h"
 #include "ConstantExpression.h"
 #include "EnumType.h"
+#include "FQName.h"
 #include "GenericBinder.h"
 #include "Interface.h"
 #include "Method.h"
@@ -106,12 +107,13 @@
 %type<fields> field_declarations struct_or_union_body
 %type<constantExpression> const_expr
 %type<enumValue> enum_value
-%type<enumValues> enum_values
+%type<enumValues> enum_values enum_declaration_body
 %type<typedVars> typed_vars
 %type<typedVar> typed_var
 %type<method> method_declaration
 %type<compoundStyle> struct_or_union_keyword
-%type<stringVec> annotation_string_values annotation_value
+%type<stringVec> annotation_string_values annotation_string_value
+%type<constExprVec> annotation_const_expr_values annotation_const_expr_value
 %type<annotationParam> annotation_param
 %type<annotationParams> opt_annotation_params annotation_params
 %type<annotation> annotation
@@ -134,6 +136,7 @@
     android::Method *method;
     android::CompoundType::Style compoundStyle;
     std::vector<std::string> *stringVec;
+    std::vector<android::ConstantExpression *> *constExprVec;
     android::AnnotationParam *annotationParam;
     android::AnnotationParamVector *annotationParams;
     android::Annotation *annotation;
@@ -186,13 +189,17 @@
     ;
 
 annotation_param
-    : IDENTIFIER '=' annotation_value
+    : IDENTIFIER '=' annotation_string_value
+      {
+          $$ = new AnnotationParam($1, $3);
+      }
+    | IDENTIFIER '=' annotation_const_expr_value
       {
           $$ = new AnnotationParam($1, $3);
       }
     ;
 
-annotation_value
+annotation_string_value
     : STRING_LITERAL
       {
           $$ = new std::vector<std::string>;
@@ -214,6 +221,28 @@
       }
     ;
 
+annotation_const_expr_value
+    : const_expr
+      {
+          $$ = new std::vector<ConstantExpression *>;
+          $$->push_back($1);
+      }
+    | '{' annotation_const_expr_values '}' { $$ = $2; }
+    ;
+
+annotation_const_expr_values
+    : const_expr
+      {
+          $$ = new std::vector<ConstantExpression *>;
+          $$->push_back($1);
+      }
+    | annotation_const_expr_values ',' const_expr
+      {
+          $$ = $1;
+          $$->push_back($3);
+      }
+    ;
+
 program
     : package imports body
     ;
@@ -367,10 +396,39 @@
     ;
 
 const_expr
-    : INTEGER                   { $$ = new ConstantExpression($1, ConstantExpression::kConstExprLiteral); }
+    : INTEGER                   { $$ = new ConstantExpression($1); }
     | fqname
       {
-          $$ = new ConstantExpression($1->string().c_str(), ConstantExpression::kConstExprUnknown);
+          if(!$1->isValidValueName()) {
+              std::cerr << "ERROR: '" << $1->string()
+                        << "' does not refer to an enum value at "
+                        << @1 << ".\n";
+              YYERROR;
+          }
+          if($1->isIdentifier()) {
+              std::string identifier = $1->name();
+              LocalIdentifier *iden = ast->scope()->lookupIdentifier(identifier);
+              if(!iden) {
+                  std::cerr << "ERROR: at " << @1 << ", identifier " << $1
+                            << " could not be found.\n";
+                  YYERROR;
+              }
+              if(!iden->isEnumValue()) {
+                  std::cerr << "ERROR: at " << @1 << ", identifier " << $1
+                            << " is not an enum value.\n";
+                  YYERROR;
+              }
+              $$ = new ConstantExpression(
+                      *(static_cast<EnumValue *>(iden)->constExpr()), $1->string());
+          } else {
+              std::string errorMsg;
+              EnumValue *v = ast->lookupEnumValue(*($1), &errorMsg);
+              if(v == nullptr) {
+                  std::cerr << "ERROR: " << errorMsg << " at " << @1 << ".\n";
+                  YYERROR;
+              }
+              $$ = new ConstantExpression(*(v->constExpr()), $1->string());
+          }
       }
     | const_expr '?' const_expr ':' const_expr
       {
@@ -544,9 +602,14 @@
     ;
 
 named_enum_declaration
-    : ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
+    : ENUM IDENTIFIER opt_storage_type
       {
-          EnumType *enumType = new EnumType($2, $5, $3);
+          ast->enterScope(new EnumType($2, $3));
+      }
+      enum_declaration_body
+      {
+          EnumType *enumType = static_cast<EnumType *>(ast->scope());
+          ast->leaveScope();
 
           std::string errorMsg;
           if (!ast->addScopedType(enumType, &errorMsg)) {
@@ -557,11 +620,16 @@
     ;
 
 enum_declaration
-    : ENUM '{' enum_values opt_comma '}'
+    : ENUM
       {
           std::string anonName = ast->scope()->pickUniqueAnonymousName();
+          ast->enterScope(new EnumType(anonName.c_str()));
+      }
+      enum_declaration_body
+      {
 
-          EnumType *enumType = new EnumType(anonName.c_str(), $3);
+          EnumType *enumType = static_cast<EnumType *>(ast->scope());
+          ast->leaveScope();
 
           std::string errorMsg;
           if (!ast->addScopedType(enumType, &errorMsg)) {
@@ -572,9 +640,14 @@
 
           $$ = enumType->ref();
       }
-    | ENUM IDENTIFIER opt_storage_type '{' enum_values opt_comma '}'
+    | ENUM IDENTIFIER opt_storage_type
       {
-          EnumType *enumType = new EnumType($2, $5, $3);
+          ast->enterScope(new EnumType($2, $3));
+      }
+      enum_declaration_body
+      {
+          EnumType *enumType = static_cast<EnumType *>(ast->scope());
+          ast->leaveScope();
 
           std::string errorMsg;
           if (!ast->addScopedType(enumType, &errorMsg)) {
@@ -586,6 +659,10 @@
       }
     ;
 
+enum_declaration_body
+    : '{' enum_values opt_comma '}' { $$ = $2; }
+    ;
+
 enum_value
     : IDENTIFIER { $$ = new EnumValue($1); }
     | IDENTIFIER '=' const_expr { $$ = new EnumValue($1, $3); }
@@ -593,24 +670,20 @@
 
 enum_values
     : /* empty */
-      {
-          $$ = new std::vector<EnumValue *>;
-      }
+      { /* do nothing */ }
     | enum_value
       {
-          $$ = new std::vector<EnumValue *>;
-          $$->push_back($1);
+          static_cast<EnumType *>(ast->scope())->addValue($1);
       }
     | enum_values ',' enum_value
       {
-          $$ = $1;
-          $$->push_back($3);
+          static_cast<EnumType *>(ast->scope())->addValue($3);
       }
     ;
 
 type
     : fqtype { $$ = $1; }
-    | fqtype '[' INTEGER ']'
+    | fqtype '[' const_expr ']'
       {
           if ($1->isBinder()) {
               std::cerr << "ERROR: Arrays of interface types are not supported."
@@ -619,14 +692,10 @@
               YYERROR;
           }
 
-          char *end;
-          unsigned long size = strtoul($3, &end, 10);
-          CHECK(end > $3 && *end == '\0');
-
           if ($1->isArray()) {
-              $$ = new ArrayType(static_cast<ArrayType *>($1), size);
+              $$ = new ArrayType(static_cast<ArrayType *>($1), $3);
           } else {
-              $$ = new ArrayType($1, size);
+              $$ = new ArrayType($1, $3);
           }
       }
     | VEC '<' fqtype '>'