EnumType.cpp revision a15f8091d2d4312a16edfcebccb13b3ea4782c29
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 "EnumType.h"
18
19#include <hidl-util/Formatter.h>
20#include <inttypes.h>
21#include <unordered_map>
22
23#include "Annotation.h"
24#include "Location.h"
25#include "ScalarType.h"
26
27namespace android {
28
29EnumType::EnumType(const char* localName, const Location& location,
30                   const Reference<Type>& storageType, Scope* parent)
31    : Scope(localName, location, parent), mValues(), mStorageType(storageType) {
32    BitFieldType* bitfieldType = new BitFieldType();
33    bitfieldType->setElementType(Reference<Type>(this, Location()));
34    mBitfieldType.set(bitfieldType);
35}
36
37const Type *EnumType::storageType() const {
38    return mStorageType;
39}
40
41const std::vector<EnumValue *> &EnumType::values() const {
42    return mValues;
43}
44
45void EnumType::addValue(EnumValue* value) {
46    CHECK(value != nullptr);
47    mValues.push_back(value);
48}
49
50status_t EnumType::resolveInheritance() {
51    const EnumType* prevType = nullptr;
52    EnumValue* prevValue = nullptr;
53
54    for (const auto* type : superTypeChain()) {
55        if (!type->values().empty()) {
56            prevType = type;
57            prevValue = type->values().back();
58            break;
59        }
60    }
61
62    for (auto* value : mValues) {
63        value->autofill(prevType, prevValue, mStorageType->resolveToScalarType());
64        prevType = this;
65        prevValue = value;
66    }
67
68    return Scope::resolveInheritance();
69}
70
71status_t EnumType::evaluate() {
72    status_t err = mStorageType->callForReference(&Type::evaluate);
73    if (err != OK) return err;
74
75    for (auto* value : mValues) {
76        err = value->evaluate();
77        if (err != OK) return err;
78    }
79    return Scope::evaluate();
80}
81
82status_t EnumType::validate() const {
83    CHECK(getSubTypes().empty());
84
85    status_t err = mStorageType->callForReference(&Type::validate);
86    if (err != OK) return err;
87
88    for (auto* value : mValues) {
89        err = value->validate();
90        if (err != OK) return err;
91    }
92
93    if (!isElidableType() || !mStorageType->isValidEnumStorageType()) {
94        std::cerr << "ERROR: Invalid enum storage type (" << (mStorageType)->typeName()
95                  << ") specified at " << mStorageType.location() << "\n";
96        return UNKNOWN_ERROR;
97    }
98
99    err = validateUniqueNames();
100    if (err != OK) return err;
101
102    return Scope::validate();
103}
104
105status_t EnumType::validateUniqueNames() const {
106    std::unordered_map<std::string, const EnumType*> registeredValueNames;
107    for (const auto* type : superTypeChain()) {
108        for (const auto* enumValue : type->mValues) {
109            // No need to check super value uniqueness
110            registeredValueNames[enumValue->name()] = type;
111        }
112    }
113
114    for (const auto* value : mValues) {
115        auto registered = registeredValueNames.find(value->name());
116
117        if (registered != registeredValueNames.end()) {
118            const EnumType* definedInType = registered->second;
119
120            if (definedInType == this) {
121                // Defined in this enum
122                std::cerr << "ERROR: Redefinition of value '" << value->name() << "'";
123            } else {
124                // Defined in super enum
125                std::cerr << "ERROR: Redefinition of value '" << value->name() << "define in enum '"
126                          << definedInType->fullName() << "'";
127            }
128            std::cerr << " at " << value->location() << "\n";
129            return UNKNOWN_ERROR;
130        }
131
132        registeredValueNames[value->name()] = this;
133    }
134
135    return OK;
136}
137
138bool EnumType::isElidableType() const {
139    return mStorageType->isElidableType();
140}
141
142const ScalarType *EnumType::resolveToScalarType() const {
143    return mStorageType->resolveToScalarType();
144}
145
146std::string EnumType::typeName() const {
147    return "enum " + localName();
148}
149
150bool EnumType::isEnum() const {
151    return true;
152}
153
154bool EnumType::canCheckEquality() const {
155    return true;
156}
157
158std::string EnumType::getCppType(StorageMode,
159                                 bool /* specifyNamespaces */) const {
160    return fullName();
161}
162
163std::string EnumType::getJavaType(bool forInitializer) const {
164    return mStorageType->resolveToScalarType()->getJavaType(forInitializer);
165}
166
167std::string EnumType::getJavaSuffix() const {
168    return mStorageType->resolveToScalarType()->getJavaSuffix();
169}
170
171std::string EnumType::getJavaWrapperType() const {
172    return mStorageType->resolveToScalarType()->getJavaWrapperType();
173}
174
175std::string EnumType::getVtsType() const {
176    return "TYPE_ENUM";
177}
178
179BitFieldType* EnumType::getBitfieldType() const {
180    return mBitfieldType;
181}
182
183LocalIdentifier *EnumType::lookupIdentifier(const std::string &name) const {
184    std::vector<const EnumType*> chain = typeChain();
185    for (auto it = chain.begin(); it != chain.end(); ++it) {
186        const auto &type = *it;
187        for(EnumValue *v : type->values()) {
188            if(v->name() == name) {
189                return v;
190            }
191        }
192    }
193    return nullptr;
194}
195
196void EnumType::emitReaderWriter(
197        Formatter &out,
198        const std::string &name,
199        const std::string &parcelObj,
200        bool parcelObjIsPointer,
201        bool isReader,
202        ErrorMode mode) const {
203    const ScalarType *scalarType = mStorageType->resolveToScalarType();
204    CHECK(scalarType != NULL);
205
206    scalarType->emitReaderWriterWithCast(
207            out,
208            name,
209            parcelObj,
210            parcelObjIsPointer,
211            isReader,
212            mode,
213            true /* needsCast */);
214}
215
216void EnumType::emitJavaFieldReaderWriter(
217        Formatter &out,
218        size_t depth,
219        const std::string &parcelName,
220        const std::string &blobName,
221        const std::string &fieldName,
222        const std::string &offset,
223        bool isReader) const {
224    return mStorageType->emitJavaFieldReaderWriter(
225            out, depth, parcelName, blobName, fieldName, offset, isReader);
226}
227
228status_t EnumType::emitTypeDeclarations(Formatter &out) const {
229    const ScalarType *scalarType = mStorageType->resolveToScalarType();
230    CHECK(scalarType != nullptr);
231
232    const std::string storageType = scalarType->getCppStackType();
233
234    out << "enum class "
235        << localName()
236        << " : "
237        << storageType
238        << " {\n";
239
240    out.indent();
241
242    std::vector<const EnumType*> chain = typeChain();
243
244    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
245        const auto &type = *it;
246
247        for (const auto &entry : type->values()) {
248            out << entry->name();
249
250            std::string value = entry->cppValue(scalarType->getKind());
251            CHECK(!value.empty()); // use autofilled values for c++.
252            out << " = " << value;
253
254            out << ",";
255
256            std::string comment = entry->comment();
257            if (!comment.empty() && comment != value) {
258                out << " // " << comment;
259            }
260
261            out << "\n";
262        }
263    }
264
265    out.unindent();
266    out << "};\n\n";
267
268    return OK;
269}
270
271void EnumType::emitEnumBitwiseOperator(
272        Formatter &out,
273        bool lhsIsEnum,
274        bool rhsIsEnum,
275        const std::string &op) const {
276    const ScalarType *scalarType = mStorageType->resolveToScalarType();
277    CHECK(scalarType != nullptr);
278
279    const std::string storageType = scalarType->getCppStackType();
280
281    out << "constexpr "
282        << storageType
283        << " operator"
284        << op
285        << "(const "
286        << (lhsIsEnum ? fullName() : storageType)
287        << " lhs, const "
288        << (rhsIsEnum ? fullName() : storageType)
289        << " rhs) {\n";
290
291    out.indent([&] {
292        out << "return static_cast<"
293            << storageType
294            << ">(";
295
296        if (lhsIsEnum) {
297            out << "static_cast<"
298                << storageType
299                << ">(lhs)";
300        } else {
301            out << "lhs";
302        }
303        out << " " << op << " ";
304        if (rhsIsEnum) {
305            out << "static_cast<"
306                << storageType
307                << ">(rhs)";
308        } else {
309            out << "rhs";
310        }
311        out << ");\n";
312    });
313
314    out << "}\n\n";
315}
316
317void EnumType::emitBitFieldBitwiseAssignmentOperator(
318        Formatter &out,
319        const std::string &op) const {
320    const ScalarType *scalarType = mStorageType->resolveToScalarType();
321    CHECK(scalarType != nullptr);
322
323    const std::string storageType = scalarType->getCppStackType();
324
325    out << "constexpr " << storageType << " &operator" << op << "=("
326        << storageType << "& v, const " << fullName() << " e) {\n";
327
328    out.indent([&] {
329        out << "v " << op << "= static_cast<" << storageType << ">(e);\n";
330        out << "return v;\n";
331    });
332
333    out << "}\n\n";
334}
335
336status_t EnumType::emitGlobalTypeDeclarations(Formatter &out) const {
337    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
338    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "|");
339    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "|");
340    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
341    emitEnumBitwiseOperator(out, false /* lhsIsEnum */, true  /* rhsIsEnum */, "&");
342    emitEnumBitwiseOperator(out, true  /* lhsIsEnum */, false /* rhsIsEnum */, "&");
343
344    emitBitFieldBitwiseAssignmentOperator(out, "|");
345    emitBitFieldBitwiseAssignmentOperator(out, "&");
346
347    // toString for bitfields, equivalent to dumpBitfield in Java
348    out << "template<typename>\n"
349        << "std::string toString("
350        << resolveToScalarType()->getCppArgumentType()
351        << " o);\n";
352    out << "template<>\n"
353        << "std::string toString<" << getCppStackType() << ">("
354        << resolveToScalarType()->getCppArgumentType()
355        << " o);\n\n";
356
357    // toString for enum itself
358    out << "std::string toString("
359        << getCppArgumentType()
360        << " o);\n\n";
361
362    return OK;
363}
364
365status_t EnumType::emitTypeDefinitions(Formatter& out, const std::string& /* prefix */) const {
366    const ScalarType *scalarType = mStorageType->resolveToScalarType();
367    CHECK(scalarType != NULL);
368
369    out << "template<>\n"
370        << "std::string toString<" << getCppStackType() << ">("
371        << scalarType->getCppArgumentType()
372        << " o) ";
373    out.block([&] {
374        // include toHexString for scalar types
375        out << "using ::android::hardware::details::toHexString;\n"
376            << "std::string os;\n"
377            << getBitfieldType()->getCppStackType() << " flipped = 0;\n"
378            << "bool first = true;\n";
379        for (EnumValue *value : values()) {
380            std::string valueName = fullName() + "::" + value->name();
381            out.sIf("(o & " + valueName + ")" +
382                    " == static_cast<" + scalarType->getCppStackType() +
383                    ">(" + valueName + ")", [&] {
384                out << "os += (first ? \"\" : \" | \");\n"
385                    << "os += \"" << value->name() << "\";\n"
386                    << "first = false;\n"
387                    << "flipped |= " << valueName << ";\n";
388            }).endl();
389        }
390        // put remaining bits
391        out.sIf("o != flipped", [&] {
392            out << "os += (first ? \"\" : \" | \");\n";
393            scalarType->emitHexDump(out, "os", "o & (~flipped)");
394        });
395        out << "os += \" (\";\n";
396        scalarType->emitHexDump(out, "os", "o");
397        out << "os += \")\";\n";
398
399        out << "return os;\n";
400    }).endl().endl();
401
402    out << "std::string toString("
403        << getCppArgumentType()
404        << " o) ";
405
406    out.block([&] {
407        out << "using ::android::hardware::details::toHexString;\n";
408        for (EnumValue *value : values()) {
409            out.sIf("o == " + fullName() + "::" + value->name(), [&] {
410                out << "return \"" << value->name() << "\";\n";
411            }).endl();
412        }
413        out << "std::string os;\n";
414        scalarType->emitHexDump(out, "os",
415            "static_cast<" + scalarType->getCppStackType() + ">(o)");
416        out << "return os;\n";
417    }).endl().endl();
418
419    return OK;
420}
421
422status_t EnumType::emitJavaTypeDeclarations(Formatter &out, bool atTopLevel) const {
423    const ScalarType *scalarType = mStorageType->resolveToScalarType();
424    CHECK(scalarType != NULL);
425
426    out << "public "
427        << (atTopLevel ? "" : "static ")
428        << "final class "
429        << localName()
430        << " {\n";
431
432    out.indent();
433
434    const std::string typeName =
435        scalarType->getJavaType(false /* forInitializer */);
436
437    std::vector<const EnumType*> chain = typeChain();
438
439    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
440        const auto &type = *it;
441
442        for (const auto &entry : type->values()) {
443            out << "public static final "
444                << typeName
445                << " "
446                << entry->name()
447                << " = ";
448
449            // javaValue will make the number signed.
450            std::string value = entry->javaValue(scalarType->getKind());
451            CHECK(!value.empty()); // use autofilled values for java.
452            out << value;
453
454            out << ";";
455
456            std::string comment = entry->comment();
457            if (!comment.empty() && comment != value) {
458                out << " // " << comment;
459            }
460
461            out << "\n";
462        }
463    }
464
465    out << "public static final String toString("
466        << typeName << " o) ";
467    out.block([&] {
468        for (EnumValue *value : values()) {
469            out.sIf("o == " + value->name(), [&] {
470                out << "return \"" << value->name() << "\";\n";
471            }).endl();
472        }
473        out << "return \"0x\" + ";
474        scalarType->emitConvertToJavaHexString(out, "o");
475        out << ";\n";
476    }).endl();
477
478    auto bitfieldType = getBitfieldType()->getJavaType(false /* forInitializer */);
479    auto bitfieldWrapperType = getBitfieldType()->getJavaWrapperType();
480    out << "\n"
481        << "public static final String dumpBitfield("
482        << bitfieldType << " o) ";
483    out.block([&] {
484        out << "java.util.ArrayList<String> list = new java.util.ArrayList<>();\n";
485        out << bitfieldType << " flipped = 0;\n";
486        for (EnumValue *value : values()) {
487            if (value->constExpr()->castSizeT() == 0) {
488                out << "list.add(\"" << value->name() << "\"); // " << value->name() << " == 0\n";
489                continue;
490            }
491            out.sIf("(o & " + value->name() + ") == " + value->name(), [&] {
492                out << "list.add(\"" << value->name() << "\");\n";
493                out << "flipped |= " << value->name() << ";\n";
494            }).endl();
495        }
496        // put remaining bits
497        out.sIf("o != flipped", [&] {
498            out << "list.add(\"0x\" + ";
499            scalarType->emitConvertToJavaHexString(out, "o & (~flipped)");
500            out << ");\n";
501        }).endl();
502        out << "return String.join(\" | \", list);\n";
503    }).endl().endl();
504
505    out.unindent();
506    out << "};\n\n";
507
508    return OK;
509}
510
511status_t EnumType::emitVtsTypeDeclarations(Formatter &out) const {
512    const ScalarType *scalarType = mStorageType->resolveToScalarType();
513
514    out << "name: \"" << fullName() << "\"\n";
515    out << "type: " << getVtsType() << "\n";
516    out << "enum_value: {\n";
517    out.indent();
518
519    out << "scalar_type: \""
520        << scalarType->getVtsScalarType()
521        << "\"\n\n";
522    std::vector<const EnumType*> chain = typeChain();
523
524    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
525        const auto &type = *it;
526
527        for (const auto &entry : type->values()) {
528            out << "enumerator: \"" << entry->name() << "\"\n";
529            out << "scalar_value: {\n";
530            out.indent();
531            // use autofilled values for vts.
532            std::string value = entry->value(scalarType->getKind());
533            CHECK(!value.empty());
534            out << mStorageType->resolveToScalarType()->getVtsScalarType()
535                << ": "
536                << value
537                << "\n";
538            out.unindent();
539            out << "}\n";
540        }
541    }
542
543    out.unindent();
544    out << "}\n";
545    return OK;
546}
547
548status_t EnumType::emitVtsAttributeType(Formatter &out) const {
549    out << "type: " << getVtsType() << "\n";
550    out << "predefined_type: \"" << fullName() << "\"\n";
551    return OK;
552}
553
554void EnumType::emitJavaDump(
555        Formatter &out,
556        const std::string &streamName,
557        const std::string &name) const {
558    out << streamName << ".append(" << fqName().javaName() << ".toString("
559        << name << "));\n";
560}
561
562std::vector<const EnumType*> EnumType::typeChain() const {
563    std::vector<const EnumType*> types;
564    for (const EnumType* type = this; type != nullptr;) {
565        types.push_back(type);
566
567        const Type* superType = type->storageType();
568        if (superType != nullptr && superType->isEnum()) {
569            type = static_cast<const EnumType*>(superType);
570        } else {
571            type = nullptr;
572        }
573    }
574
575    return types;
576}
577
578std::vector<const EnumType*> EnumType::superTypeChain() const {
579    const Type* superType = storageType();
580    if (superType == nullptr || !superType->isEnum()) {
581        return {};
582    }
583    return static_cast<const EnumType*>(superType)->typeChain();
584}
585
586void EnumType::getAlignmentAndSize(size_t *align, size_t *size) const {
587    mStorageType->getAlignmentAndSize(align, size);
588}
589
590const Annotation *EnumType::findExportAnnotation() const {
591    for (const auto &annotation : annotations()) {
592        if (annotation->name() == "export") {
593            return annotation;
594        }
595    }
596
597    return nullptr;
598}
599
600void EnumType::appendToExportedTypesVector(
601        std::vector<const Type *> *exportedTypes) const {
602    if (findExportAnnotation() != nullptr) {
603        exportedTypes->push_back(this);
604    }
605}
606
607status_t EnumType::emitExportedHeader(Formatter &out, bool forJava) const {
608    const Annotation *annotation = findExportAnnotation();
609    CHECK(annotation != nullptr);
610
611    std::string name = localName();
612
613    const AnnotationParam *nameParam = annotation->getParam("name");
614    if (nameParam != nullptr) {
615        name = nameParam->getSingleString();
616    }
617
618    bool exportParent = true;
619    const AnnotationParam *exportParentParam = annotation->getParam("export_parent");
620    if (exportParentParam != nullptr) {
621        exportParent = exportParentParam->getSingleBool();
622    }
623
624    std::string valuePrefix;
625    const AnnotationParam *prefixParam = annotation->getParam("value_prefix");
626    if (prefixParam != nullptr) {
627        valuePrefix = prefixParam->getSingleString();
628    }
629
630    std::string valueSuffix;
631    const AnnotationParam *suffixParam = annotation->getParam("value_suffix");
632    if (suffixParam != nullptr) {
633        valueSuffix = suffixParam->getSingleString();
634    }
635
636    const ScalarType *scalarType = mStorageType->resolveToScalarType();
637    CHECK(scalarType != nullptr);
638
639    std::vector<const EnumType *> chain;
640    if (exportParent) {
641        chain = typeChain();
642    } else {
643        chain = { this };
644    }
645
646    if (forJava) {
647        if (!name.empty()) {
648            out << "public final class "
649                << name
650                << " {\n";
651
652            out.indent();
653        } else {
654            out << "// Values declared in " << localName() << " follow.\n";
655        }
656
657        const std::string typeName =
658            scalarType->getJavaType(false /* forInitializer */);
659
660        for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
661            const auto &type = *it;
662
663            for (const auto &entry : type->values()) {
664                out << "public static final "
665                    << typeName
666                    << " "
667                    << valuePrefix
668                    << entry->name()
669                    << valueSuffix
670                    << " = ";
671
672                // javaValue will make the number signed.
673                std::string value = entry->javaValue(scalarType->getKind());
674                CHECK(!value.empty()); // use autofilled values for java.
675                out << value;
676
677                out << ";";
678
679                std::string comment = entry->comment();
680                if (!comment.empty() && comment != value) {
681                    out << " // " << comment;
682                }
683
684                out << "\n";
685            }
686        }
687
688        if (!name.empty()) {
689            out.unindent();
690            out << "};\n";
691        }
692        out << "\n";
693
694        return OK;
695    }
696
697    if (!name.empty()) {
698        out << "typedef ";
699    }
700
701    out << "enum {\n";
702
703    out.indent();
704
705    for (auto it = chain.rbegin(); it != chain.rend(); ++it) {
706        const auto &type = *it;
707
708        for (const auto &entry : type->values()) {
709            out << valuePrefix << entry->name() << valueSuffix;
710
711            std::string value = entry->cppValue(scalarType->getKind());
712            CHECK(!value.empty()); // use autofilled values for c++.
713            out << " = " << value;
714
715            out << ",";
716
717            std::string comment = entry->comment();
718            if (!comment.empty() && comment != value) {
719                out << " // " << comment;
720            }
721
722            out << "\n";
723        }
724    }
725
726    out.unindent();
727    out << "}";
728
729    if (!name.empty()) {
730        out << " " << name;
731    }
732
733    out << ";\n\n";
734
735    return OK;
736}
737
738////////////////////////////////////////////////////////////////////////////////
739
740EnumValue::EnumValue(const char* name, ConstantExpression* value, const Location& location)
741    : mName(name), mValue(value), mLocation(location), mIsAutoFill(false) {}
742
743std::string EnumValue::name() const {
744    return mName;
745}
746
747std::string EnumValue::value(ScalarType::Kind castKind) const {
748    CHECK(mValue != nullptr);
749    return mValue->value(castKind);
750}
751
752std::string EnumValue::cppValue(ScalarType::Kind castKind) const {
753    CHECK(mValue != nullptr);
754    return mValue->cppValue(castKind);
755}
756std::string EnumValue::javaValue(ScalarType::Kind castKind) const {
757    CHECK(mValue != nullptr);
758    return mValue->javaValue(castKind);
759}
760
761std::string EnumValue::comment() const {
762    CHECK(mValue != nullptr);
763    return mValue->description();
764}
765
766ConstantExpression *EnumValue::constExpr() const {
767    CHECK(mValue != nullptr);
768    return mValue;
769}
770
771void EnumValue::autofill(const EnumType* prevType, EnumValue* prevValue, const ScalarType* type) {
772    // Value is defined explicitly
773    if (mValue != nullptr) return;
774
775    CHECK((prevType == nullptr) == (prevValue == nullptr));
776
777    mIsAutoFill = true;
778    if (prevValue == nullptr) {
779        mValue = ConstantExpression::Zero(type->getKind()).release();
780    } else {
781        std::string description = prevType->fullName() + "." + prevValue->name() + " implicitly";
782        auto* prevReference = new ReferenceConstantExpression(
783            Reference<LocalIdentifier>(prevValue, mLocation), description);
784        mValue = prevReference->addOne(type->getKind()).release();
785    }
786}
787
788bool EnumValue::isAutoFill() const {
789    return mIsAutoFill;
790}
791
792bool EnumValue::isEnumValue() const {
793    return true;
794}
795
796status_t EnumValue::evaluate() {
797    mValue->evaluate();
798    return OK;
799}
800
801status_t EnumValue::validate() const {
802    // TODO(b/64358435) move isSupported from ConstantExpression
803    return OK;
804}
805
806const Location& EnumValue::location() const {
807    return mLocation;
808}
809
810////////////////////////////////////////////////////////////////////////////////
811
812bool BitFieldType::isBitField() const {
813    return true;
814}
815
816std::string BitFieldType::typeName() const {
817    return "mask" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
818}
819
820bool BitFieldType::isCompatibleElementType(Type* elementType) const {
821    return elementType->isEnum();
822}
823
824const ScalarType *BitFieldType::resolveToScalarType() const {
825    return mElementType->resolveToScalarType();
826}
827
828std::string BitFieldType::getCppType(StorageMode mode,
829                                 bool specifyNamespaces) const {
830    return resolveToScalarType()->getCppType(mode, specifyNamespaces);
831}
832
833std::string BitFieldType::getJavaType(bool forInitializer) const {
834    return resolveToScalarType()->getJavaType(forInitializer);
835}
836
837std::string BitFieldType::getJavaSuffix() const {
838    return resolveToScalarType()->getJavaSuffix();
839}
840
841std::string BitFieldType::getJavaWrapperType() const {
842    return resolveToScalarType()->getJavaWrapperType();
843}
844
845std::string BitFieldType::getVtsType() const {
846    return "TYPE_MASK";
847}
848
849bool BitFieldType::isElidableType() const {
850    return resolveToScalarType()->isElidableType();
851}
852
853bool BitFieldType::canCheckEquality() const {
854    return resolveToScalarType()->canCheckEquality();
855}
856
857status_t BitFieldType::emitVtsAttributeType(Formatter &out) const {
858    out << "type: " << getVtsType() << "\n";
859    out << "scalar_type: \""
860        << mElementType->resolveToScalarType()->getVtsScalarType()
861        << "\"\n";
862    out << "predefined_type: \"" << static_cast<NamedType*>(mElementType.get())->fullName()
863        << "\"\n";
864    return OK;
865}
866
867void BitFieldType::getAlignmentAndSize(size_t *align, size_t *size) const {
868    resolveToScalarType()->getAlignmentAndSize(align, size);
869}
870
871void BitFieldType::emitReaderWriter(
872        Formatter &out,
873        const std::string &name,
874        const std::string &parcelObj,
875        bool parcelObjIsPointer,
876        bool isReader,
877        ErrorMode mode) const {
878    resolveToScalarType()->emitReaderWriterWithCast(
879            out,
880            name,
881            parcelObj,
882            parcelObjIsPointer,
883            isReader,
884            mode,
885            true /* needsCast */);
886}
887
888EnumType* BitFieldType::getEnumType() const {
889    CHECK(mElementType->isEnum());
890    return static_cast<EnumType*>(mElementType.get());
891}
892
893// a bitfield maps to the underlying scalar type in C++, so operator<< is
894// already defined. We can still emit useful information if the bitfield is
895// in a struct / union by overriding emitDump as below.
896void BitFieldType::emitDump(
897        Formatter &out,
898        const std::string &streamName,
899        const std::string &name) const {
900    out << streamName << " += "<< getEnumType()->fqName().cppNamespace()
901        << "::toString<" << getEnumType()->getCppStackType()
902        << ">(" << name << ");\n";
903}
904
905void BitFieldType::emitJavaDump(
906        Formatter &out,
907        const std::string &streamName,
908        const std::string &name) const {
909    out << streamName << ".append(" << getEnumType()->fqName().javaName() << ".dumpBitfield("
910        << name << "));\n";
911}
912
913void BitFieldType::emitJavaFieldReaderWriter(
914        Formatter &out,
915        size_t depth,
916        const std::string &parcelName,
917        const std::string &blobName,
918        const std::string &fieldName,
919        const std::string &offset,
920        bool isReader) const {
921    return resolveToScalarType()->emitJavaFieldReaderWriter(
922            out, depth, parcelName, blobName, fieldName, offset, isReader);
923}
924
925}  // namespace android
926
927