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