1  /*
2   * Copyright (C) 2016 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 "EnumType.h"
18  
19  #include <hidl-util/Formatter.h>
20  #include <inttypes.h>
21  #include <iostream>
22  #include <string>
23  #include <unordered_map>
24  
25  #include "Annotation.h"
26  #include "Location.h"
27  #include "ScalarType.h"
28  
29  namespace android {
30  
EnumType(const std::string & localName,const FQName & fullName,const Location & location,const Reference<Type> & storageType,Scope * parent)31  EnumType::EnumType(const std::string& localName, const FQName& fullName, const Location& location,
32                     const Reference<Type>& storageType, Scope* parent)
33      : Scope(localName, fullName, location, parent), mValues(), mStorageType(storageType) {}
34  
storageType() const35  const Type *EnumType::storageType() const {
36      return mStorageType.get();
37  }
38  
values() const39  const std::vector<EnumValue *> &EnumType::values() const {
40      return mValues;
41  }
42  
forEachValueFromRoot(const std::function<void (const EnumValue *)> f) const43  void EnumType::forEachValueFromRoot(const std::function<void(const EnumValue*)> f) const {
44      std::vector<const EnumType*> chain = typeChain();
45      for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
46          const auto& type = *it;
47          for (const EnumValue* v : type->values()) {
48              f(v);
49          }
50      }
51  }
52  
numValueNames() const53  size_t EnumType::numValueNames() const {
54      size_t count = 0;
55      for (const auto it : typeChain()) {
56          count += it->values().size();
57      }
58      return count;
59  }
60  
addValue(EnumValue * value)61  void EnumType::addValue(EnumValue* value) {
62      CHECK(value != nullptr);
63      mValues.push_back(value);
64  }
65  
resolveInheritance()66  status_t EnumType::resolveInheritance() {
67      const EnumType* prevType = nullptr;
68      EnumValue* prevValue = nullptr;
69  
70      for (const auto* type : superTypeChain()) {
71          if (!type->values().empty()) {
72              prevType = type;
73              prevValue = type->values().back();
74              break;
75          }
76      }
77  
78      for (auto* value : mValues) {
79          value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
80          prevType = this;
81          prevValue = value;
82      }
83  
84      return Scope::resolveInheritance();
85  }
86  
getReferences() const87  std::vector<const Reference<Type>*> EnumType::getReferences() const {
88      return {&mStorageType};
89  }
90  
getConstantExpressions() const91  std::vector<const ConstantExpression*> EnumType::getConstantExpressions() const {
92      std::vector<const ConstantExpression*> ret;
93      for (const auto* value : mValues) {
94          ret.push_back(value->constExpr());
95      }
96      return ret;
97  }
98  
validate() const99  status_t EnumType::validate() const {
100      CHECK(getSubTypes().empty());
101  
102      if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
103          std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
104                    << ") specified at " << mStorageType.location() << "\n";
105          return UNKNOWN_ERROR;
106      }
107  
108      status_t err = validateUniqueNames();
109      if (err != OK) return err;
110  
111      return Scope::validate();
112  }
113  
validateAnnotations() const114  status_t EnumType::validateAnnotations() const {
115      for (const Annotation* annotation : annotations()) {
116          const std::string name = annotation->name();
117  
118          if (name == "export") {
119              continue;
120          }
121  
122          std::cerr << "WARNING: Unrecognized annotation '" << name << "' for " << typeName()
123                    << " at " << location() << ". Only @export is supported." << std::endl;
124          // This is a warning to avoid breaking downstream unnecessarily.
125          // return UNKNOWN_ERROR;
126      }
127      return OK;
128  }
129  
validateUniqueNames() const130  status_t EnumType::validateUniqueNames() const {
131      std::unordered_map<std::string, const EnumType*> registeredValueNames;
132      for (const auto* type : superTypeChain()) {
133          for (const auto* enumValue : type->mValues) {
134              // No need to check super value uniqueness
135              registeredValueNames[enumValue->name()] = type;
136          }
137      }
138  
139      for (const auto* value : mValues) {
140          auto registered = registeredValueNames.find(value->name());
141  
142          if (registered != registeredValueNames.end()) {
143              const EnumType* definedInType = registered->second;
144  
145              if (definedInType == this) {
146                  // Defined in this enum
147                  std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
148              } else {
149                  // Defined in super enum
150                  std::cerr << "ERROR: Redefinition of value '" << value->name()
151                            << "' defined in enum '" << definedInType->fullName() << "'";
152              }
153              std::cerr << " at " << value->location() << "\n";
154              return UNKNOWN_ERROR;
155          }
156  
157          registeredValueNames[value->name()] = this;
158      }
159  
160      return OK;
161  }
162  
isElidableType() const163  bool EnumType::isElidableType() const {
164      return mStorageType->isElidableType();
165  }
166  
resolveToScalarType() const167  const ScalarType *EnumType::resolveToScalarType() const {
168      return mStorageType->resolveToScalarType();
169  }
170  
typeName() const171  std::string EnumType::typeName() const {
172      return "enum " + definedName();
173  }
174  
isEnum() const175  bool EnumType::isEnum() const {
176      return true;
177  }
178  
deepCanCheckEquality(std::unordered_set<const Type * > *) const179  bool EnumType::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
180      return true;
181  }
182  
getCppType(StorageMode,bool) const183  std::string EnumType::getCppType(StorageMode,
184                                   bool /* specifyNamespaces */) const {
185      return fullName();
186  }
187  
getJavaType(bool forInitializer) const188  std::string EnumType::getJavaType(bool forInitializer) const {
189      return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
190  }
191  
getJavaSuffix() const192  std::string EnumType::getJavaSuffix() const {
193      return mStorageType->resolveToScalarType()->getJavaSuffix();
194  }
195  
getJavaTypeClass() const196  std::string EnumType::getJavaTypeClass() const {
197      return mStorageType->resolveToScalarType()->getJavaTypeClass();
198  }
199  
getVtsType() const200  std::string EnumType::getVtsType() const {
201      return "TYPE_ENUM";
202  }
203  
getBitfieldCppType(StorageMode,bool specifyNamespaces) const204  std::string EnumType::getBitfieldCppType(StorageMode /* mode */, bool specifyNamespaces) const {
205      const std::string space = specifyNamespaces ? "::android::hardware::" : "";
206      return space + "hidl_bitfield<" + (specifyNamespaces ? fullName() : definedName()) + ">";
207  }
208  
getBitfieldJavaType(bool forInitializer) const209  std::string EnumType::getBitfieldJavaType(bool forInitializer) const {
210      return resolveToScalarType()->getJavaType(forInitializer);
211  }
212  
getBitfieldJavaTypeClass() const213  std::string EnumType::getBitfieldJavaTypeClass() const {
214      return resolveToScalarType()->getJavaTypeClass();
215  }
216  
lookupIdentifier(const std::string & name) const217  LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
218      std::vector<const EnumType*> chain = typeChain();
219      for (auto it = chain.begin(); it != chain.end(); ++it) {
220          const auto &type = *it;
221          for(EnumValue *v : type->values()) {
222              if(v->name() == name) {
223                  return v;
224              }
225          }
226      }
227      return nullptr;
228  }
229  
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const230  void EnumType::emitJavaFieldInitializer(Formatter& out, const std::string& fieldName) const {
231      mStorageType->resolveToScalarType()->emitJavaFieldInitializer(out, fieldName);
232  }
233  
emitJavaFieldDefaultInitialValue(Formatter & out,const std::string & fieldName) const234  void EnumType::emitJavaFieldDefaultInitialValue(Formatter& out,
235                                                  const std::string& fieldName) const {
236      mStorageType->resolveToScalarType()->emitJavaFieldDefaultInitialValue(out, fieldName);
237  }
238  
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const239  void EnumType::emitReaderWriter(
240          Formatter &out,
241          const std::string &name,
242          const std::string &parcelObj,
243          bool parcelObjIsPointer,
244          bool isReader,
245          ErrorMode mode) const {
246      const ScalarType *scalarType = mStorageType->resolveToScalarType();
247      CHECK(scalarType != nullptr);
248  
249      scalarType->emitReaderWriterWithCast(
250              out,
251              name,
252              parcelObj,
253              parcelObjIsPointer,
254              isReader,
255              mode,
256              true /* needsCast */);
257  }
258  
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const259  void EnumType::emitJavaFieldReaderWriter(
260          Formatter &out,
261          size_t depth,
262          const std::string &parcelName,
263          const std::string &blobName,
264          const std::string &fieldName,
265          const std::string &offset,
266          bool isReader) const {
267      return mStorageType->emitJavaFieldReaderWriter(
268              out, depth, parcelName, blobName, fieldName, offset, isReader);
269  }
270  
emitHidlDefinition(Formatter & out) const271  void EnumType::emitHidlDefinition(Formatter& out) const {
272      if (getDocComment() != nullptr) getDocComment()->emit(out);
273  
274      if (annotations().size() != 0) {
275          out.join(annotations().begin(), annotations().end(), " ",
276                   [&](auto annotation) { annotation->dump(out); });
277          out << "\n";
278      }
279  
280      out << typeName() << " : " << mStorageType.localName() << " {\n";
281  
282      out.indent([&] {
283          for (const EnumValue* val : mValues) {
284              if (val->getDocComment() != nullptr) val->getDocComment()->emit(out);
285              out << val->name();
286              if (!val->isAutoFill()) {
287                  out << " = " << val->constExpr()->expression();
288              }
289              out << ",\n";
290          }
291      });
292  
293      out << "};\n";
294  }
295  
emitTypeDeclarations(Formatter & out) const296  void EnumType::emitTypeDeclarations(Formatter& out) const {
297      const ScalarType *scalarType = mStorageType->resolveToScalarType();
298      CHECK(scalarType != nullptr);
299  
300      const std::string storageType = scalarType->getCppStackType();
301  
302      out << "enum class " << definedName() << " : " << storageType << " {\n";
303  
304      out.indent();
305  
306      std::vector<const EnumType*> chain = typeChain();
307  
308      for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
309          const auto &type = *it;
310  
311          for (const auto &entry : type->values()) {
312              auto name = entry->name();
313  
314              // The math.h header defines a NAN macro that breaks that declaration of a NAN
315              // enumerator in the wifi HAL. Undefine that macro before declaring the enumerator.
316              // This change strictly improves the situation, because the enum won't compile if the
317              // NAN macro is defined. It does not fix attempts to use NAN, because the include order
318              // of math.h versus a HIDL header determines which NAN is declared. Code that wants to
319              // use the wifi NAN may still need to #undef the math.h macro. This special handling
320              // only happens for NAN, because we might want to diagnose other macro<->enum conflicts.
321              if (name == "NAN") {
322                  out << "#undef NAN // avoid conflict with math.h NAN\n";
323              }
324              // The same hack is also needed for math.h OVERFLOW.
325              if (name == "OVERFLOW") {
326                  out << "#undef OVERFLOW // avoid conflict with math.h OVERFLOW\n";
327              }
328  
329              entry->emitDocComment(out);
330  
331              out << name;
332  
333              std::string value = entry->cppValue(scalarType->getKind());
334              CHECK(!value.empty()); // use autofilled values for c++.
335              out << " = " << value << ",\n";
336          }
337      }
338  
339      out.unindent();
340      out << "};\n\n";
341  }
342  
emitTypeForwardDeclaration(Formatter & out) const343  void EnumType::emitTypeForwardDeclaration(Formatter& out) const {
344      const ScalarType* scalarType = mStorageType->resolveToScalarType();
345      const std::string storageType = scalarType->getCppStackType();
346  
347      out << "enum class " << definedName() << " : " << storageType << ";\n";
348  }
349  
emitIteratorDeclaration(Formatter & out) const350  void EnumType::emitIteratorDeclaration(Formatter& out) const {
351      size_t elementCount = 0;
352      for (const auto* type : typeChain()) {
353          elementCount += type->mValues.size();
354      }
355  
356      // TODO(pcc): Remove the pragmas once all users of the hidl headers have
357      // been moved to C++17.
358      out << "#pragma clang diagnostic push\n";
359      out << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
360  
361      out << "template<> inline constexpr std::array<" << getCppStackType() << ", " << elementCount
362          << "> hidl_enum_values<" << getCppStackType() << "> = ";
363      out.block([&] {
364          auto enumerators = typeChain();
365          std::reverse(enumerators.begin(), enumerators.end());
366          for (const auto* type : enumerators) {
367              for (const auto* enumValue : type->mValues) {
368                  out << fullName() << "::" << enumValue->name() << ",\n";
369              }
370          }
371      }) << ";\n";
372  
373      out << "#pragma clang diagnostic pop\n";
374  }
375  
emitEnumBitwiseOperator(Formatter & out,bool lhsIsEnum,bool rhsIsEnum,const std::string & op) const376  void EnumType::emitEnumBitwiseOperator(
377          Formatter &out,
378          bool lhsIsEnum,
379          bool rhsIsEnum,
380          const std::string &op) const {
381      const ScalarType *scalarType = mStorageType->resolveToScalarType();
382      CHECK(scalarType != nullptr);
383  
384      const std::string storageType = scalarType->getCppStackType();
385  
386      out << "constexpr "
387          << storageType
388          << " operator"
389          << op
390          << "(const "
391          << (lhsIsEnum ? fullName() : storageType)
392          << " lhs, const "
393          << (rhsIsEnum ? fullName() : storageType)
394          << " rhs) {\n";
395  
396      out.indent([&] {
397          out << "return static_cast<"
398              << storageType
399              << ">(";
400  
401          if (lhsIsEnum) {
402              out << "static_cast<"
403                  << storageType
404                  << ">(lhs)";
405          } else {
406              out << "lhs";
407          }
408          out << " " << op << " ";
409          if (rhsIsEnum) {
410              out << "static_cast<"
411                  << storageType
412                  << ">(rhs)";
413          } else {
414              out << "rhs";
415          }
416          out << ");\n";
417      });
418  
419      out << "}\n";
420  }
421  
emitBitFieldBitwiseAssignmentOperator(Formatter & out,const std::string & op) const422  void EnumType::emitBitFieldBitwiseAssignmentOperator(
423          Formatter &out,
424          const std::string &op) const {
425      const ScalarType *scalarType = mStorageType->resolveToScalarType();
426      CHECK(scalarType != nullptr);
427  
428      const std::string storageType = scalarType->getCppStackType();
429  
430      out << "constexpr " << storageType << " &operator" << op << "=("
431          << storageType << "& v, const " << fullName() << " e) {\n";
432  
433      out.indent([&] {
434          out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
435          out << "return v;\n";
436      });
437  
438      out << "}\n";
439  }
440  
emitGlobalTypeDeclarations(Formatter & out) const441  void EnumType::emitGlobalTypeDeclarations(Formatter& out) const {
442      out << "namespace android {\n";
443      out << "namespace hardware {\n";
444      out << "namespace details {\n";
445  
446      emitIteratorDeclaration(out);
447  
448      out << "}  // namespace details\n";
449      out << "}  // namespace hardware\n";
450      out << "}  // namespace android\n\n";
451  }
452  
emitPackageTypeDeclarations(Formatter & out) const453  void EnumType::emitPackageTypeDeclarations(Formatter& out) const {
454      out << "template<typename>\n"
455          << "static inline std::string toString(" << resolveToScalarType()->getCppArgumentType()
456          << " o);\n";
457      out << "static inline std::string toString(" << getCppArgumentType() << " o);\n";
458      out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os);\n";
459  
460      emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
461      emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
462      emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
463      emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
464      emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
465      emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
466  
467      emitBitFieldBitwiseAssignmentOperator(out, "|");
468      emitBitFieldBitwiseAssignmentOperator(out, "&");
469  
470      out.endl();
471  }
472  
emitPackageTypeHeaderDefinitions(Formatter & out) const473  void EnumType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
474      const ScalarType *scalarType = mStorageType->resolveToScalarType();
475      CHECK(scalarType != nullptr);
476  
477      out << "template<>\n"
478          << "inline std::string toString<" << getCppStackType() << ">("
479          << scalarType->getCppArgumentType() << " o) ";
480      out.block([&] {
481          // include toHexString for scalar types
482          out << "using ::android::hardware::details::toHexString;\n"
483              << "std::string os;\n"
484              << getBitfieldCppType(StorageMode_Stack) << " flipped = 0;\n"
485              << "bool first = true;\n";
486          forEachValueFromRoot([&](const EnumValue* value) {
487              std::string valueName = fullName() + "::" + value->name();
488              out.sIf("(o & " + valueName + ")" +
489                      " == static_cast<" + scalarType->getCppStackType() +
490                      ">(" + valueName + ")", [&] {
491                  out << "os += (first ? \"\" : \" | \");\n"
492                      << "os += \"" << value->name() << "\";\n"
493                      << "first = false;\n"
494                      << "flipped |= " << valueName << ";\n";
495              }).endl();
496          });
497          // put remaining bits
498          out.sIf("o != flipped", [&] {
499              out << "os += (first ? \"\" : \" | \");\n";
500              scalarType->emitHexDump(out, "os", "o & (~flipped)");
501          });
502          out << "os += \" (\";\n";
503          scalarType->emitHexDump(out, "os", "o");
504          out << "os += \")\";\n";
505  
506          out << "return os;\n";
507      }).endl().endl();
508  
509      out << "static inline std::string toString(" << getCppArgumentType() << " o) ";
510  
511      out.block([&] {
512          out << "using ::android::hardware::details::toHexString;\n";
513          forEachValueFromRoot([&](const EnumValue* value) {
514              out.sIf("o == " + fullName() + "::" + value->name(), [&] {
515                  out << "return \"" << value->name() << "\";\n";
516              }).endl();
517          });
518          out << "std::string os;\n";
519          scalarType->emitHexDump(out, "os",
520              "static_cast<" + scalarType->getCppStackType() + ">(o)");
521          out << "return os;\n";
522      }).endl().endl();
523  
524      out << "static inline void PrintTo(" << getCppArgumentType() << " o, ::std::ostream* os) ";
525  
526      out.block([&] { out << "*os << toString(o);\n"; }).endl().endl();
527  }
528  
emitJavaTypeDeclarations(Formatter & out,bool atTopLevel) const529  void EnumType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
530      const ScalarType *scalarType = mStorageType->resolveToScalarType();
531      CHECK(scalarType != nullptr);
532  
533      out << "public " << (atTopLevel ? "" : "static ") << "final class " << definedName() << " {\n";
534  
535      out.indent();
536  
537      const std::string typeName =
538          scalarType->getJavaType(false /* forInitializer */);
539  
540      std::vector<const EnumType*> chain = typeChain();
541  
542      for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
543          const auto &type = *it;
544  
545          for (const auto &entry : type->values()) {
546              entry->emitDocComment(out);
547  
548              out << "public static final "
549                  << typeName
550                  << " "
551                  << entry->name()
552                  << " = ";
553  
554              // javaValue will make the number signed.
555              std::string value = entry->javaValue(scalarType->getKind());
556              CHECK(!value.empty()); // use autofilled values for java.
557              out << value << ";\n";
558          }
559      }
560  
561      out << "public static final String toString("
562          << typeName << " o) ";
563      out.block([&] {
564          forEachValueFromRoot([&](const EnumValue* value) {
565              out.sIf("o == " + value->name(), [&] {
566                  out << "return \"" << value->name() << "\";\n";
567              }).endl();
568          });
569          out << "return \"0x\" + ";
570          scalarType->emitConvertToJavaHexString(out, "o");
571          out << ";\n";
572      }).endl();
573  
574      auto bitfieldType = getBitfieldJavaType(false /* forInitializer */);
575      out << "\n"
576          << "public static final String dumpBitfield("
577          << bitfieldType << " o) ";
578      out.block([&] {
579          out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
580          out << bitfieldType << " flipped = 0;\n";
581          forEachValueFromRoot([&](const EnumValue* value) {
582              if (value->constExpr()->castSizeT() == 0) {
583                  out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
584                  return;  // continue to next value
585              }
586              out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
587                  out << "list.add(\"" << value->name() << "\");\n";
588                  out << "flipped |= " << value->name() << ";\n";
589              }).endl();
590          });
591          // put remaining bits
592          out.sIf("o != flipped", [&] {
593              out << "list.add(\"0x\" + ";
594              scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
595              out << ");\n";
596          }).endl();
597          out << "return String.join(\" | \", list);\n";
598      }).endl().endl();
599  
600      out.unindent();
601      out << "};\n\n";
602  }
603  
emitVtsTypeDeclarations(Formatter & out) const604  void EnumType::emitVtsTypeDeclarations(Formatter& out) const {
605      const ScalarType *scalarType = mStorageType->resolveToScalarType();
606  
607      out << "name: \"" << fullName() << "\"\n";
608      out << "type: " << getVtsType() << "\n";
609      out << "enum_value: {\n";
610      out.indent();
611  
612      out << "scalar_type: \""
613          << scalarType->getVtsScalarType()
614          << "\"\n\n";
615      std::vector<const EnumType*> chain = typeChain();
616  
617      for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
618          const auto &type = *it;
619  
620          for (const auto &entry : type->values()) {
621              out << "enumerator: \"" << entry->name() << "\"\n";
622              out << "scalar_value: {\n";
623              out.indent();
624              // use autofilled values for vts.
625              std::string value = entry->rawValue(scalarType->getKind());
626              CHECK(!value.empty());
627              out << mStorageType->resolveToScalarType()->getVtsScalarType()
628                  << ": "
629                  << value
630                  << "\n";
631              out.unindent();
632              out << "}\n";
633          }
634      }
635  
636      out.unindent();
637      out << "}\n";
638  }
639  
emitVtsAttributeType(Formatter & out) const640  void EnumType::emitVtsAttributeType(Formatter& out) const {
641      out << "type: " << getVtsType() << "\n";
642      out << "predefined_type: \"" << fullName() << "\"\n";
643  }
644  
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const645  void EnumType::emitJavaDump(
646          Formatter &out,
647          const std::string &streamName,
648          const std::string &name) const {
649      out << streamName << ".append(" << fqName().javaName() << ".toString("
650          << name << "));\n";
651  }
652  
typeChain() const653  std::vector<const EnumType*> EnumType::typeChain() const {
654      std::vector<const EnumType*> types;
655      for (const EnumType* type = this; type != nullptr;) {
656          types.push_back(type);
657  
658          const Type* superType = type->storageType();
659          if (superType != nullptr && superType->isEnum()) {
660              type = static_cast<const EnumType*>(superType);
661          } else {
662              type = nullptr;
663          }
664      }
665  
666      return types;
667  }
668  
superTypeChain() const669  std::vector<const EnumType*> EnumType::superTypeChain() const {
670      const Type* superType = storageType();
671      if (superType == nullptr || !superType->isEnum()) {
672          return {};
673      }
674      return static_cast<const EnumType*>(superType)->typeChain();
675  }
676  
getAlignmentAndSize(size_t * align,size_t * size) const677  void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
678      mStorageType->getAlignmentAndSize(align, size);
679  }
680  
findExportAnnotation() const681  const Annotation *EnumType::findExportAnnotation() const {
682      for (const auto &annotation : annotations()) {
683          if (annotation->name() == "export") {
684              return annotation;
685          }
686      }
687  
688      return nullptr;
689  }
690  
appendToExportedTypesVector(std::vector<const Type * > * exportedTypes) const691  void EnumType::appendToExportedTypesVector(
692          std::vector<const Type *> *exportedTypes) const {
693      if (findExportAnnotation() != nullptr) {
694          exportedTypes->push_back(this);
695      }
696  }
697  
emitExportedHeader(Formatter & out,bool forJava) const698  void EnumType::emitExportedHeader(Formatter& out, bool forJava) const {
699      const Annotation *annotation = findExportAnnotation();
700      CHECK(annotation != nullptr);
701  
702      std::string name = definedName();
703  
704      const AnnotationParam *nameParam = annotation->getParam("name");
705      if (nameParam != nullptr) {
706          name = nameParam->getSingleString();
707      }
708  
709      bool exportParent = true;
710      const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
711      if (exportParentParam != nullptr) {
712          exportParent = exportParentParam->getSingleBool();
713      }
714  
715      std::string valuePrefix;
716      const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
717      if (prefixParam != nullptr) {
718          valuePrefix = prefixParam->getSingleString();
719      }
720  
721      std::string valueSuffix;
722      const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
723      if (suffixParam != nullptr) {
724          valueSuffix = suffixParam->getSingleString();
725      }
726  
727      const ScalarType *scalarType = mStorageType->resolveToScalarType();
728      CHECK(scalarType != nullptr);
729  
730      std::vector<const EnumType *> chain;
731      if (exportParent) {
732          chain = typeChain();
733      } else {
734          chain = { this };
735      }
736  
737      if (forJava) {
738          if (!name.empty()) {
739              out << "public final class "
740                  << name
741                  << " {\n";
742  
743              out.indent();
744          } else {
745              out << "// Values declared in " << definedName() << " follow.\n";
746          }
747  
748          const std::string typeName =
749              scalarType->getJavaType(false /* forInitializer */);
750  
751          for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
752              const auto &type = *it;
753  
754              for (const auto &entry : type->values()) {
755                  out << "public static final "
756                      << typeName
757                      << " "
758                      << valuePrefix
759                      << entry->name()
760                      << valueSuffix
761                      << " = ";
762  
763                  // javaValue will make the number signed.
764                  std::string value = entry->javaValue(scalarType->getKind());
765                  CHECK(!value.empty()); // use autofilled values for java.
766                  out << value << ";\n";
767              }
768          }
769  
770          if (!name.empty()) {
771              out.unindent();
772              out << "};\n";
773          }
774          out << "\n";
775  
776          return;
777      }
778  
779      if (!name.empty()) {
780          out << "typedef ";
781      }
782  
783      out << "enum {\n";
784  
785      out.indent();
786  
787      for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
788          const auto &type = *it;
789  
790          for (const auto &entry : type->values()) {
791              out << valuePrefix << entry->name() << valueSuffix;
792  
793              std::string value = entry->cppValue(scalarType->getKind());
794              CHECK(!value.empty()); // use autofilled values for c++.
795              out << " = " << value << ",\n";
796          }
797      }
798  
799      out.unindent();
800      out << "}";
801  
802      if (!name.empty()) {
803          out << " " << name;
804      }
805  
806      out << ";\n\n";
807  }
808  
809  ////////////////////////////////////////////////////////////////////////////////
810  
EnumValue(const std::string & name,ConstantExpression * value,const Location & location)811  EnumValue::EnumValue(const std::string& name, ConstantExpression* value, const Location& location)
812      : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
813  
name() const814  std::string EnumValue::name() const {
815      return mName;
816  }
817  
rawValue(ScalarType::Kind castKind) const818  std::string EnumValue::rawValue(ScalarType::Kind castKind) const {
819      CHECK(mValue != nullptr);
820      return mValue->rawValue(castKind);
821  }
822  
cppValue(ScalarType::Kind castKind) const823  std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
824      CHECK(mValue != nullptr);
825      return mValue->cppValue(castKind);
826  }
javaValue(ScalarType::Kind castKind) const827  std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
828      CHECK(mValue != nullptr);
829      return mValue->javaValue(castKind);
830  }
831  
constExpr() const832  ConstantExpression *EnumValue::constExpr() const {
833      CHECK(mValue != nullptr);
834      return mValue;
835  }
836  
autofill(const EnumType * prevType,EnumValue * prevValue,const ScalarType * type)837  void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
838      // Value is defined explicitly
839      if (mValue != nullptr) return;
840  
841      CHECK((prevType == nullptr) == (prevValue == nullptr));
842  
843      mIsAutoFill = true;
844      if (prevValue == nullptr) {
845          mValue = ConstantExpression::Zero(type->getKind()).release();
846      } else {
847          std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
848          auto* prevReference = new ReferenceConstantExpression(
849                  Reference<LocalIdentifier>(prevValue->mName, prevValue, mLocation), description);
850          mValue = prevReference->addOne(type->getKind()).release();
851      }
852  }
853  
isAutoFill() const854  bool EnumValue::isAutoFill() const {
855      return mIsAutoFill;
856  }
857  
isEnumValue() const858  bool EnumValue::isEnumValue() const {
859      return true;
860  }
861  
location() const862  const Location& EnumValue::location() const {
863      return mLocation;
864  }
865  
866  ////////////////////////////////////////////////////////////////////////////////
867  
BitFieldType(Scope * parent)868  BitFieldType::BitFieldType(Scope* parent) : TemplatedType(parent, "bitfield") {}
869  
isBitField() const870  bool BitFieldType::isBitField() const {
871      return true;
872  }
873  
getElementEnumType() const874  const EnumType* BitFieldType::getElementEnumType() const {
875      CHECK(mElementType.get() != nullptr && mElementType->isEnum());
876      return static_cast<const EnumType*>(mElementType.get());
877  }
878  
templatedTypeName() const879  std::string BitFieldType::templatedTypeName() const {
880      return "mask";
881  }
882  
isCompatibleElementType(const Type * elementType) const883  bool BitFieldType::isCompatibleElementType(const Type* elementType) const {
884      return elementType->isEnum();
885  }
886  
resolveToScalarType() const887  const ScalarType *BitFieldType::resolveToScalarType() const {
888      return mElementType->resolveToScalarType();
889  }
890  
getCppType(StorageMode mode,bool specifyNamespaces) const891  std::string BitFieldType::getCppType(StorageMode mode,
892                                   bool specifyNamespaces) const {
893      return getElementEnumType()->getBitfieldCppType(mode, specifyNamespaces);
894  }
895  
getJavaType(bool forInitializer) const896  std::string BitFieldType::getJavaType(bool forInitializer) const {
897      return getElementEnumType()->getBitfieldJavaType(forInitializer);
898  }
899  
getJavaSuffix() const900  std::string BitFieldType::getJavaSuffix() const {
901      return resolveToScalarType()->getJavaSuffix();
902  }
903  
getJavaTypeClass() const904  std::string BitFieldType::getJavaTypeClass() const {
905      return getElementEnumType()->getBitfieldJavaTypeClass();
906  }
907  
getVtsType() const908  std::string BitFieldType::getVtsType() const {
909      return "TYPE_MASK";
910  }
911  
isElidableType() const912  bool BitFieldType::isElidableType() const {
913      return resolveToScalarType()->isElidableType();
914  }
915  
deepCanCheckEquality(std::unordered_set<const Type * > * visited) const916  bool BitFieldType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
917      return resolveToScalarType()->canCheckEquality(visited);
918  }
919  
emitVtsAttributeType(Formatter & out) const920  void BitFieldType::emitVtsAttributeType(Formatter& out) const {
921      out << "type: " << getVtsType() << "\n";
922      out << "scalar_type: \""
923          << mElementType->resolveToScalarType()->getVtsScalarType()
924          << "\"\n";
925      out << "predefined_type: \"" << static_cast<const NamedType*>(mElementType.get())->fullName()
926          << "\"\n";
927  }
928  
getAlignmentAndSize(size_t * align,size_t * size) const929  void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
930      resolveToScalarType()->getAlignmentAndSize(align, size);
931  }
932  
emitReaderWriter(Formatter & out,const std::string & name,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode) const933  void BitFieldType::emitReaderWriter(
934          Formatter &out,
935          const std::string &name,
936          const std::string &parcelObj,
937          bool parcelObjIsPointer,
938          bool isReader,
939          ErrorMode mode) const {
940      resolveToScalarType()->emitReaderWriterWithCast(
941              out,
942              name,
943              parcelObj,
944              parcelObjIsPointer,
945              isReader,
946              mode,
947              true /* needsCast */);
948  }
949  
getEnumType() const950  const EnumType* BitFieldType::getEnumType() const {
951      CHECK(mElementType->isEnum());
952      return static_cast<const EnumType*>(mElementType.get());
953  }
954  
955  // a bitfield maps to the underlying scalar type in C++, so operator<< is
956  // already defined. We can still emit useful information if the bitfield is
957  // in a struct / union by overriding emitDump as below.
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const958  void BitFieldType::emitDump(
959          Formatter &out,
960          const std::string &streamName,
961          const std::string &name) const {
962      out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
963          << "::toString<" << getEnumType()->getCppStackType()
964          << ">(" << name << ");\n";
965  }
966  
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const967  void BitFieldType::emitJavaDump(
968          Formatter &out,
969          const std::string &streamName,
970          const std::string &name) const {
971      out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
972          << name << "));\n";
973  }
974  
emitJavaFieldReaderWriter(Formatter & out,size_t depth,const std::string & parcelName,const std::string & blobName,const std::string & fieldName,const std::string & offset,bool isReader) const975  void BitFieldType::emitJavaFieldReaderWriter(
976          Formatter &out,
977          size_t depth,
978          const std::string &parcelName,
979          const std::string &blobName,
980          const std::string &fieldName,
981          const std::string &offset,
982          bool isReader) const {
983      return resolveToScalarType()->emitJavaFieldReaderWriter(
984              out, depth, parcelName, blobName, fieldName, offset, isReader);
985  }
986  
987  }  // namespace android
988  
989