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