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