• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "Type.h"
18 
19 #include "ConstantExpression.h"
20 #include "NamedType.h"
21 #include "ScalarType.h"
22 #include "Scope.h"
23 
24 #include <android-base/logging.h>
25 #include <hidl-util/Formatter.h>
26 #include <algorithm>
27 #include <iostream>
28 #include <string>
29 
30 namespace android {
31 
Type(Scope * parent,const std::string & definedName)32 Type::Type(Scope* parent, const std::string& definedName)
33     : mDefinedName(definedName), mParent(parent) {}
34 
~Type()35 Type::~Type() {}
36 
isScope() const37 bool Type::isScope() const {
38     return false;
39 }
40 
isInterface() const41 bool Type::isInterface() const {
42     return false;
43 }
44 
isScalar() const45 bool Type::isScalar() const {
46     return false;
47 }
48 
isString() const49 bool Type::isString() const {
50     return false;
51 }
52 
isEnum() const53 bool Type::isEnum() const {
54     return false;
55 }
56 
isBitField() const57 bool Type::isBitField() const {
58     return false;
59 }
60 
isHandle() const61 bool Type::isHandle() const {
62     return false;
63 }
64 
isTypeDef() const65 bool Type::isTypeDef() const {
66     return false;
67 }
68 
isNamedType() const69 bool Type::isNamedType() const {
70     return false;
71 }
72 
isMemory() const73 bool Type::isMemory() const {
74     return false;
75 }
76 
isCompoundType() const77 bool Type::isCompoundType() const {
78     return false;
79 }
80 
isArray() const81 bool Type::isArray() const {
82     return false;
83 }
84 
isVector() const85 bool Type::isVector() const {
86     return false;
87 }
88 
isTemplatedType() const89 bool Type::isTemplatedType() const {
90     return false;
91 }
92 
isPointer() const93 bool Type::isPointer() const {
94     return false;
95 }
96 
isFmq() const97 bool Type::isFmq() const {
98     return false;
99 }
100 
resolve()101 Type* Type::resolve() {
102     return const_cast<Type*>(static_cast<const Type*>(this)->resolve());
103 }
104 
resolve() const105 const Type* Type::resolve() const {
106     return this;
107 }
108 
getDefinedTypes()109 std::vector<Type*> Type::getDefinedTypes() {
110     const auto& constRet = static_cast<const Type*>(this)->getDefinedTypes();
111     std::vector<Type*> ret(constRet.size());
112     std::transform(constRet.begin(), constRet.end(), ret.begin(),
113                    [](const auto* type) { return const_cast<Type*>(type); });
114     return ret;
115 }
116 
getDefinedTypes() const117 std::vector<const Type*> Type::getDefinedTypes() const {
118     return {};
119 }
120 
getReferences()121 std::vector<Reference<Type>*> Type::getReferences() {
122     const auto& constRet = static_cast<const Type*>(this)->getReferences();
123     std::vector<Reference<Type>*> ret(constRet.size());
124     std::transform(constRet.begin(), constRet.end(), ret.begin(),
125                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
126     return ret;
127 }
128 
getReferences() const129 std::vector<const Reference<Type>*> Type::getReferences() const {
130     return {};
131 }
132 
getConstantExpressions()133 std::vector<ConstantExpression*> Type::getConstantExpressions() {
134     const auto& constRet = static_cast<const Type*>(this)->getConstantExpressions();
135     std::vector<ConstantExpression*> ret(constRet.size());
136     std::transform(constRet.begin(), constRet.end(), ret.begin(),
137                    [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
138     return ret;
139 }
140 
getConstantExpressions() const141 std::vector<const ConstantExpression*> Type::getConstantExpressions() const {
142     return {};
143 }
144 
getStrongReferences()145 std::vector<Reference<Type>*> Type::getStrongReferences() {
146     const auto& constRet = static_cast<const Type*>(this)->getStrongReferences();
147     std::vector<Reference<Type>*> ret(constRet.size());
148     std::transform(constRet.begin(), constRet.end(), ret.begin(),
149                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
150     return ret;
151 }
152 
getStrongReferences() const153 std::vector<const Reference<Type>*> Type::getStrongReferences() const {
154     std::vector<const Reference<Type>*> ret;
155     for (const auto* ref : getReferences()) {
156         if (!ref->shallowGet()->isNeverStrongReference()) {
157             ret.push_back(ref);
158         }
159     }
160     return ret;
161 }
162 
recursivePass(ParseStage stage,const std::function<status_t (Type *)> & func,std::unordered_set<const Type * > * visited)163 status_t Type::recursivePass(ParseStage stage, const std::function<status_t(Type*)>& func,
164                              std::unordered_set<const Type*>* visited) {
165     if (mParseStage > stage) return OK;
166     if (mParseStage < stage) return UNKNOWN_ERROR;
167 
168     if (visited->find(this) != visited->end()) return OK;
169     visited->insert(this);
170 
171     status_t err = func(this);
172     if (err != OK) return err;
173 
174     for (auto* nextType : getDefinedTypes()) {
175         err = nextType->recursivePass(stage, func, visited);
176         if (err != OK) return err;
177     }
178 
179     for (auto* nextRef : getReferences()) {
180         err = nextRef->shallowGet()->recursivePass(stage, func, visited);
181         if (err != OK) return err;
182     }
183 
184     return OK;
185 }
186 
recursivePass(ParseStage stage,const std::function<status_t (const Type *)> & func,std::unordered_set<const Type * > * visited) const187 status_t Type::recursivePass(ParseStage stage, const std::function<status_t(const Type*)>& func,
188                              std::unordered_set<const Type*>* visited) const {
189     if (mParseStage > stage) return OK;
190     if (mParseStage < stage) return UNKNOWN_ERROR;
191 
192     if (visited->find(this) != visited->end()) return OK;
193     visited->insert(this);
194 
195     status_t err = func(this);
196     if (err != OK) return err;
197 
198     for (const auto* nextType : getDefinedTypes()) {
199         err = nextType->recursivePass(stage, func, visited);
200         if (err != OK) return err;
201     }
202 
203     for (const auto* nextRef : getReferences()) {
204         err = nextRef->shallowGet()->recursivePass(stage, func, visited);
205         if (err != OK) return err;
206     }
207 
208     return OK;
209 }
210 
resolveInheritance()211 status_t Type::resolveInheritance() {
212     return OK;
213 }
214 
validate() const215 status_t Type::validate() const {
216     return OK;
217 }
218 
CheckAcyclicStatus(status_t status,const Type * cycleEnd)219 Type::CheckAcyclicStatus::CheckAcyclicStatus(status_t status, const Type* cycleEnd)
220     : status(status), cycleEnd(cycleEnd) {
221     CHECK(cycleEnd == nullptr || status != OK);
222 }
223 
topologicalOrder(std::unordered_map<const Type *,size_t> * reversedOrder,std::unordered_set<const Type * > * stack) const224 Type::CheckAcyclicStatus Type::topologicalOrder(
225     std::unordered_map<const Type*, size_t>* reversedOrder,
226     std::unordered_set<const Type*>* stack) const {
227     if (stack->find(this) != stack->end()) {
228         std::cerr << "ERROR: Cyclic declaration:\n";
229         return CheckAcyclicStatus(UNKNOWN_ERROR, this);
230     }
231 
232     if (reversedOrder->find(this) != reversedOrder->end()) return CheckAcyclicStatus(OK);
233     stack->insert(this);
234 
235     for (const auto* nextType : getDefinedTypes()) {
236         auto err = nextType->topologicalOrder(reversedOrder, stack);
237 
238         if (err.status != OK) {
239             if (err.cycleEnd == nullptr) return err;
240 
241             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "'";
242             if (nextType->isNamedType()) {
243                 std::cerr << " at " << static_cast<const NamedType*>(nextType)->location();
244             }
245             std::cerr << "\n";
246 
247             if (err.cycleEnd == this) {
248                 return CheckAcyclicStatus(err.status);
249             }
250             return err;
251         }
252     }
253 
254     for (const auto* nextRef : getStrongReferences()) {
255         const auto* nextType = nextRef->shallowGet();
256         auto err = nextType->topologicalOrder(reversedOrder, stack);
257 
258         if (err.status != OK) {
259             if (err.cycleEnd == nullptr) return err;
260 
261             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "' at "
262                       << nextRef->location() << "\n";
263 
264             if (err.cycleEnd == this) {
265                 return CheckAcyclicStatus(err.status);
266             }
267             return err;
268         }
269     }
270 
271     CHECK(stack->find(this) != stack->end());
272     stack->erase(this);
273 
274     CHECK(reversedOrder->find(this) == reversedOrder->end());
275     // Do not call insert and size in one statement to not rely on
276     // evaluation order.
277     size_t index = reversedOrder->size();
278     reversedOrder->insert({this, index});
279 
280     return CheckAcyclicStatus(OK);
281 }
282 
checkForwardReferenceRestrictions(const Reference<Type> & ref) const283 status_t Type::checkForwardReferenceRestrictions(const Reference<Type>& ref) const {
284     const Location& refLoc = ref.location();
285     const Type* refType = ref.shallowGet();
286 
287     // Not NamedTypes are avaiable everywhere.
288     // Only ArrayType and TemplatedType contain additional types in
289     // their reference (which is actually a part of type definition),
290     // so they are proceeded in this case.
291     //
292     // If we support named templated types one day, we will need to change
293     // this logic.
294     if (!refType->isNamedType()) {
295         for (const Reference<Type>* innerRef : refType->getReferences()) {
296             status_t err = checkForwardReferenceRestrictions(*innerRef);
297             if (err != OK) return err;
298         }
299         return OK;
300     }
301 
302     const Location& typeLoc = static_cast<const NamedType*>(refType)->location();
303 
304     // If referenced type is declared in another file or before reference,
305     // there is no forward reference here.
306     if (!Location::inSameFile(refLoc, typeLoc) ||
307         (!Location::intersect(refLoc, typeLoc) && typeLoc < refLoc)) {
308         return OK;
309     }
310 
311     // Type must be declared somewhere in the current stack to make it
312     // available for forward referencing.
313     const Type* refTypeParent = refType->parent();
314     for (const Type* ancestor = this; ancestor != nullptr; ancestor = ancestor->parent()) {
315         if (ancestor == refTypeParent) return OK;
316     }
317 
318     std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at " << ref.location()
319               << " is not supported.\n"
320               << "C++ forward declaration doesn't support inner types.\n";
321 
322     return UNKNOWN_ERROR;
323 }
324 
resolveToScalarType() const325 const ScalarType *Type::resolveToScalarType() const {
326     return nullptr;
327 }
328 
isValidEnumStorageType() const329 bool Type::isValidEnumStorageType() const {
330     const ScalarType *scalarType = resolveToScalarType();
331 
332     if (scalarType == nullptr) {
333         return false;
334     }
335 
336     return scalarType->isValidEnumStorageType();
337 }
338 
isElidableType() const339 bool Type::isElidableType() const {
340     return false;
341 }
342 
canCheckEquality() const343 bool Type::canCheckEquality() const {
344     std::unordered_set<const Type*> visited;
345     return canCheckEquality(&visited);
346 }
347 
canCheckEquality(std::unordered_set<const Type * > * visited) const348 bool Type::canCheckEquality(std::unordered_set<const Type*>* visited) const {
349     // See isJavaCompatible for similar structure.
350     if (visited->find(this) != visited->end()) {
351         return true;
352     }
353     visited->insert(this);
354     return deepCanCheckEquality(visited);
355 }
356 
deepCanCheckEquality(std::unordered_set<const Type * > *) const357 bool Type::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
358     return false;
359 }
360 
getParseStage() const361 Type::ParseStage Type::getParseStage() const {
362     return mParseStage;
363 }
364 
setParseStage(ParseStage stage)365 void Type::setParseStage(ParseStage stage) {
366     CHECK(mParseStage < stage);
367     mParseStage = stage;
368 }
369 
parent()370 Scope* Type::parent() {
371     return mParent;
372 }
373 
parent() const374 const Scope* Type::parent() const {
375     return mParent;
376 }
377 
definedName() const378 const std::string& Type::definedName() const {
379     return mDefinedName;
380 }
381 
getCppType(StorageMode,bool) const382 std::string Type::getCppType(StorageMode, bool) const {
383     CHECK(!"Should not be here") << typeName();
384     return std::string();
385 }
386 
decorateCppName(const std::string & name,StorageMode mode,bool specifyNamespaces) const387 std::string Type::decorateCppName(
388         const std::string &name, StorageMode mode, bool specifyNamespaces) const {
389     return getCppType(mode, specifyNamespaces) + " " + name;
390 }
391 
getJavaType(bool) const392 std::string Type::getJavaType(bool /* forInitializer */) const {
393     CHECK(!"Should not be here") << typeName();
394     return std::string();
395 }
396 
getJavaTypeClass() const397 std::string Type::getJavaTypeClass() const {
398     return getJavaType();
399 }
400 
getJavaTypeCast(const std::string & objName) const401 std::string Type::getJavaTypeCast(const std::string& objName) const {
402     return "(" + getJavaType() + ") " + objName;
403 }
404 
getJavaSuffix() const405 std::string Type::getJavaSuffix() const {
406     CHECK(!"Should not be here") << typeName();
407     return std::string();
408 }
409 
getVtsType() const410 std::string Type::getVtsType() const {
411     CHECK(!"Should not be here") << typeName();
412     return std::string();
413 }
414 
getVtsValueName() const415 std::string Type::getVtsValueName() const {
416     CHECK(!"Should not be here") << typeName();
417     return std::string();
418 }
419 
emitReaderWriter(Formatter &,const std::string &,const std::string &,bool,bool,ErrorMode) const420 void Type::emitReaderWriter(
421         Formatter &,
422         const std::string &,
423         const std::string &,
424         bool,
425         bool,
426         ErrorMode) const {
427     CHECK(!"Should not be here") << typeName();
428 }
429 
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const430 void Type::emitDump(
431         Formatter &out,
432         const std::string &streamName,
433         const std::string &name) const {
434     emitDumpWithMethod(out, streamName, "::android::hardware::toString", name);
435 }
436 
emitDumpWithMethod(Formatter & out,const std::string & streamName,const std::string & methodName,const std::string & name) const437 void Type::emitDumpWithMethod(
438         Formatter &out,
439         const std::string &streamName,
440         const std::string &methodName,
441         const std::string &name) const {
442     out << streamName
443         << " += "
444         << methodName
445         << "("
446         << name
447         << ");\n";
448 }
449 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const450 void Type::emitJavaDump(
451         Formatter &out,
452         const std::string &streamName,
453         const std::string &name) const {
454     out << streamName << ".append(" << name << ");\n";
455 }
456 
emitReaderWriterEmbedded(Formatter &,size_t,const std::string &,const std::string &,bool,const std::string &,bool,bool,ErrorMode,const std::string &,const std::string &) const457 void Type::emitReaderWriterEmbedded(
458         Formatter &,
459         size_t,
460         const std::string &,
461         const std::string &,
462         bool,
463         const std::string &,
464         bool,
465         bool,
466         ErrorMode,
467         const std::string &,
468         const std::string &) const {
469     CHECK(!"Should not be here") << typeName();
470 }
471 
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader) const472 void Type::emitJavaReaderWriter(
473         Formatter &out,
474         const std::string &parcelObj,
475         const std::string &argName,
476         bool isReader) const {
477     emitJavaReaderWriterWithSuffix(
478             out,
479             parcelObj,
480             argName,
481             isReader,
482             getJavaSuffix(),
483             "" /* extra */);
484 }
485 
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const486 void Type::emitJavaFieldInitializer(
487         Formatter &out,
488         const std::string &fieldName) const {
489     out << getJavaType()
490         << " "
491         << fieldName
492         << ";\n";
493 }
494 
emitJavaFieldDefaultInitialValue(Formatter &,const std::string &) const495 void Type::emitJavaFieldDefaultInitialValue(Formatter &, const std::string &) const {}
496 
emitJavaFieldReaderWriter(Formatter &,size_t,const std::string &,const std::string &,const std::string &,const std::string &,bool) const497 void Type::emitJavaFieldReaderWriter(
498         Formatter &,
499         size_t,
500         const std::string &,
501         const std::string &,
502         const std::string &,
503         const std::string &,
504         bool) const {
505     CHECK(!"Should not be here") << typeName();
506 }
507 
handleError(Formatter & out,ErrorMode mode)508 void Type::handleError(Formatter &out, ErrorMode mode) {
509     switch (mode) {
510         case ErrorMode_Goto:
511         {
512             out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
513             break;
514         }
515 
516         case ErrorMode_Break:
517         {
518             out << "if (_hidl_err != ::android::OK) { break; }\n\n";
519             break;
520         }
521 
522         case ErrorMode_Return:
523         {
524             out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n";
525             break;
526         }
527 
528         case ErrorMode_ReturnNothing:
529         {
530             out << "if (_hidl_err != ::android::OK) { return; }\n\n";
531             break;
532         }
533         default:
534         {
535             LOG(FATAL) << "Should not be here";
536         }
537     }
538 }
539 
emitReaderWriterEmbeddedForTypeName(Formatter & out,const std::string & name,bool nameIsPointer,const std::string & parcelObj,bool parcelObjIsPointer,bool isReader,ErrorMode mode,const std::string & parentName,const std::string & offsetText,const std::string & typeName,const std::string & childName,const std::string & funcNamespace) const540 void Type::emitReaderWriterEmbeddedForTypeName(
541         Formatter &out,
542         const std::string &name,
543         bool nameIsPointer,
544         const std::string &parcelObj,
545         bool parcelObjIsPointer,
546         bool isReader,
547         ErrorMode mode,
548         const std::string &parentName,
549         const std::string &offsetText,
550         const std::string &typeName,
551         const std::string &childName,
552         const std::string &funcNamespace) const {
553 
554         const std::string parcelObjDeref =
555         parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
556 
557     const std::string parcelObjPointer =
558         parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
559 
560     const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
561     const std::string namePointer = nameIsPointer ? name : ("&" + name);
562 
563     out << "_hidl_err = ";
564 
565     if (!funcNamespace.empty()) {
566         out << funcNamespace << "::";
567     }
568 
569     out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n");
570 
571     out.indent();
572     out.indent();
573 
574     if (isReader) {
575         out << "const_cast<"
576             << typeName
577             << " &>("
578             << nameDerefed
579             << "),\n";
580     } else {
581         out << nameDerefed
582             << ",\n";
583     }
584 
585     out << (isReader ? parcelObjDeref : parcelObjPointer)
586         << ",\n"
587         << parentName
588         << ",\n"
589         << offsetText;
590 
591     if (!childName.empty()) {
592         out << ", &"
593             << childName;
594     }
595 
596     out << ");\n\n";
597 
598     out.unindent();
599     out.unindent();
600 
601     handleError(out, mode);
602 }
603 
emitHidlDefinition(Formatter &) const604 void Type::emitHidlDefinition(Formatter&) const {
605     CHECK(!"Should not be here.") << typeName();
606 }
607 
emitTypeDeclarations(Formatter &) const608 void Type::emitTypeDeclarations(Formatter&) const {}
609 
emitTypeForwardDeclaration(Formatter &) const610 void Type::emitTypeForwardDeclaration(Formatter&) const {}
611 
emitGlobalTypeDeclarations(Formatter &) const612 void Type::emitGlobalTypeDeclarations(Formatter&) const {}
613 
emitPackageTypeDeclarations(Formatter &) const614 void Type::emitPackageTypeDeclarations(Formatter&) const {}
615 
emitPackageTypeHeaderDefinitions(Formatter &) const616 void Type::emitPackageTypeHeaderDefinitions(Formatter&) const {}
617 
emitPackageHwDeclarations(Formatter &) const618 void Type::emitPackageHwDeclarations(Formatter&) const {}
619 
emitTypeDefinitions(Formatter &,const std::string &) const620 void Type::emitTypeDefinitions(Formatter&, const std::string&) const {}
621 
emitJavaTypeDeclarations(Formatter &,bool) const622 void Type::emitJavaTypeDeclarations(Formatter&, bool) const {}
623 
needsEmbeddedReadWrite() const624 bool Type::needsEmbeddedReadWrite() const {
625     return false;
626 }
627 
resultNeedsDeref() const628 bool Type::resultNeedsDeref() const {
629     return false;
630 }
631 
getCppStackType(bool specifyNamespaces) const632 std::string Type::getCppStackType(bool specifyNamespaces) const {
633     return getCppType(StorageMode_Stack, specifyNamespaces);
634 }
635 
getCppResultType(bool specifyNamespaces) const636 std::string Type::getCppResultType(bool specifyNamespaces) const {
637     return getCppType(StorageMode_Result, specifyNamespaces);
638 }
639 
getCppArgumentType(bool specifyNamespaces) const640 std::string Type::getCppArgumentType(bool specifyNamespaces) const {
641     return getCppType(StorageMode_Argument, specifyNamespaces);
642 }
643 
getCppTypeCast(const std::string & objName,bool specifyNamespaces) const644 std::string Type::getCppTypeCast(const std::string& objName, bool specifyNamespaces) const {
645     return "(" + getCppStackType(specifyNamespaces) + ") " + objName;
646 }
647 
emitJavaReaderWriterWithSuffix(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader,const std::string & suffix,const std::string & extra) const648 void Type::emitJavaReaderWriterWithSuffix(
649         Formatter &out,
650         const std::string &parcelObj,
651         const std::string &argName,
652         bool isReader,
653         const std::string &suffix,
654         const std::string &extra) const {
655     out << parcelObj
656         << "."
657         << (isReader ? "read" : "write")
658         << suffix
659         << "(";
660 
661     if (isReader) {
662         out << extra;
663     } else {
664         out << (extra.empty() ? "" : (extra + ", "));
665         out << argName;
666     }
667 
668     out << ");\n";
669 }
670 
emitVtsTypeDeclarations(Formatter &) const671 void Type::emitVtsTypeDeclarations(Formatter&) const {}
672 
emitVtsAttributeType(Formatter & out) const673 void Type::emitVtsAttributeType(Formatter& out) const {
674     emitVtsTypeDeclarations(out);
675 }
676 
isJavaCompatible() const677 bool Type::isJavaCompatible() const {
678     std::unordered_set<const Type*> visited;
679     return isJavaCompatible(&visited);
680 }
681 
containsPointer() const682 bool Type::containsPointer() const {
683     std::unordered_set<const Type*> visited;
684     return containsPointer(&visited);
685 }
686 
isJavaCompatible(std::unordered_set<const Type * > * visited) const687 bool Type::isJavaCompatible(std::unordered_set<const Type*>* visited) const {
688     // We need to find al least one path from requested vertex
689     // to not java compatible.
690     // That means that if we have already visited some vertex,
691     // there is no need to determine whether it is java compatible
692     // (and we can assume that it is java compatible),
693     // as if not, the information about that would appear in the
694     // requested vertex through another path.
695     if (visited->find(this) != visited->end()) {
696         return true;
697     }
698     visited->insert(this);
699     return deepIsJavaCompatible(visited);
700 }
701 
containsPointer(std::unordered_set<const Type * > * visited) const702 bool Type::containsPointer(std::unordered_set<const Type*>* visited) const {
703     // See isJavaCompatible for similar structure.
704     if (visited->find(this) != visited->end()) {
705         return false;
706     }
707     visited->insert(this);
708     return deepContainsPointer(visited);
709 }
710 
deepIsJavaCompatible(std::unordered_set<const Type * > *) const711 bool Type::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const {
712     return true;
713 }
714 
deepContainsPointer(std::unordered_set<const Type * > *) const715 bool Type::deepContainsPointer(std::unordered_set<const Type*>* /* visited */) const {
716     return false;
717 }
718 
getAlignmentAndSize(size_t *,size_t *) const719 void Type::getAlignmentAndSize(
720         size_t * /* align */, size_t * /* size */) const {
721     CHECK(!"Should not be here.") << typeName();
722 }
723 
appendToExportedTypesVector(std::vector<const Type * > *) const724 void Type::appendToExportedTypesVector(
725         std::vector<const Type *> * /* exportedTypes */) const {
726 }
727 
emitExportedHeader(Formatter &,bool) const728 void Type::emitExportedHeader(Formatter& /* out */, bool /* forJava */) const {}
729 
isNeverStrongReference() const730 bool Type::isNeverStrongReference() const {
731     return false;
732 }
733 
734 ////////////////////////////////////////
735 
TemplatedType(Scope * parent,const std::string & definedName)736 TemplatedType::TemplatedType(Scope* parent, const std::string& definedName)
737     : Type(parent, definedName) {}
738 
typeName() const739 std::string TemplatedType::typeName() const {
740     return templatedTypeName() + " of " + mElementType->typeName();
741 }
742 
setElementType(const Reference<Type> & elementType)743 void TemplatedType::setElementType(const Reference<Type>& elementType) {
744     // can only be set once.
745     CHECK(mElementType.isEmptyReference());
746     CHECK(!elementType.isEmptyReference());
747 
748     mElementType = elementType;
749     mDefinedName = mDefinedName + "<" + mElementType.localName() + ">";
750 }
751 
getElementType() const752 const Type* TemplatedType::getElementType() const {
753     return mElementType.get();
754 }
755 
isTemplatedType() const756 bool TemplatedType::isTemplatedType() const {
757     return true;
758 }
759 
getReferences() const760 std::vector<const Reference<Type>*> TemplatedType::getReferences() const {
761     return {&mElementType};
762 }
763 
validate() const764 status_t TemplatedType::validate() const {
765     if (!isCompatibleElementType(mElementType.get())) {
766         std::cerr << "ERROR: " << typeName() /* contains element type */
767                   << " is not supported at " << mElementType.location() << "\n";
768         return UNKNOWN_ERROR;
769     }
770 
771     return Type::validate();
772 }
773 
emitVtsTypeDeclarations(Formatter & out) const774 void TemplatedType::emitVtsTypeDeclarations(Formatter& out) const {
775     out << "type: " << getVtsType() << "\n";
776     out << getVtsValueName() << ": {\n";
777     out.indent();
778     mElementType->emitVtsTypeDeclarations(out);
779     out.unindent();
780     out << "}\n";
781 }
782 
emitVtsAttributeType(Formatter & out) const783 void TemplatedType::emitVtsAttributeType(Formatter& out) const {
784     out << "type: " << getVtsType() << "\n";
785     out << getVtsValueName() << ": {\n";
786     out.indent();
787     mElementType->emitVtsAttributeType(out);
788     out.unindent();
789     out << "}\n";
790 }
791 
792 }  // namespace android
793 
794