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 
29 namespace android {
30 
Type(Scope * parent)31 Type::Type(Scope* parent) : mParent(parent) {}
32 
~Type()33 Type::~Type() {}
34 
isScope() const35 bool Type::isScope() const {
36     return false;
37 }
38 
isInterface() const39 bool Type::isInterface() const {
40     return false;
41 }
42 
isScalar() const43 bool Type::isScalar() const {
44     return false;
45 }
46 
isString() const47 bool Type::isString() const {
48     return false;
49 }
50 
isEnum() const51 bool Type::isEnum() const {
52     return false;
53 }
54 
isBitField() const55 bool Type::isBitField() const {
56     return false;
57 }
58 
isHandle() const59 bool Type::isHandle() const {
60     return false;
61 }
62 
isTypeDef() const63 bool Type::isTypeDef() const {
64     return false;
65 }
66 
isBinder() const67 bool Type::isBinder() const {
68     return false;
69 }
70 
isNamedType() const71 bool Type::isNamedType() const {
72     return false;
73 }
74 
isMemory() const75 bool Type::isMemory() const {
76     return false;
77 }
78 
isCompoundType() const79 bool Type::isCompoundType() const {
80     return false;
81 }
82 
isArray() const83 bool Type::isArray() const {
84     return false;
85 }
86 
isVector() const87 bool Type::isVector() const {
88     return false;
89 }
90 
isTemplatedType() const91 bool Type::isTemplatedType() const {
92     return false;
93 }
94 
isPointer() const95 bool Type::isPointer() const {
96     return false;
97 }
98 
resolve()99 Type* Type::resolve() {
100     return const_cast<Type*>(static_cast<const Type*>(this)->resolve());
101 }
102 
resolve() const103 const Type* Type::resolve() const {
104     return this;
105 }
106 
getDefinedTypes()107 std::vector<Type*> Type::getDefinedTypes() {
108     const auto& constRet = static_cast<const Type*>(this)->getDefinedTypes();
109     std::vector<Type*> ret(constRet.size());
110     std::transform(constRet.begin(), constRet.end(), ret.begin(),
111                    [](const auto* type) { return const_cast<Type*>(type); });
112     return ret;
113 }
114 
getDefinedTypes() const115 std::vector<const Type*> Type::getDefinedTypes() const {
116     return {};
117 }
118 
getReferences()119 std::vector<Reference<Type>*> Type::getReferences() {
120     const auto& constRet = static_cast<const Type*>(this)->getReferences();
121     std::vector<Reference<Type>*> ret(constRet.size());
122     std::transform(constRet.begin(), constRet.end(), ret.begin(),
123                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
124     return ret;
125 }
126 
getReferences() const127 std::vector<const Reference<Type>*> Type::getReferences() const {
128     return {};
129 }
130 
getConstantExpressions()131 std::vector<ConstantExpression*> Type::getConstantExpressions() {
132     const auto& constRet = static_cast<const Type*>(this)->getConstantExpressions();
133     std::vector<ConstantExpression*> ret(constRet.size());
134     std::transform(constRet.begin(), constRet.end(), ret.begin(),
135                    [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
136     return ret;
137 }
138 
getConstantExpressions() const139 std::vector<const ConstantExpression*> Type::getConstantExpressions() const {
140     return {};
141 }
142 
getStrongReferences()143 std::vector<Reference<Type>*> Type::getStrongReferences() {
144     const auto& constRet = static_cast<const Type*>(this)->getStrongReferences();
145     std::vector<Reference<Type>*> ret(constRet.size());
146     std::transform(constRet.begin(), constRet.end(), ret.begin(),
147                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
148     return ret;
149 }
150 
getStrongReferences() const151 std::vector<const Reference<Type>*> Type::getStrongReferences() const {
152     std::vector<const Reference<Type>*> ret;
153     for (const auto* ref : getReferences()) {
154         if (!ref->shallowGet()->isNeverStrongReference()) {
155             ret.push_back(ref);
156         }
157     }
158     return ret;
159 }
160 
recursivePass(const std::function<status_t (Type *)> & func,std::unordered_set<const Type * > * visited)161 status_t Type::recursivePass(const std::function<status_t(Type*)>& func,
162                              std::unordered_set<const Type*>* visited) {
163     if (mIsPostParseCompleted) return OK;
164 
165     if (visited->find(this) != visited->end()) return OK;
166     visited->insert(this);
167 
168     status_t err = func(this);
169     if (err != OK) return err;
170 
171     for (auto* nextType : getDefinedTypes()) {
172         err = nextType->recursivePass(func, visited);
173         if (err != OK) return err;
174     }
175 
176     for (auto* nextRef : getReferences()) {
177         err = nextRef->shallowGet()->recursivePass(func, visited);
178         if (err != OK) return err;
179     }
180 
181     return OK;
182 }
183 
recursivePass(const std::function<status_t (const Type *)> & func,std::unordered_set<const Type * > * visited) const184 status_t Type::recursivePass(const std::function<status_t(const Type*)>& func,
185                              std::unordered_set<const Type*>* visited) const {
186     if (mIsPostParseCompleted) return OK;
187 
188     if (visited->find(this) != visited->end()) return OK;
189     visited->insert(this);
190 
191     status_t err = func(this);
192     if (err != OK) return err;
193 
194     for (const auto* nextType : getDefinedTypes()) {
195         err = nextType->recursivePass(func, visited);
196         if (err != OK) return err;
197     }
198 
199     for (const auto* nextRef : getReferences()) {
200         err = nextRef->shallowGet()->recursivePass(func, visited);
201         if (err != OK) return err;
202     }
203 
204     return OK;
205 }
206 
resolveInheritance()207 status_t Type::resolveInheritance() {
208     return OK;
209 }
210 
validate() const211 status_t Type::validate() const {
212     return OK;
213 }
214 
CheckAcyclicStatus(status_t status,const Type * cycleEnd)215 Type::CheckAcyclicStatus::CheckAcyclicStatus(status_t status, const Type* cycleEnd)
216     : status(status), cycleEnd(cycleEnd) {
217     CHECK(cycleEnd == nullptr || status != OK);
218 }
219 
topologicalOrder(std::unordered_map<const Type *,size_t> * reversedOrder,std::unordered_set<const Type * > * stack) const220 Type::CheckAcyclicStatus Type::topologicalOrder(
221     std::unordered_map<const Type*, size_t>* reversedOrder,
222     std::unordered_set<const Type*>* stack) const {
223     if (stack->find(this) != stack->end()) {
224         std::cerr << "ERROR: Cyclic declaration:\n";
225         return CheckAcyclicStatus(UNKNOWN_ERROR, this);
226     }
227 
228     if (reversedOrder->find(this) != reversedOrder->end()) return CheckAcyclicStatus(OK);
229     stack->insert(this);
230 
231     for (const auto* nextType : getDefinedTypes()) {
232         auto err = nextType->topologicalOrder(reversedOrder, stack);
233 
234         if (err.status != OK) {
235             if (err.cycleEnd == nullptr) return err;
236 
237             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "'";
238             if (nextType->isNamedType()) {
239                 std::cerr << " at " << static_cast<const NamedType*>(nextType)->location();
240             }
241             std::cerr << "\n";
242 
243             if (err.cycleEnd == this) {
244                 return CheckAcyclicStatus(err.status);
245             }
246             return err;
247         }
248     }
249 
250     for (const auto* nextRef : getStrongReferences()) {
251         const auto* nextType = nextRef->shallowGet();
252         auto err = nextType->topologicalOrder(reversedOrder, stack);
253 
254         if (err.status != OK) {
255             if (err.cycleEnd == nullptr) return err;
256 
257             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "' at "
258                       << nextRef->location() << "\n";
259 
260             if (err.cycleEnd == this) {
261                 return CheckAcyclicStatus(err.status);
262             }
263             return err;
264         }
265     }
266 
267     CHECK(stack->find(this) != stack->end());
268     stack->erase(this);
269 
270     CHECK(reversedOrder->find(this) == reversedOrder->end());
271     // Do not call insert and size in one statement to not rely on
272     // evaluation order.
273     size_t index = reversedOrder->size();
274     reversedOrder->insert({this, index});
275 
276     return CheckAcyclicStatus(OK);
277 }
278 
checkForwardReferenceRestrictions(const Reference<Type> & ref) const279 status_t Type::checkForwardReferenceRestrictions(const Reference<Type>& ref) const {
280     const Location& refLoc = ref.location();
281     const Type* refType = ref.shallowGet();
282 
283     // Not NamedTypes are avaiable everywhere.
284     // Only ArrayType and TemplatedType contain additional types in
285     // their reference (which is actually a part of type definition),
286     // so they are proceeded in this case.
287     //
288     // If we support named templated types one day, we will need to change
289     // this logic.
290     if (!refType->isNamedType()) {
291         for (const Reference<Type>* innerRef : refType->getReferences()) {
292             status_t err = checkForwardReferenceRestrictions(*innerRef);
293             if (err != OK) return err;
294         }
295         return OK;
296     }
297 
298     const Location& typeLoc = static_cast<const NamedType*>(refType)->location();
299 
300     // If referenced type is declared in another file or before reference,
301     // there is no forward reference here.
302     if (!Location::inSameFile(refLoc, typeLoc) ||
303         (!Location::intersect(refLoc, typeLoc) && typeLoc < refLoc)) {
304         return OK;
305     }
306 
307     // Type must be declared somewhere in the current stack to make it
308     // available for forward referencing.
309     const Type* refTypeParent = refType->parent();
310     for (const Type* ancestor = this; ancestor != nullptr; ancestor = ancestor->parent()) {
311         if (ancestor == refTypeParent) return OK;
312     }
313 
314     std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at " << ref.location()
315               << " is not supported.\n"
316               << "C++ forward declaration doesn't support inner types.\n";
317 
318     return UNKNOWN_ERROR;
319 }
320 
resolveToScalarType() const321 const ScalarType *Type::resolveToScalarType() const {
322     return NULL;
323 }
324 
isValidEnumStorageType() const325 bool Type::isValidEnumStorageType() const {
326     const ScalarType *scalarType = resolveToScalarType();
327 
328     if (scalarType == NULL) {
329         return false;
330     }
331 
332     return scalarType->isValidEnumStorageType();
333 }
334 
isElidableType() const335 bool Type::isElidableType() const {
336     return false;
337 }
338 
canCheckEquality() const339 bool Type::canCheckEquality() const {
340     std::unordered_set<const Type*> visited;
341     return canCheckEquality(&visited);
342 }
343 
canCheckEquality(std::unordered_set<const Type * > * visited) const344 bool Type::canCheckEquality(std::unordered_set<const Type*>* visited) const {
345     // See isJavaCompatible for similar structure.
346     if (visited->find(this) != visited->end()) {
347         return true;
348     }
349     visited->insert(this);
350     return deepCanCheckEquality(visited);
351 }
352 
deepCanCheckEquality(std::unordered_set<const Type * > *) const353 bool Type::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
354     return false;
355 }
356 
setPostParseCompleted()357 void Type::setPostParseCompleted() {
358     CHECK(!mIsPostParseCompleted);
359     mIsPostParseCompleted = true;
360 }
361 
parent()362 Scope* Type::parent() {
363     return mParent;
364 }
365 
parent() const366 const Scope* Type::parent() const {
367     return mParent;
368 }
369 
getCppType(StorageMode,bool) const370 std::string Type::getCppType(StorageMode, bool) const {
371     CHECK(!"Should not be here");
372     return std::string();
373 }
374 
decorateCppName(const std::string & name,StorageMode mode,bool specifyNamespaces) const375 std::string Type::decorateCppName(
376         const std::string &name, StorageMode mode, bool specifyNamespaces) const {
377     return getCppType(mode, specifyNamespaces) + " " + name;
378 }
379 
getJavaType(bool) const380 std::string Type::getJavaType(bool /* forInitializer */) const {
381     CHECK(!"Should not be here");
382     return std::string();
383 }
384 
getJavaWrapperType() const385 std::string Type::getJavaWrapperType() const {
386     return getJavaType();
387 }
388 
getJavaSuffix() const389 std::string Type::getJavaSuffix() const {
390     CHECK(!"Should not be here");
391     return std::string();
392 }
393 
getVtsType() const394 std::string Type::getVtsType() const {
395     CHECK(!"Should not be here");
396     return std::string();
397 }
398 
getVtsValueName() const399 std::string Type::getVtsValueName() const {
400     CHECK(!"Should not be here");
401     return std::string();
402 }
403 
emitReaderWriter(Formatter &,const std::string &,const std::string &,bool,bool,ErrorMode) const404 void Type::emitReaderWriter(
405         Formatter &,
406         const std::string &,
407         const std::string &,
408         bool,
409         bool,
410         ErrorMode) const {
411     CHECK(!"Should not be here");
412 }
413 
emitResolveReferences(Formatter &,const std::string &,bool,const std::string &,bool,bool,ErrorMode) const414 void Type::emitResolveReferences(
415         Formatter &,
416         const std::string &,
417         bool,
418         const std::string &,
419         bool,
420         bool,
421         ErrorMode) const {
422     CHECK(!"Should not be here");
423 }
424 
emitResolveReferencesEmbedded(Formatter &,size_t,const std::string &,const std::string &,bool,const std::string &,bool,bool,ErrorMode,const std::string &,const std::string &) const425 void Type::emitResolveReferencesEmbedded(
426         Formatter &,
427         size_t,
428         const std::string &,
429         const std::string &,
430         bool,
431         const std::string &,
432         bool,
433         bool,
434         ErrorMode,
435         const std::string &,
436         const std::string &) const {
437     CHECK(!"Should not be here");
438 }
439 
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const440 void Type::emitDump(
441         Formatter &out,
442         const std::string &streamName,
443         const std::string &name) const {
444     emitDumpWithMethod(out, streamName, "::android::hardware::toString", name);
445 }
446 
emitDumpWithMethod(Formatter & out,const std::string & streamName,const std::string & methodName,const std::string & name) const447 void Type::emitDumpWithMethod(
448         Formatter &out,
449         const std::string &streamName,
450         const std::string &methodName,
451         const std::string &name) const {
452     out << streamName
453         << " += "
454         << methodName
455         << "("
456         << name
457         << ");\n";
458 }
459 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const460 void Type::emitJavaDump(
461         Formatter &out,
462         const std::string &streamName,
463         const std::string &name) const {
464     out << streamName << ".append(" << name << ");\n";
465 }
466 
useParentInEmitResolveReferencesEmbedded() const467 bool Type::useParentInEmitResolveReferencesEmbedded() const {
468     return needsResolveReferences();
469 }
470 
useNameInEmitReaderWriterEmbedded(bool) const471 bool Type::useNameInEmitReaderWriterEmbedded(bool) const {
472     return needsEmbeddedReadWrite();
473 }
474 
emitReaderWriterEmbedded(Formatter &,size_t,const std::string &,const std::string &,bool,const std::string &,bool,bool,ErrorMode,const std::string &,const std::string &) const475 void Type::emitReaderWriterEmbedded(
476         Formatter &,
477         size_t,
478         const std::string &,
479         const std::string &,
480         bool,
481         const std::string &,
482         bool,
483         bool,
484         ErrorMode,
485         const std::string &,
486         const std::string &) const {
487     CHECK(!"Should not be here");
488 }
489 
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader) const490 void Type::emitJavaReaderWriter(
491         Formatter &out,
492         const std::string &parcelObj,
493         const std::string &argName,
494         bool isReader) const {
495     emitJavaReaderWriterWithSuffix(
496             out,
497             parcelObj,
498             argName,
499             isReader,
500             getJavaSuffix(),
501             "" /* extra */);
502 }
503 
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const504 void Type::emitJavaFieldInitializer(
505         Formatter &out,
506         const std::string &fieldName) const {
507     out << getJavaType()
508         << " "
509         << fieldName
510         << ";\n";
511 }
512 
emitJavaFieldReaderWriter(Formatter &,size_t,const std::string &,const std::string &,const std::string &,const std::string &,bool) const513 void Type::emitJavaFieldReaderWriter(
514         Formatter &,
515         size_t,
516         const std::string &,
517         const std::string &,
518         const std::string &,
519         const std::string &,
520         bool) const {
521     CHECK(!"Should not be here");
522 }
523 
handleError(Formatter & out,ErrorMode mode) const524 void Type::handleError(Formatter &out, ErrorMode mode) const {
525     switch (mode) {
526         case ErrorMode_Ignore:
527         {
528             out << "/* _hidl_err ignored! */\n\n";
529             break;
530         }
531 
532         case ErrorMode_Goto:
533         {
534             out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
535             break;
536         }
537 
538         case ErrorMode_Break:
539         {
540             out << "if (_hidl_err != ::android::OK) { break; }\n\n";
541             break;
542         }
543 
544         case ErrorMode_Return:
545         {
546             out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n";
547             break;
548         }
549     }
550 }
551 
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) const552 void Type::emitReaderWriterEmbeddedForTypeName(
553         Formatter &out,
554         const std::string &name,
555         bool nameIsPointer,
556         const std::string &parcelObj,
557         bool parcelObjIsPointer,
558         bool isReader,
559         ErrorMode mode,
560         const std::string &parentName,
561         const std::string &offsetText,
562         const std::string &typeName,
563         const std::string &childName,
564         const std::string &funcNamespace) const {
565 
566         const std::string parcelObjDeref =
567         parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
568 
569     const std::string parcelObjPointer =
570         parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
571 
572     const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
573     const std::string namePointer = nameIsPointer ? name : ("&" + name);
574 
575     out << "_hidl_err = ";
576 
577     if (!funcNamespace.empty()) {
578         out << funcNamespace << "::";
579     }
580 
581     out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n");
582 
583     out.indent();
584     out.indent();
585 
586     if (isReader) {
587         out << "const_cast<"
588             << typeName
589             << " &>("
590             << nameDerefed
591             << "),\n";
592     } else {
593         out << nameDerefed
594             << ",\n";
595     }
596 
597     out << (isReader ? parcelObjDeref : parcelObjPointer)
598         << ",\n"
599         << parentName
600         << ",\n"
601         << offsetText;
602 
603     if (!childName.empty()) {
604         out << ", &"
605             << childName;
606     }
607 
608     out << ");\n\n";
609 
610     out.unindent();
611     out.unindent();
612 
613     handleError(out, mode);
614 }
615 
emitTypeDeclarations(Formatter &) const616 void Type::emitTypeDeclarations(Formatter&) const {}
617 
emitTypeForwardDeclaration(Formatter &) const618 void Type::emitTypeForwardDeclaration(Formatter&) const {}
619 
emitGlobalTypeDeclarations(Formatter &) const620 void Type::emitGlobalTypeDeclarations(Formatter&) const {}
621 
emitPackageTypeDeclarations(Formatter &) const622 void Type::emitPackageTypeDeclarations(Formatter&) const {}
623 
emitPackageHwDeclarations(Formatter &) const624 void Type::emitPackageHwDeclarations(Formatter&) const {}
625 
emitTypeDefinitions(Formatter &,const std::string &) const626 void Type::emitTypeDefinitions(Formatter&, const std::string&) const {}
627 
emitJavaTypeDeclarations(Formatter &,bool) const628 void Type::emitJavaTypeDeclarations(Formatter&, bool) const {}
629 
needsEmbeddedReadWrite() const630 bool Type::needsEmbeddedReadWrite() const {
631     return false;
632 }
633 
resultNeedsDeref() const634 bool Type::resultNeedsDeref() const {
635     return false;
636 }
637 
needsResolveReferences() const638 bool Type::needsResolveReferences() const {
639     std::unordered_set<const Type*> visited;
640     return needsResolveReferences(&visited);
641 }
642 
needsResolveReferences(std::unordered_set<const Type * > * visited) const643 bool Type::needsResolveReferences(std::unordered_set<const Type*>* visited) const {
644     // See isJavaCompatible for similar structure.
645     if (visited->find(this) != visited->end()) {
646         return false;
647     }
648     visited->insert(this);
649     return deepNeedsResolveReferences(visited);
650 }
651 
deepNeedsResolveReferences(std::unordered_set<const Type * > *) const652 bool Type::deepNeedsResolveReferences(std::unordered_set<const Type*>* /* visited */) const {
653     return false;
654 }
655 
getCppStackType(bool specifyNamespaces) const656 std::string Type::getCppStackType(bool specifyNamespaces) const {
657     return getCppType(StorageMode_Stack, specifyNamespaces);
658 }
659 
getCppResultType(bool specifyNamespaces) const660 std::string Type::getCppResultType(bool specifyNamespaces) const {
661     return getCppType(StorageMode_Result, specifyNamespaces);
662 }
663 
getCppArgumentType(bool specifyNamespaces) const664 std::string Type::getCppArgumentType(bool specifyNamespaces) const {
665     return getCppType(StorageMode_Argument, specifyNamespaces);
666 }
667 
emitJavaReaderWriterWithSuffix(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader,const std::string & suffix,const std::string & extra) const668 void Type::emitJavaReaderWriterWithSuffix(
669         Formatter &out,
670         const std::string &parcelObj,
671         const std::string &argName,
672         bool isReader,
673         const std::string &suffix,
674         const std::string &extra) const {
675     out << parcelObj
676         << "."
677         << (isReader ? "read" : "write")
678         << suffix
679         << "(";
680 
681     if (isReader) {
682         out << extra;
683     } else {
684         out << (extra.empty() ? "" : (extra + ", "));
685         out << argName;
686     }
687 
688     out << ");\n";
689 }
690 
emitVtsTypeDeclarations(Formatter &) const691 void Type::emitVtsTypeDeclarations(Formatter&) const {}
692 
emitVtsAttributeType(Formatter & out) const693 void Type::emitVtsAttributeType(Formatter& out) const {
694     emitVtsTypeDeclarations(out);
695 }
696 
isJavaCompatible() const697 bool Type::isJavaCompatible() const {
698     std::unordered_set<const Type*> visited;
699     return isJavaCompatible(&visited);
700 }
701 
containsPointer() const702 bool Type::containsPointer() const {
703     std::unordered_set<const Type*> visited;
704     return containsPointer(&visited);
705 }
706 
isJavaCompatible(std::unordered_set<const Type * > * visited) const707 bool Type::isJavaCompatible(std::unordered_set<const Type*>* visited) const {
708     // We need to find al least one path from requested vertex
709     // to not java compatible.
710     // That means that if we have already visited some vertex,
711     // there is no need to determine whether it is java compatible
712     // (and we can assume that it is java compatible),
713     // as if not, the information about that would appear in the
714     // requested vertex through another path.
715     if (visited->find(this) != visited->end()) {
716         return true;
717     }
718     visited->insert(this);
719     return deepIsJavaCompatible(visited);
720 }
721 
containsPointer(std::unordered_set<const Type * > * visited) const722 bool Type::containsPointer(std::unordered_set<const Type*>* visited) const {
723     // See isJavaCompatible for similar structure.
724     if (visited->find(this) != visited->end()) {
725         return false;
726     }
727     visited->insert(this);
728     return deepContainsPointer(visited);
729 }
730 
deepIsJavaCompatible(std::unordered_set<const Type * > *) const731 bool Type::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const {
732     return true;
733 }
734 
deepContainsPointer(std::unordered_set<const Type * > *) const735 bool Type::deepContainsPointer(std::unordered_set<const Type*>* /* visited */) const {
736     return false;
737 }
738 
getAlignmentAndSize(size_t *,size_t *) const739 void Type::getAlignmentAndSize(
740         size_t * /* align */, size_t * /* size */) const {
741     CHECK(!"Should not be here.");
742 }
743 
appendToExportedTypesVector(std::vector<const Type * > *) const744 void Type::appendToExportedTypesVector(
745         std::vector<const Type *> * /* exportedTypes */) const {
746 }
747 
emitExportedHeader(Formatter &,bool) const748 void Type::emitExportedHeader(Formatter& /* out */, bool /* forJava */) const {}
749 
isNeverStrongReference() const750 bool Type::isNeverStrongReference() const {
751     return false;
752 }
753 
754 ////////////////////////////////////////
755 
TemplatedType(Scope * parent)756 TemplatedType::TemplatedType(Scope* parent) : Type(parent) {}
757 
typeName() const758 std::string TemplatedType::typeName() const {
759     return templatedTypeName() + " of " + mElementType->typeName();
760 }
761 
setElementType(const Reference<Type> & elementType)762 void TemplatedType::setElementType(const Reference<Type>& elementType) {
763     // can only be set once.
764     CHECK(mElementType.isEmptyReference());
765     CHECK(!elementType.isEmptyReference());
766 
767     mElementType = elementType;
768 }
769 
getElementType() const770 const Type* TemplatedType::getElementType() const {
771     return mElementType.get();
772 }
773 
isTemplatedType() const774 bool TemplatedType::isTemplatedType() const {
775     return true;
776 }
777 
getReferences() const778 std::vector<const Reference<Type>*> TemplatedType::getReferences() const {
779     return {&mElementType};
780 }
781 
validate() const782 status_t TemplatedType::validate() const {
783     if (!isCompatibleElementType(mElementType.get())) {
784         std::cerr << "ERROR: " << typeName() /* contains element type */
785                   << " is not supported at " << mElementType.location() << "\n";
786         return UNKNOWN_ERROR;
787     }
788 
789     return Type::validate();
790 }
791 
emitVtsTypeDeclarations(Formatter & out) const792 void TemplatedType::emitVtsTypeDeclarations(Formatter& out) const {
793     out << "type: " << getVtsType() << "\n";
794     out << getVtsValueName() << ": {\n";
795     out.indent();
796     mElementType->emitVtsTypeDeclarations(out);
797     out.unindent();
798     out << "}\n";
799 }
800 
emitVtsAttributeType(Formatter & out) const801 void TemplatedType::emitVtsAttributeType(Formatter& out) const {
802     out << "type: " << getVtsType() << "\n";
803     out << getVtsValueName() << ": {\n";
804     out.indent();
805     mElementType->emitVtsAttributeType(out);
806     out.unindent();
807     out << "}\n";
808 }
809 
810 }  // namespace android
811 
812