• 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 
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 
isNamedType() const67 bool Type::isNamedType() const {
68     return false;
69 }
70 
isMemory() const71 bool Type::isMemory() const {
72     return false;
73 }
74 
isCompoundType() const75 bool Type::isCompoundType() const {
76     return false;
77 }
78 
isArray() const79 bool Type::isArray() const {
80     return false;
81 }
82 
isVector() const83 bool Type::isVector() const {
84     return false;
85 }
86 
isTemplatedType() const87 bool Type::isTemplatedType() const {
88     return false;
89 }
90 
isPointer() const91 bool Type::isPointer() const {
92     return false;
93 }
94 
resolve()95 Type* Type::resolve() {
96     return const_cast<Type*>(static_cast<const Type*>(this)->resolve());
97 }
98 
resolve() const99 const Type* Type::resolve() const {
100     return this;
101 }
102 
getDefinedTypes()103 std::vector<Type*> Type::getDefinedTypes() {
104     const auto& constRet = static_cast<const Type*>(this)->getDefinedTypes();
105     std::vector<Type*> ret(constRet.size());
106     std::transform(constRet.begin(), constRet.end(), ret.begin(),
107                    [](const auto* type) { return const_cast<Type*>(type); });
108     return ret;
109 }
110 
getDefinedTypes() const111 std::vector<const Type*> Type::getDefinedTypes() const {
112     return {};
113 }
114 
getReferences()115 std::vector<Reference<Type>*> Type::getReferences() {
116     const auto& constRet = static_cast<const Type*>(this)->getReferences();
117     std::vector<Reference<Type>*> ret(constRet.size());
118     std::transform(constRet.begin(), constRet.end(), ret.begin(),
119                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
120     return ret;
121 }
122 
getReferences() const123 std::vector<const Reference<Type>*> Type::getReferences() const {
124     return {};
125 }
126 
getConstantExpressions()127 std::vector<ConstantExpression*> Type::getConstantExpressions() {
128     const auto& constRet = static_cast<const Type*>(this)->getConstantExpressions();
129     std::vector<ConstantExpression*> ret(constRet.size());
130     std::transform(constRet.begin(), constRet.end(), ret.begin(),
131                    [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
132     return ret;
133 }
134 
getConstantExpressions() const135 std::vector<const ConstantExpression*> Type::getConstantExpressions() const {
136     return {};
137 }
138 
getStrongReferences()139 std::vector<Reference<Type>*> Type::getStrongReferences() {
140     const auto& constRet = static_cast<const Type*>(this)->getStrongReferences();
141     std::vector<Reference<Type>*> ret(constRet.size());
142     std::transform(constRet.begin(), constRet.end(), ret.begin(),
143                    [](const auto* ref) { return const_cast<Reference<Type>*>(ref); });
144     return ret;
145 }
146 
getStrongReferences() const147 std::vector<const Reference<Type>*> Type::getStrongReferences() const {
148     std::vector<const Reference<Type>*> ret;
149     for (const auto* ref : getReferences()) {
150         if (!ref->shallowGet()->isNeverStrongReference()) {
151             ret.push_back(ref);
152         }
153     }
154     return ret;
155 }
156 
recursivePass(ParseStage stage,const std::function<status_t (Type *)> & func,std::unordered_set<const Type * > * visited)157 status_t Type::recursivePass(ParseStage stage, const std::function<status_t(Type*)>& func,
158                              std::unordered_set<const Type*>* visited) {
159     if (mParseStage > stage) return OK;
160     if (mParseStage < stage) return UNKNOWN_ERROR;
161 
162     if (visited->find(this) != visited->end()) return OK;
163     visited->insert(this);
164 
165     status_t err = func(this);
166     if (err != OK) return err;
167 
168     for (auto* nextType : getDefinedTypes()) {
169         err = nextType->recursivePass(stage, func, visited);
170         if (err != OK) return err;
171     }
172 
173     for (auto* nextRef : getReferences()) {
174         err = nextRef->shallowGet()->recursivePass(stage, func, visited);
175         if (err != OK) return err;
176     }
177 
178     return OK;
179 }
180 
recursivePass(ParseStage stage,const std::function<status_t (const Type *)> & func,std::unordered_set<const Type * > * visited) const181 status_t Type::recursivePass(ParseStage stage, const std::function<status_t(const Type*)>& func,
182                              std::unordered_set<const Type*>* visited) const {
183     if (mParseStage > stage) return OK;
184     if (mParseStage < stage) return UNKNOWN_ERROR;
185 
186     if (visited->find(this) != visited->end()) return OK;
187     visited->insert(this);
188 
189     status_t err = func(this);
190     if (err != OK) return err;
191 
192     for (const auto* nextType : getDefinedTypes()) {
193         err = nextType->recursivePass(stage, func, visited);
194         if (err != OK) return err;
195     }
196 
197     for (const auto* nextRef : getReferences()) {
198         err = nextRef->shallowGet()->recursivePass(stage, func, visited);
199         if (err != OK) return err;
200     }
201 
202     return OK;
203 }
204 
resolveInheritance()205 status_t Type::resolveInheritance() {
206     return OK;
207 }
208 
validate() const209 status_t Type::validate() const {
210     return OK;
211 }
212 
CheckAcyclicStatus(status_t status,const Type * cycleEnd)213 Type::CheckAcyclicStatus::CheckAcyclicStatus(status_t status, const Type* cycleEnd)
214     : status(status), cycleEnd(cycleEnd) {
215     CHECK(cycleEnd == nullptr || status != OK);
216 }
217 
topologicalOrder(std::unordered_map<const Type *,size_t> * reversedOrder,std::unordered_set<const Type * > * stack) const218 Type::CheckAcyclicStatus Type::topologicalOrder(
219     std::unordered_map<const Type*, size_t>* reversedOrder,
220     std::unordered_set<const Type*>* stack) const {
221     if (stack->find(this) != stack->end()) {
222         std::cerr << "ERROR: Cyclic declaration:\n";
223         return CheckAcyclicStatus(UNKNOWN_ERROR, this);
224     }
225 
226     if (reversedOrder->find(this) != reversedOrder->end()) return CheckAcyclicStatus(OK);
227     stack->insert(this);
228 
229     for (const auto* nextType : getDefinedTypes()) {
230         auto err = nextType->topologicalOrder(reversedOrder, stack);
231 
232         if (err.status != OK) {
233             if (err.cycleEnd == nullptr) return err;
234 
235             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "'";
236             if (nextType->isNamedType()) {
237                 std::cerr << " at " << static_cast<const NamedType*>(nextType)->location();
238             }
239             std::cerr << "\n";
240 
241             if (err.cycleEnd == this) {
242                 return CheckAcyclicStatus(err.status);
243             }
244             return err;
245         }
246     }
247 
248     for (const auto* nextRef : getStrongReferences()) {
249         const auto* nextType = nextRef->shallowGet();
250         auto err = nextType->topologicalOrder(reversedOrder, stack);
251 
252         if (err.status != OK) {
253             if (err.cycleEnd == nullptr) return err;
254 
255             std::cerr << "  '" << nextType->typeName() << "' in '" << typeName() << "' at "
256                       << nextRef->location() << "\n";
257 
258             if (err.cycleEnd == this) {
259                 return CheckAcyclicStatus(err.status);
260             }
261             return err;
262         }
263     }
264 
265     CHECK(stack->find(this) != stack->end());
266     stack->erase(this);
267 
268     CHECK(reversedOrder->find(this) == reversedOrder->end());
269     // Do not call insert and size in one statement to not rely on
270     // evaluation order.
271     size_t index = reversedOrder->size();
272     reversedOrder->insert({this, index});
273 
274     return CheckAcyclicStatus(OK);
275 }
276 
checkForwardReferenceRestrictions(const Reference<Type> & ref) const277 status_t Type::checkForwardReferenceRestrictions(const Reference<Type>& ref) const {
278     const Location& refLoc = ref.location();
279     const Type* refType = ref.shallowGet();
280 
281     // Not NamedTypes are avaiable everywhere.
282     // Only ArrayType and TemplatedType contain additional types in
283     // their reference (which is actually a part of type definition),
284     // so they are proceeded in this case.
285     //
286     // If we support named templated types one day, we will need to change
287     // this logic.
288     if (!refType->isNamedType()) {
289         for (const Reference<Type>* innerRef : refType->getReferences()) {
290             status_t err = checkForwardReferenceRestrictions(*innerRef);
291             if (err != OK) return err;
292         }
293         return OK;
294     }
295 
296     const Location& typeLoc = static_cast<const NamedType*>(refType)->location();
297 
298     // If referenced type is declared in another file or before reference,
299     // there is no forward reference here.
300     if (!Location::inSameFile(refLoc, typeLoc) ||
301         (!Location::intersect(refLoc, typeLoc) && typeLoc < refLoc)) {
302         return OK;
303     }
304 
305     // Type must be declared somewhere in the current stack to make it
306     // available for forward referencing.
307     const Type* refTypeParent = refType->parent();
308     for (const Type* ancestor = this; ancestor != nullptr; ancestor = ancestor->parent()) {
309         if (ancestor == refTypeParent) return OK;
310     }
311 
312     std::cerr << "ERROR: Forward reference of '" << refType->typeName() << "' at " << ref.location()
313               << " is not supported.\n"
314               << "C++ forward declaration doesn't support inner types.\n";
315 
316     return UNKNOWN_ERROR;
317 }
318 
resolveToScalarType() const319 const ScalarType *Type::resolveToScalarType() const {
320     return nullptr;
321 }
322 
isValidEnumStorageType() const323 bool Type::isValidEnumStorageType() const {
324     const ScalarType *scalarType = resolveToScalarType();
325 
326     if (scalarType == nullptr) {
327         return false;
328     }
329 
330     return scalarType->isValidEnumStorageType();
331 }
332 
isElidableType() const333 bool Type::isElidableType() const {
334     return false;
335 }
336 
canCheckEquality() const337 bool Type::canCheckEquality() const {
338     std::unordered_set<const Type*> visited;
339     return canCheckEquality(&visited);
340 }
341 
canCheckEquality(std::unordered_set<const Type * > * visited) const342 bool Type::canCheckEquality(std::unordered_set<const Type*>* visited) const {
343     // See isJavaCompatible for similar structure.
344     if (visited->find(this) != visited->end()) {
345         return true;
346     }
347     visited->insert(this);
348     return deepCanCheckEquality(visited);
349 }
350 
deepCanCheckEquality(std::unordered_set<const Type * > *) const351 bool Type::deepCanCheckEquality(std::unordered_set<const Type*>* /* visited */) const {
352     return false;
353 }
354 
getParseStage() const355 Type::ParseStage Type::getParseStage() const {
356     return mParseStage;
357 }
358 
setParseStage(ParseStage stage)359 void Type::setParseStage(ParseStage stage) {
360     CHECK(mParseStage < stage);
361     mParseStage = stage;
362 }
363 
parent()364 Scope* Type::parent() {
365     return mParent;
366 }
367 
parent() const368 const Scope* Type::parent() const {
369     return mParent;
370 }
371 
getCppType(StorageMode,bool) const372 std::string Type::getCppType(StorageMode, bool) const {
373     CHECK(!"Should not be here") << typeName();
374     return std::string();
375 }
376 
decorateCppName(const std::string & name,StorageMode mode,bool specifyNamespaces) const377 std::string Type::decorateCppName(
378         const std::string &name, StorageMode mode, bool specifyNamespaces) const {
379     return getCppType(mode, specifyNamespaces) + " " + name;
380 }
381 
getJavaType(bool) const382 std::string Type::getJavaType(bool /* forInitializer */) const {
383     CHECK(!"Should not be here") << typeName();
384     return std::string();
385 }
386 
getJavaTypeClass() const387 std::string Type::getJavaTypeClass() const {
388     return getJavaType();
389 }
390 
getJavaTypeCast(const std::string & objName) const391 std::string Type::getJavaTypeCast(const std::string& objName) const {
392     return "(" + getJavaType() + ") " + objName;
393 }
394 
getJavaSuffix() const395 std::string Type::getJavaSuffix() const {
396     CHECK(!"Should not be here") << typeName();
397     return std::string();
398 }
399 
getVtsType() const400 std::string Type::getVtsType() const {
401     CHECK(!"Should not be here") << typeName();
402     return std::string();
403 }
404 
getVtsValueName() const405 std::string Type::getVtsValueName() const {
406     CHECK(!"Should not be here") << typeName();
407     return std::string();
408 }
409 
emitReaderWriter(Formatter &,const std::string &,const std::string &,bool,bool,ErrorMode) const410 void Type::emitReaderWriter(
411         Formatter &,
412         const std::string &,
413         const std::string &,
414         bool,
415         bool,
416         ErrorMode) const {
417     CHECK(!"Should not be here") << typeName();
418 }
419 
emitResolveReferences(Formatter &,const std::string &,bool,const std::string &,bool,bool,ErrorMode) const420 void Type::emitResolveReferences(
421         Formatter &,
422         const std::string &,
423         bool,
424         const std::string &,
425         bool,
426         bool,
427         ErrorMode) const {
428     CHECK(!"Should not be here") << typeName();
429 }
430 
emitResolveReferencesEmbedded(Formatter &,size_t,const std::string &,const std::string &,bool,const std::string &,bool,bool,ErrorMode,const std::string &,const std::string &) const431 void Type::emitResolveReferencesEmbedded(
432         Formatter &,
433         size_t,
434         const std::string &,
435         const std::string &,
436         bool,
437         const std::string &,
438         bool,
439         bool,
440         ErrorMode,
441         const std::string &,
442         const std::string &) const {
443     CHECK(!"Should not be here") << typeName();
444 }
445 
emitDump(Formatter & out,const std::string & streamName,const std::string & name) const446 void Type::emitDump(
447         Formatter &out,
448         const std::string &streamName,
449         const std::string &name) const {
450     emitDumpWithMethod(out, streamName, "::android::hardware::toString", name);
451 }
452 
emitDumpWithMethod(Formatter & out,const std::string & streamName,const std::string & methodName,const std::string & name) const453 void Type::emitDumpWithMethod(
454         Formatter &out,
455         const std::string &streamName,
456         const std::string &methodName,
457         const std::string &name) const {
458     out << streamName
459         << " += "
460         << methodName
461         << "("
462         << name
463         << ");\n";
464 }
465 
emitJavaDump(Formatter & out,const std::string & streamName,const std::string & name) const466 void Type::emitJavaDump(
467         Formatter &out,
468         const std::string &streamName,
469         const std::string &name) const {
470     out << streamName << ".append(" << name << ");\n";
471 }
472 
useParentInEmitResolveReferencesEmbedded() const473 bool Type::useParentInEmitResolveReferencesEmbedded() const {
474     return needsResolveReferences();
475 }
476 
emitReaderWriterEmbedded(Formatter &,size_t,const std::string &,const std::string &,bool,const std::string &,bool,bool,ErrorMode,const std::string &,const std::string &) const477 void Type::emitReaderWriterEmbedded(
478         Formatter &,
479         size_t,
480         const std::string &,
481         const std::string &,
482         bool,
483         const std::string &,
484         bool,
485         bool,
486         ErrorMode,
487         const std::string &,
488         const std::string &) const {
489     CHECK(!"Should not be here") << typeName();
490 }
491 
emitJavaReaderWriter(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader) const492 void Type::emitJavaReaderWriter(
493         Formatter &out,
494         const std::string &parcelObj,
495         const std::string &argName,
496         bool isReader) const {
497     emitJavaReaderWriterWithSuffix(
498             out,
499             parcelObj,
500             argName,
501             isReader,
502             getJavaSuffix(),
503             "" /* extra */);
504 }
505 
emitJavaFieldInitializer(Formatter & out,const std::string & fieldName) const506 void Type::emitJavaFieldInitializer(
507         Formatter &out,
508         const std::string &fieldName) const {
509     out << getJavaType()
510         << " "
511         << fieldName
512         << ";\n";
513 }
514 
emitJavaFieldDefaultInitialValue(Formatter &,const std::string &) const515 void Type::emitJavaFieldDefaultInitialValue(Formatter &, const std::string &) const {}
516 
emitJavaFieldReaderWriter(Formatter &,size_t,const std::string &,const std::string &,const std::string &,const std::string &,bool) const517 void Type::emitJavaFieldReaderWriter(
518         Formatter &,
519         size_t,
520         const std::string &,
521         const std::string &,
522         const std::string &,
523         const std::string &,
524         bool) const {
525     CHECK(!"Should not be here") << typeName();
526 }
527 
handleError(Formatter & out,ErrorMode mode) const528 void Type::handleError(Formatter &out, ErrorMode mode) const {
529     switch (mode) {
530         case ErrorMode_Ignore:
531         {
532             out << "/* _hidl_err ignored! */\n\n";
533             break;
534         }
535 
536         case ErrorMode_Goto:
537         {
538             out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
539             break;
540         }
541 
542         case ErrorMode_Break:
543         {
544             out << "if (_hidl_err != ::android::OK) { break; }\n\n";
545             break;
546         }
547 
548         case ErrorMode_Return:
549         {
550             out << "if (_hidl_err != ::android::OK) { return _hidl_err; }\n\n";
551             break;
552         }
553     }
554 }
555 
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) const556 void Type::emitReaderWriterEmbeddedForTypeName(
557         Formatter &out,
558         const std::string &name,
559         bool nameIsPointer,
560         const std::string &parcelObj,
561         bool parcelObjIsPointer,
562         bool isReader,
563         ErrorMode mode,
564         const std::string &parentName,
565         const std::string &offsetText,
566         const std::string &typeName,
567         const std::string &childName,
568         const std::string &funcNamespace) const {
569 
570         const std::string parcelObjDeref =
571         parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
572 
573     const std::string parcelObjPointer =
574         parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
575 
576     const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
577     const std::string namePointer = nameIsPointer ? name : ("&" + name);
578 
579     out << "_hidl_err = ";
580 
581     if (!funcNamespace.empty()) {
582         out << funcNamespace << "::";
583     }
584 
585     out << (isReader ? "readEmbeddedFromParcel(\n" : "writeEmbeddedToParcel(\n");
586 
587     out.indent();
588     out.indent();
589 
590     if (isReader) {
591         out << "const_cast<"
592             << typeName
593             << " &>("
594             << nameDerefed
595             << "),\n";
596     } else {
597         out << nameDerefed
598             << ",\n";
599     }
600 
601     out << (isReader ? parcelObjDeref : parcelObjPointer)
602         << ",\n"
603         << parentName
604         << ",\n"
605         << offsetText;
606 
607     if (!childName.empty()) {
608         out << ", &"
609             << childName;
610     }
611 
612     out << ");\n\n";
613 
614     out.unindent();
615     out.unindent();
616 
617     handleError(out, mode);
618 }
619 
emitTypeDeclarations(Formatter &) const620 void Type::emitTypeDeclarations(Formatter&) const {}
621 
emitTypeForwardDeclaration(Formatter &) const622 void Type::emitTypeForwardDeclaration(Formatter&) const {}
623 
emitGlobalTypeDeclarations(Formatter &) const624 void Type::emitGlobalTypeDeclarations(Formatter&) const {}
625 
emitPackageTypeDeclarations(Formatter &) const626 void Type::emitPackageTypeDeclarations(Formatter&) const {}
627 
emitPackageTypeHeaderDefinitions(Formatter &) const628 void Type::emitPackageTypeHeaderDefinitions(Formatter&) const {}
629 
emitPackageHwDeclarations(Formatter &) const630 void Type::emitPackageHwDeclarations(Formatter&) const {}
631 
emitTypeDefinitions(Formatter &,const std::string &) const632 void Type::emitTypeDefinitions(Formatter&, const std::string&) const {}
633 
emitJavaTypeDeclarations(Formatter &,bool) const634 void Type::emitJavaTypeDeclarations(Formatter&, bool) const {}
635 
needsEmbeddedReadWrite() const636 bool Type::needsEmbeddedReadWrite() const {
637     return false;
638 }
639 
resultNeedsDeref() const640 bool Type::resultNeedsDeref() const {
641     return false;
642 }
643 
needsResolveReferences() const644 bool Type::needsResolveReferences() const {
645     std::unordered_set<const Type*> visited;
646     return needsResolveReferences(&visited);
647 }
648 
needsResolveReferences(std::unordered_set<const Type * > * visited) const649 bool Type::needsResolveReferences(std::unordered_set<const Type*>* visited) const {
650     // See isJavaCompatible for similar structure.
651     if (visited->find(this) != visited->end()) {
652         return false;
653     }
654     visited->insert(this);
655     return deepNeedsResolveReferences(visited);
656 }
657 
deepNeedsResolveReferences(std::unordered_set<const Type * > *) const658 bool Type::deepNeedsResolveReferences(std::unordered_set<const Type*>* /* visited */) const {
659     return false;
660 }
661 
getCppStackType(bool specifyNamespaces) const662 std::string Type::getCppStackType(bool specifyNamespaces) const {
663     return getCppType(StorageMode_Stack, specifyNamespaces);
664 }
665 
getCppResultType(bool specifyNamespaces) const666 std::string Type::getCppResultType(bool specifyNamespaces) const {
667     return getCppType(StorageMode_Result, specifyNamespaces);
668 }
669 
getCppArgumentType(bool specifyNamespaces) const670 std::string Type::getCppArgumentType(bool specifyNamespaces) const {
671     return getCppType(StorageMode_Argument, specifyNamespaces);
672 }
673 
getCppTypeCast(const std::string & objName,bool specifyNamespaces) const674 std::string Type::getCppTypeCast(const std::string& objName, bool specifyNamespaces) const {
675     return "(" + getCppStackType(specifyNamespaces) + ") " + objName;
676 }
677 
emitJavaReaderWriterWithSuffix(Formatter & out,const std::string & parcelObj,const std::string & argName,bool isReader,const std::string & suffix,const std::string & extra) const678 void Type::emitJavaReaderWriterWithSuffix(
679         Formatter &out,
680         const std::string &parcelObj,
681         const std::string &argName,
682         bool isReader,
683         const std::string &suffix,
684         const std::string &extra) const {
685     out << parcelObj
686         << "."
687         << (isReader ? "read" : "write")
688         << suffix
689         << "(";
690 
691     if (isReader) {
692         out << extra;
693     } else {
694         out << (extra.empty() ? "" : (extra + ", "));
695         out << argName;
696     }
697 
698     out << ");\n";
699 }
700 
emitVtsTypeDeclarations(Formatter &) const701 void Type::emitVtsTypeDeclarations(Formatter&) const {}
702 
emitVtsAttributeType(Formatter & out) const703 void Type::emitVtsAttributeType(Formatter& out) const {
704     emitVtsTypeDeclarations(out);
705 }
706 
isJavaCompatible() const707 bool Type::isJavaCompatible() const {
708     std::unordered_set<const Type*> visited;
709     return isJavaCompatible(&visited);
710 }
711 
containsPointer() const712 bool Type::containsPointer() const {
713     std::unordered_set<const Type*> visited;
714     return containsPointer(&visited);
715 }
716 
isJavaCompatible(std::unordered_set<const Type * > * visited) const717 bool Type::isJavaCompatible(std::unordered_set<const Type*>* visited) const {
718     // We need to find al least one path from requested vertex
719     // to not java compatible.
720     // That means that if we have already visited some vertex,
721     // there is no need to determine whether it is java compatible
722     // (and we can assume that it is java compatible),
723     // as if not, the information about that would appear in the
724     // requested vertex through another path.
725     if (visited->find(this) != visited->end()) {
726         return true;
727     }
728     visited->insert(this);
729     return deepIsJavaCompatible(visited);
730 }
731 
containsPointer(std::unordered_set<const Type * > * visited) const732 bool Type::containsPointer(std::unordered_set<const Type*>* visited) const {
733     // See isJavaCompatible for similar structure.
734     if (visited->find(this) != visited->end()) {
735         return false;
736     }
737     visited->insert(this);
738     return deepContainsPointer(visited);
739 }
740 
deepIsJavaCompatible(std::unordered_set<const Type * > *) const741 bool Type::deepIsJavaCompatible(std::unordered_set<const Type*>* /* visited */) const {
742     return true;
743 }
744 
deepContainsPointer(std::unordered_set<const Type * > *) const745 bool Type::deepContainsPointer(std::unordered_set<const Type*>* /* visited */) const {
746     return false;
747 }
748 
getAlignmentAndSize(size_t *,size_t *) const749 void Type::getAlignmentAndSize(
750         size_t * /* align */, size_t * /* size */) const {
751     CHECK(!"Should not be here.");
752 }
753 
appendToExportedTypesVector(std::vector<const Type * > *) const754 void Type::appendToExportedTypesVector(
755         std::vector<const Type *> * /* exportedTypes */) const {
756 }
757 
emitExportedHeader(Formatter &,bool) const758 void Type::emitExportedHeader(Formatter& /* out */, bool /* forJava */) const {}
759 
isNeverStrongReference() const760 bool Type::isNeverStrongReference() const {
761     return false;
762 }
763 
764 ////////////////////////////////////////
765 
TemplatedType(Scope * parent)766 TemplatedType::TemplatedType(Scope* parent) : Type(parent) {}
767 
typeName() const768 std::string TemplatedType::typeName() const {
769     return templatedTypeName() + " of " + mElementType->typeName();
770 }
771 
setElementType(const Reference<Type> & elementType)772 void TemplatedType::setElementType(const Reference<Type>& elementType) {
773     // can only be set once.
774     CHECK(mElementType.isEmptyReference());
775     CHECK(!elementType.isEmptyReference());
776 
777     mElementType = elementType;
778 }
779 
getElementType() const780 const Type* TemplatedType::getElementType() const {
781     return mElementType.get();
782 }
783 
isTemplatedType() const784 bool TemplatedType::isTemplatedType() const {
785     return true;
786 }
787 
getReferences() const788 std::vector<const Reference<Type>*> TemplatedType::getReferences() const {
789     return {&mElementType};
790 }
791 
validate() const792 status_t TemplatedType::validate() const {
793     if (!isCompatibleElementType(mElementType.get())) {
794         std::cerr << "ERROR: " << typeName() /* contains element type */
795                   << " is not supported at " << mElementType.location() << "\n";
796         return UNKNOWN_ERROR;
797     }
798 
799     return Type::validate();
800 }
801 
emitVtsTypeDeclarations(Formatter & out) const802 void TemplatedType::emitVtsTypeDeclarations(Formatter& out) const {
803     out << "type: " << getVtsType() << "\n";
804     out << getVtsValueName() << ": {\n";
805     out.indent();
806     mElementType->emitVtsTypeDeclarations(out);
807     out.unindent();
808     out << "}\n";
809 }
810 
emitVtsAttributeType(Formatter & out) const811 void TemplatedType::emitVtsAttributeType(Formatter& out) const {
812     out << "type: " << getVtsType() << "\n";
813     out << getVtsValueName() << ": {\n";
814     out.indent();
815     mElementType->emitVtsAttributeType(out);
816     out.unindent();
817     out << "}\n";
818 }
819 
820 }  // namespace android
821 
822