Home | History | Annotate | Download | only in hidl
      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 "ConstantExpression.h"
     18 
     19 #include <android-base/logging.h>
     20 #include <android-base/parseint.h>
     21 #include <stdio.h>
     22 #include <algorithm>
     23 #include <iostream>
     24 #include <sstream>
     25 #include <string>
     26 
     27 #include "EnumType.h"
     28 #include "Scope.h"  // LocalIdentifier
     29 
     30 // The macros are really nasty here. Consider removing
     31 // as many macros as possible.
     32 
     33 #define OPEQ(__y__) (std::string(mOp) == std::string(__y__))
     34 #define COMPUTE_UNARY(__op__)  if (op == std::string(#__op__)) return __op__ val;
     35 #define COMPUTE_BINARY(__op__) if (op == std::string(#__op__)) return lval __op__ rval;
     36 #define OP_IS_BIN_ARITHMETIC  (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
     37 #define OP_IS_BIN_BITFLIP     (OPEQ("|") || OPEQ("^") || OPEQ("&"))
     38 #define OP_IS_BIN_COMP        (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
     39 #define OP_IS_BIN_SHIFT       (OPEQ(">>") || OPEQ("<<"))
     40 #define OP_IS_BIN_LOGICAL     (OPEQ("||") || OPEQ("&&"))
     41 #define SK(__x__) ScalarType::Kind::KIND_##__x__
     42 #define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
     43 
     44 // NOLINT to suppress missing parentheses warnings about __def__.
     45 #define SWITCH_KIND(__cond__, __action__, __def__)           \
     46         switch(__cond__) {                                        \
     47             case SK(BOOL): __action__(bool)                         \
     48             case SK(UINT8): __action__(uint8_t)                     \
     49             case SK(INT8): __action__(int8_t)                       \
     50             case SK(UINT16): __action__(uint16_t)                   \
     51             case SK(INT16): __action__(int16_t)                     \
     52             case SK(UINT32): __action__(uint32_t)                   \
     53             case SK(INT32): __action__(int32_t)                     \
     54             case SK(UINT64): __action__(uint64_t)                   \
     55             case SK(INT64): __action__(int64_t)                     \
     56             default: __def__                        /* NOLINT */    \
     57         }
     58 
     59 namespace android {
     60 
     61 static inline bool isSupported(ScalarType::Kind kind) {
     62     return SK(BOOL) == kind || ScalarType(kind, nullptr /* parent */).isValidEnumStorageType();
     63 }
     64 
     65 /* See docs at the end for details on integral promotion. */
     66 ScalarType::Kind integralPromotion(ScalarType::Kind in) {
     67     return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
     68 }
     69 
     70 /* See docs at the end for details on usual arithmetic conversion. */
     71 ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
     72                                            ScalarType::Kind rgt) {
     73     CHECK(isSupported(lft) && isSupported(rgt));
     74     // Kinds in concern: bool, (u)int[8|16|32|64]
     75     if(lft == rgt) return lft; // easy case
     76     if(lft == SK(BOOL)) return rgt;
     77     if(rgt == SK(BOOL)) return lft;
     78     bool isLftSigned = (lft == SK(INT8))  || (lft == SK(INT16))
     79                     || (lft == SK(INT32)) || (lft == SK(INT64));
     80     bool isRgtSigned = (rgt == SK(INT8))  || (rgt == SK(INT16))
     81                     || (rgt == SK(INT32)) || (rgt == SK(INT64));
     82     if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
     83     ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
     84     ScalarType::Kind signedRank   = isLftSigned ? lft : rgt;
     85     if(unsignedRank >= signedRank) return unsignedRank;
     86     if(signedRank > unsignedRank)  return signedRank;
     87 
     88     // Although there is such rule to return "the unsigned counterpart of
     89     // the signed operand", it should not reach here in our HIDL grammar.
     90     CHECK(false) << "Could not do usual arithmetic conversion for type " << lft << "and" << rgt;
     91     switch(signedRank) {
     92         case SK(INT8):  return SK(UINT8);
     93         case SK(INT16): return SK(UINT16);
     94         case SK(INT32): return SK(UINT32);
     95         case SK(INT64): return SK(UINT64);
     96         default: return SK(UINT64);
     97     }
     98 }
     99 
    100 template <class T>
    101 T handleUnary(const std::string& op, T val) {
    102     COMPUTE_UNARY(+)
    103     COMPUTE_UNARY(-)
    104     COMPUTE_UNARY(!)
    105     COMPUTE_UNARY(~)
    106     // Should not reach here.
    107     SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
    108     return static_cast<T>(0xdeadbeef);
    109 }
    110 
    111 template <class T>
    112 T handleBinaryCommon(T lval, const std::string& op, T rval) {
    113     COMPUTE_BINARY(+)
    114     COMPUTE_BINARY(-)
    115     COMPUTE_BINARY(*)
    116     COMPUTE_BINARY(/)
    117     COMPUTE_BINARY(%)
    118     COMPUTE_BINARY(|)
    119     COMPUTE_BINARY(^)
    120     COMPUTE_BINARY(&)
    121     // comparison operators: return 0 or 1 by nature.
    122     COMPUTE_BINARY(==)
    123     COMPUTE_BINARY(!=)
    124     COMPUTE_BINARY(<)
    125     COMPUTE_BINARY(>)
    126     COMPUTE_BINARY(<=)
    127     COMPUTE_BINARY(>=)
    128     // Should not reach here.
    129     SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
    130                        << lval << " " << op << " " << rval;
    131     return static_cast<T>(0xdeadbeef);
    132 }
    133 
    134 template <class T>
    135 T handleShift(T lval, const std::string& op, int64_t rval) {
    136     // just cast rval to int64_t and it should fit.
    137     COMPUTE_BINARY(>>)
    138     COMPUTE_BINARY(<<)
    139     // Should not reach here.
    140     SHOULD_NOT_REACH() << "Could not handleShift for "
    141                        << lval << " " << op << " " << rval;
    142     return static_cast<T>(0xdeadbeef);
    143 }
    144 
    145 bool handleLogical(bool lval, const std::string& op, bool rval) {
    146     COMPUTE_BINARY(||);
    147     COMPUTE_BINARY(&&);
    148     // Should not reach here.
    149     SHOULD_NOT_REACH() << "Could not handleLogical for "
    150                        << lval << " " << op << " " << rval;
    151     return false;
    152 }
    153 
    154 std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
    155     return ValueOf(kind, 0);
    156 }
    157 
    158 std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
    159     return ValueOf(kind, 1);
    160 }
    161 
    162 std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
    163                                                                 uint64_t value) {
    164     return std::make_unique<LiteralConstantExpression>(kind, value);
    165 }
    166 
    167 bool ConstantExpression::isEvaluated() const {
    168     return mIsEvaluated;
    169 }
    170 
    171 LiteralConstantExpression::LiteralConstantExpression(
    172     ScalarType::Kind kind, uint64_t value, const std::string& expr) {
    173 
    174     CHECK(!expr.empty());
    175     CHECK(isSupported(kind));
    176     mTrivialDescription = true;
    177     mExpr = expr;
    178     mValueKind = kind;
    179     mValue = value;
    180     mIsEvaluated = true;
    181 }
    182 
    183 LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
    184   : LiteralConstantExpression(kind, value, std::to_string(value)) {}
    185 
    186 LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
    187     CHECK(!value.empty());
    188 
    189     bool isLong = false, isUnsigned = false;
    190     bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
    191 
    192     auto rbegin = value.rbegin();
    193     auto rend = value.rend();
    194     for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
    195          ++rbegin) {
    196         isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
    197         isLong |= (*rbegin == 'l' || *rbegin == 'L');
    198     }
    199     std::string newVal(value.begin(), rbegin.base());
    200     CHECK(!newVal.empty());
    201 
    202     uint64_t rawValue = 0;
    203 
    204     bool parseOK = base::ParseUint(newVal, &rawValue);
    205     if (!parseOK) {
    206         return nullptr;
    207     }
    208 
    209     ScalarType::Kind kind;
    210 
    211     // guess literal type.
    212     if(isLong) {
    213         if(isUnsigned) // ul
    214             kind = SK(UINT64);
    215         else // l
    216             kind = SK(INT64);
    217     } else { // no l suffix
    218         if(isUnsigned) { // u
    219             if(rawValue <= UINT32_MAX)
    220                 kind = SK(UINT32);
    221             else
    222                 kind = SK(UINT64);
    223         } else { // no suffix
    224             if(isHex) {
    225                 if(rawValue <= INT32_MAX) // rawValue always >= 0
    226                     kind = SK(INT32);
    227                 else if(rawValue <= UINT32_MAX)
    228                     kind = SK(UINT32);
    229                 else if(rawValue <= INT64_MAX) // rawValue always >= 0
    230                     kind = SK(INT64);
    231                 else if(rawValue <= UINT64_MAX)
    232                     kind = SK(UINT64);
    233                 else
    234                     return nullptr;
    235             } else {
    236                 if(rawValue <= INT32_MAX) // rawValue always >= 0
    237                     kind = SK(INT32);
    238                 else
    239                     kind = SK(INT64);
    240             }
    241         }
    242     }
    243 
    244     return new LiteralConstantExpression(kind, rawValue, value);
    245 }
    246 
    247 void LiteralConstantExpression::evaluate() {
    248     // Evaluated in constructor
    249     CHECK(isEvaluated());
    250 }
    251 
    252 void UnaryConstantExpression::evaluate() {
    253     if (isEvaluated()) return;
    254     CHECK(mUnary->isEvaluated());
    255     mIsEvaluated = true;
    256 
    257     mExpr = std::string("(") + mOp + mUnary->description() + ")";
    258     mValueKind = mUnary->mValueKind;
    259 
    260 #define CASE_UNARY(__type__)                                          \
    261     mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
    262     return;
    263 
    264     SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
    265 }
    266 
    267 void BinaryConstantExpression::evaluate() {
    268     if (isEvaluated()) return;
    269     CHECK(mLval->isEvaluated());
    270     CHECK(mRval->isEvaluated());
    271     mIsEvaluated = true;
    272 
    273     mExpr = std::string("(") + mLval->description() + " " + mOp + " " + mRval->description() + ")";
    274 
    275     bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
    276 
    277     // CASE 1: + - *  / % | ^ & < > <= >= == !=
    278     if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
    279         // promoted kind for both operands.
    280         ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
    281                                                               integralPromotion(mRval->mValueKind));
    282         // result kind.
    283         mValueKind = isArithmeticOrBitflip
    284                     ? promoted // arithmetic or bitflip operators generates promoted type
    285                     : SK(BOOL); // comparison operators generates bool
    286 
    287 #define CASE_BINARY_COMMON(__type__)                                       \
    288     mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
    289                                 static_cast<__type__>(mRval->mValue));     \
    290     return;
    291 
    292         SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
    293     }
    294 
    295     // CASE 2: << >>
    296     std::string newOp = mOp;
    297     if(OP_IS_BIN_SHIFT) {
    298         mValueKind = integralPromotion(mLval->mValueKind);
    299         // instead of promoting rval, simply casting it to int64 should also be good.
    300         int64_t numBits = mRval->cast<int64_t>();
    301         if(numBits < 0) {
    302             // shifting with negative number of bits is undefined in C. In HIDL it
    303             // is defined as shifting into the other direction.
    304             newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
    305             numBits = -numBits;
    306         }
    307 
    308 #define CASE_SHIFT(__type__)                                                    \
    309     mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
    310     return;
    311 
    312         SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
    313     }
    314 
    315     // CASE 3: && ||
    316     if(OP_IS_BIN_LOGICAL) {
    317         mValueKind = SK(BOOL);
    318         // easy; everything is bool.
    319         mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
    320         return;
    321     }
    322 
    323     SHOULD_NOT_REACH();
    324 }
    325 
    326 void TernaryConstantExpression::evaluate() {
    327     if (isEvaluated()) return;
    328     CHECK(mCond->isEvaluated());
    329     CHECK(mTrueVal->isEvaluated());
    330     CHECK(mFalseVal->isEvaluated());
    331     mIsEvaluated = true;
    332 
    333     mExpr = std::string("(") + mCond->description() + "?" + mTrueVal->description() + ":" +
    334             mFalseVal->description() + ")";
    335 
    336     // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
    337     mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
    338 
    339 #define CASE_TERNARY(__type__)                                           \
    340     mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue))   \
    341                            : (static_cast<__type__>(mFalseVal->mValue)); \
    342     return;
    343 
    344     SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
    345 }
    346 
    347 void ReferenceConstantExpression::evaluate() {
    348     if (isEvaluated()) return;
    349     CHECK(mReference->constExpr() != nullptr);
    350 
    351     ConstantExpression* expr = mReference->constExpr();
    352     CHECK(expr->isEvaluated());
    353 
    354     mValueKind = expr->mValueKind;
    355     mValue = expr->mValue;
    356     mIsEvaluated = true;
    357 }
    358 
    359 std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
    360     auto ret = std::make_unique<BinaryConstantExpression>(
    361         this, "+", ConstantExpression::One(baseKind).release());
    362     return ret;
    363 }
    364 
    365 const std::string& ConstantExpression::description() const {
    366     CHECK(isEvaluated());
    367     return mExpr;
    368 }
    369 
    370 bool ConstantExpression::descriptionIsTrivial() const {
    371     CHECK(isEvaluated());
    372     return mTrivialDescription;
    373 }
    374 
    375 std::string ConstantExpression::value() const {
    376     CHECK(isEvaluated());
    377     return rawValue(mValueKind);
    378 }
    379 
    380 std::string ConstantExpression::value(ScalarType::Kind castKind) const {
    381     CHECK(isEvaluated());
    382     return rawValue(castKind);
    383 }
    384 
    385 std::string ConstantExpression::cppValue() const {
    386     CHECK(isEvaluated());
    387     return cppValue(mValueKind);
    388 }
    389 
    390 std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
    391     CHECK(isEvaluated());
    392     std::string literal(rawValue(castKind));
    393     // this is a hack to translate
    394     //       enum x : int64_t {  y = 1l << 63 };
    395     // into
    396     //       enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
    397     // by adding the explicit cast.
    398     // Because 9223372036854775808 is uint64_t, and
    399     // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
    400     // be narrowed to int64_t.
    401     if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
    402         return "static_cast<" +
    403                ScalarType(SK(INT64), nullptr /* parent */).getCppStackType()  // "int64_t"
    404                + ">(" + literal + "ull)";
    405     }
    406 
    407     // add suffix if necessary.
    408     if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
    409     if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
    410     return literal;
    411 }
    412 
    413 std::string ConstantExpression::javaValue() const {
    414     CHECK(isEvaluated());
    415     return javaValue(mValueKind);
    416 }
    417 
    418 std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
    419     CHECK(isEvaluated());
    420     switch(castKind) {
    421         case SK(UINT64): return rawValue(SK(INT64)) + "L";
    422         case SK(INT64):  return rawValue(SK(INT64)) + "L";
    423         case SK(UINT32): return rawValue(SK(INT32));
    424         case SK(UINT16): return rawValue(SK(INT16));
    425         case SK(UINT8) : return rawValue(SK(INT8));
    426         case SK(BOOL)  :
    427             return this->cast<bool>() ? "true" : "false";
    428         default: break;
    429     }
    430     return rawValue(castKind);
    431 }
    432 
    433 std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
    434     CHECK(isEvaluated());
    435 
    436 #define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
    437 
    438     SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
    439 }
    440 
    441 template<typename T>
    442 T ConstantExpression::cast() const {
    443     CHECK(isEvaluated());
    444 
    445 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
    446 
    447     SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
    448 }
    449 
    450 size_t ConstantExpression::castSizeT() const {
    451     CHECK(isEvaluated());
    452     return this->cast<size_t>();
    453 }
    454 
    455 bool ConstantExpression::isReferenceConstantExpression() const {
    456     return false;
    457 }
    458 
    459 std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
    460     const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
    461     std::vector<ConstantExpression*> ret(constRet.size());
    462     std::transform(constRet.begin(), constRet.end(), ret.begin(),
    463                    [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
    464     return ret;
    465 }
    466 
    467 std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
    468     const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
    469     std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
    470     std::transform(constRet.begin(), constRet.end(), ret.begin(),
    471                    [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
    472     return ret;
    473 }
    474 
    475 std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
    476     return {};
    477 }
    478 
    479 status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
    480                                            std::unordered_set<const ConstantExpression*>* visited,
    481                                            bool processBeforeDependencies) {
    482     if (mIsPostParseCompleted) return OK;
    483 
    484     if (visited->find(this) != visited->end()) return OK;
    485     visited->insert(this);
    486 
    487     if (processBeforeDependencies) {
    488         status_t err = func(this);
    489         if (err != OK) return err;
    490     }
    491 
    492     for (auto* nextCE : getConstantExpressions()) {
    493         status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
    494         if (err != OK) return err;
    495     }
    496 
    497     for (auto* nextRef : getReferences()) {
    498         auto* nextCE = nextRef->shallowGet()->constExpr();
    499         CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
    500         status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
    501         if (err != OK) return err;
    502     }
    503 
    504     if (!processBeforeDependencies) {
    505         status_t err = func(this);
    506         if (err != OK) return err;
    507     }
    508 
    509     return OK;
    510 }
    511 
    512 status_t ConstantExpression::recursivePass(
    513     const std::function<status_t(const ConstantExpression*)>& func,
    514     std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
    515     if (mIsPostParseCompleted) return OK;
    516 
    517     if (visited->find(this) != visited->end()) return OK;
    518     visited->insert(this);
    519 
    520     if (processBeforeDependencies) {
    521         status_t err = func(this);
    522         if (err != OK) return err;
    523     }
    524 
    525     for (const auto* nextCE : getConstantExpressions()) {
    526         status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
    527         if (err != OK) return err;
    528     }
    529 
    530     for (const auto* nextRef : getReferences()) {
    531         const auto* nextCE = nextRef->shallowGet()->constExpr();
    532         CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
    533         status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
    534         if (err != OK) return err;
    535     }
    536 
    537     if (!processBeforeDependencies) {
    538         status_t err = func(this);
    539         if (err != OK) return err;
    540     }
    541 
    542     return OK;
    543 }
    544 
    545 ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
    546     status_t status, const ConstantExpression* cycleEnd,
    547     const ReferenceConstantExpression* lastReference)
    548     : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
    549     CHECK(cycleEnd == nullptr || status != OK);
    550     CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
    551 }
    552 
    553 ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
    554     std::unordered_set<const ConstantExpression*>* visited,
    555     std::unordered_set<const ConstantExpression*>* stack) const {
    556     if (stack->find(this) != stack->end()) {
    557         CHECK(isReferenceConstantExpression())
    558             << "Only reference constant expression could be the cycle end";
    559 
    560         std::cerr << "ERROR: Cyclic declaration:\n";
    561         return CheckAcyclicStatus(UNKNOWN_ERROR, this,
    562                                   static_cast<const ReferenceConstantExpression*>(this));
    563     }
    564 
    565     if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
    566     visited->insert(this);
    567     stack->insert(this);
    568 
    569     for (const auto* nextCE : getConstantExpressions()) {
    570         auto err = nextCE->checkAcyclic(visited, stack);
    571         if (err.status != OK) {
    572             return err;
    573         }
    574     }
    575 
    576     for (const auto* nextRef : getReferences()) {
    577         const auto* nextCE = nextRef->shallowGet()->constExpr();
    578         CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
    579         auto err = nextCE->checkAcyclic(visited, stack);
    580 
    581         if (err.status != OK) {
    582             if (err.cycleEnd == nullptr) return err;
    583 
    584             // Only ReferenceConstantExpression has references,
    585             CHECK(isReferenceConstantExpression())
    586                 << "Only reference constant expression could have refereneces";
    587 
    588             // mExpr is defined explicitly before evaluation
    589             std::cerr << "  '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
    590                       << nextRef->location() << "\n";
    591 
    592             if (err.cycleEnd == this) {
    593                 return CheckAcyclicStatus(err.status);
    594             }
    595             return CheckAcyclicStatus(err.status, err.cycleEnd,
    596                                       static_cast<const ReferenceConstantExpression*>(this));
    597         }
    598     }
    599 
    600     CHECK(stack->find(this) != stack->end());
    601     stack->erase(this);
    602     return CheckAcyclicStatus(OK);
    603 }
    604 
    605 void ConstantExpression::setPostParseCompleted() {
    606     CHECK(!mIsPostParseCompleted);
    607     mIsPostParseCompleted = true;
    608 }
    609 
    610 std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
    611     return {};
    612 }
    613 
    614 UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
    615     : mUnary(value), mOp(op) {}
    616 
    617 std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
    618     return {mUnary};
    619 }
    620 
    621 BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
    622                                                    ConstantExpression* rval)
    623     : mLval(lval), mRval(rval), mOp(op) {}
    624 
    625 std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
    626     return {mLval, mRval};
    627 }
    628 
    629 TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
    630                                                      ConstantExpression* trueVal,
    631                                                      ConstantExpression* falseVal)
    632     : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
    633 
    634 std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
    635     return {mCond, mTrueVal, mFalseVal};
    636 }
    637 
    638 ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
    639                                                          const std::string& expr)
    640     : mReference(value) {
    641     mExpr = expr;
    642     mTrivialDescription = mExpr.empty();
    643 }
    644 
    645 bool ReferenceConstantExpression::isReferenceConstantExpression() const {
    646     return true;
    647 }
    648 
    649 std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
    650     // Returns reference instead
    651     return {};
    652 }
    653 
    654 std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
    655     return {&mReference};
    656 }
    657 
    658 /*
    659 
    660 Evaluating expressions in HIDL language
    661 
    662 The following rules are mostly like that in:
    663 http://en.cppreference.com/w/cpp/language/operator_arithmetic
    664 http://en.cppreference.com/w/cpp/language/operator_logical
    665 http://en.cppreference.com/w/cpp/language/operator_comparison
    666 http://en.cppreference.com/w/cpp/language/operator_other
    667 
    668 The type of literal is the first type which the value
    669 can fit from the list of types depending on the suffix and bases.
    670 
    671 suffix              decimal bases           hexadecimal bases
    672 no suffix           int32_t                 int32_t
    673                     int64_t                 uint32_t
    674                                             int64_t
    675                                             uint64_t
    676 
    677 u/U                 uint32_t                (same as left)
    678                     uint64_t
    679 
    680 l/L                 int64_t                 int64_t
    681 
    682 ul/UL/uL/Ul         uint64_t                uint64_t
    683 
    684 
    685 Note: There are no negative integer literals.
    686       -1 is the unary minus applied to 1.
    687 
    688 Unary arithmetic and bitwise operators (~ + -):
    689   don't change the type of the argument.
    690   (so -1u = -(1u) has type uint32_t)
    691 
    692 Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
    693 1. Integral promotion is first applied on both sides.
    694 2. If both operands have the same type, no promotion is necessary.
    695 3. Usual arithmetic conversions.
    696 
    697 Integral promotion: if an operand is of a type with less than 32 bits,
    698 (including bool), it is promoted to int32_t.
    699 
    700 Usual arithmetic conversions:
    701 1. If operands are both signed or both unsigned, lesser conversion rank is
    702    converted to greater conversion rank.
    703 2. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
    704 3. Otherwise, if signed's type can hold all values in unsigned's type,
    705    -> signed's type
    706 4. Otherwise, both converted to the unsigned counterpart of the signed operand's
    707    type.
    708 rank: bool < int8_t < int16_t < int32_t < int64_t
    709 
    710 
    711 Shift operators (<< >>):
    712 1. Integral promotion is applied on both sides.
    713 2. For unsigned a, a << b discards bits that shifts out.
    714    For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
    715    For signed negative a, a << b gives error.
    716 3. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
    717    For signed negative a, a >> b discards bits that shifts out, and the signed
    718    bit gets extended. ("arithmetic right shift")
    719 4. Shifting with negative number of bits is undefined. (Currently, the
    720    parser will shift into the other direction. This behavior may change.)
    721 5. Shifting with number of bits exceeding the width of the type is undefined.
    722    (Currently, 1 << 32 == 1. This behavior may change.)
    723 
    724 Logical operators (!, &&, ||):
    725 1. Convert first operand to bool. (true if non-zero, false otherwise)
    726 2. If short-circuited, return the result as type bool, value 1 or 0.
    727 3. Otherwise, convert second operand to bool, evaluate the result, and return
    728    the result in the same fashion.
    729 
    730 Arithmetic comparison operators (< > <= >= == !=):
    731 1. Promote operands in the same way as binary arithmetic and bitwise operators.
    732    (Integral promotion + Usual arithmetic conversions)
    733 2. Return type bool, value 0 or 1 the same way as logical operators.
    734 
    735 Ternary conditional operator (?:):
    736 1. Evaluate the conditional and evaluate the operands.
    737 2. Return type of expression is the type under usual arithmetic conversions on
    738    the second and third operand. (No integral promotions necessary.)
    739 
    740 */
    741 
    742 }  // namespace android
    743 
    744