blob: 9413c9a35831777951e8506b42a47ad26d746ed5 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Yifan Hong52165692016-08-12 18:06:40 -070017#include "ConstantExpression.h"
18
Yifan Hong57886972016-08-17 10:42:15 -070019#include <android-base/logging.h>
Timur Iskhakovb58f4182017-08-29 15:19:24 -070020#include <android-base/parseint.h>
21#include <stdio.h>
22#include <algorithm>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070023#include <iostream>
Yifan Hong57886972016-08-17 10:42:15 -070024#include <sstream>
Timur Iskhakovb58f4182017-08-29 15:19:24 -070025#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070026
Yifan Hongf24fa852016-09-23 11:03:15 -070027#include "EnumType.h"
Timur Iskhakov7296af12017-08-09 21:52:48 +000028#include "Scope.h" // LocalIdentifier
Yifan Hongf24fa852016-09-23 11:03:15 -070029
Yifan Hong57886972016-08-17 10:42:15 -070030// The macros are really nasty here. Consider removing
31// as many macros as possible.
32
Timur Iskhakovd27580c2017-08-09 20:14:52 -070033#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;
Yifan Hong57886972016-08-17 10:42:15 -070036#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__
Yifan Hongf24fa852016-09-23 11:03:15 -070042#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070043
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070044// NOLINT to suppress missing parentheses warnings about __def__.
Yifan Hong57886972016-08-17 10:42:15 -070045#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070046 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) \
Chih-Hung Hsieh306cc4b2017-08-02 14:59:25 -070056 default: __def__ /* NOLINT */ \
57 }
Yifan Hong52165692016-08-12 18:06:40 -070058
59namespace android {
60
Yifan Hongf24fa852016-09-23 11:03:15 -070061static inline bool isSupported(ScalarType::Kind kind) {
Timur Iskhakov63f39902017-08-29 15:47:29 -070062 return SK(BOOL) == kind || ScalarType(kind, nullptr /* parent */).isValidEnumStorageType();
Yifan Hongf24fa852016-09-23 11:03:15 -070063}
64
Yifan Hong57886972016-08-17 10:42:15 -070065/* See docs at the end for details on integral promotion. */
66ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070067 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070068}
69
Yifan Hong57886972016-08-17 10:42:15 -070070/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070071ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
72 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070073 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070074 // 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;
Yifan Hong57886972016-08-17 10:42:15 -070087
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070088 // Although there is such rule to return "the unsigned counterpart of
89 // the signed operand", it should not reach here in our HIDL grammar.
Steven Morelandcbff5612017-10-11 17:01:54 -070090 CHECK(false) << "Could not do usual arithmetic conversion for type " << lft << "and" << rgt;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070091 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 }
Yifan Hong52165692016-08-12 18:06:40 -070098}
Yifan Hong57886972016-08-17 10:42:15 -070099
100template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000101T handleUnary(const std::string& op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700102 COMPUTE_UNARY(+)
103 COMPUTE_UNARY(-)
104 COMPUTE_UNARY(!)
105 COMPUTE_UNARY(~)
106 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700107 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700108 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700109}
110
111template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000112T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700113 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.
Yifan Hongf24fa852016-09-23 11:03:15 -0700129 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
130 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700131 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700132}
133
134template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000135T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700136 // just cast rval to int64_t and it should fit.
137 COMPUTE_BINARY(>>)
138 COMPUTE_BINARY(<<)
139 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700140 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700141 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700142 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700143}
144
Timur Iskhakov7296af12017-08-09 21:52:48 +0000145bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700146 COMPUTE_BINARY(||);
147 COMPUTE_BINARY(&&);
148 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700149 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700150 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700151 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700152}
153
Timur Iskhakov7296af12017-08-09 21:52:48 +0000154std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
155 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700156}
157
Timur Iskhakov7296af12017-08-09 21:52:48 +0000158std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
159 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700160}
161
Timur Iskhakov7296af12017-08-09 21:52:48 +0000162std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
163 uint64_t value) {
164 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700165}
166
Neel Mehta3b414a82019-07-02 15:47:48 -0700167ConstantExpression::ConstantExpression(const std::string& expr) : mExpr(expr) {}
168
Timur Iskhakov7296af12017-08-09 21:52:48 +0000169bool ConstantExpression::isEvaluated() const {
170 return mIsEvaluated;
171}
172
Neel Mehta3b414a82019-07-02 15:47:48 -0700173LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value,
174 const std::string& expr)
175 : ConstantExpression(expr) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700176 CHECK(!expr.empty());
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700177 CHECK(isSupported(kind));
Neel Mehta3b414a82019-07-02 15:47:48 -0700178
Steven Moreland77943692018-08-09 12:53:42 -0700179 mTrivialDescription = std::to_string(value) == expr;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000180 mValueKind = kind;
181 mValue = value;
182 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700183}
184
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700185LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
186 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
187
188LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000189 CHECK(!value.empty());
Yifan Hongf24fa852016-09-23 11:03:15 -0700190
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700191 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000192 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
193
194 auto rbegin = value.rbegin();
195 auto rend = value.rend();
196 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
197 ++rbegin) {
198 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
199 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700200 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000201 std::string newVal(value.begin(), rbegin.base());
202 CHECK(!newVal.empty());
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700203
204 uint64_t rawValue = 0;
205
206 bool parseOK = base::ParseUint(newVal, &rawValue);
207 if (!parseOK) {
208 return nullptr;
209 }
210
211 ScalarType::Kind kind;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700212
213 // guess literal type.
214 if(isLong) {
215 if(isUnsigned) // ul
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700216 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700217 else // l
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700218 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700219 } else { // no l suffix
220 if(isUnsigned) { // u
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700221 if(rawValue <= UINT32_MAX)
222 kind = SK(UINT32);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700223 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700224 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700225 } else { // no suffix
226 if(isHex) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700227 if(rawValue <= INT32_MAX) // rawValue always >= 0
228 kind = SK(INT32);
229 else if(rawValue <= UINT32_MAX)
230 kind = SK(UINT32);
231 else if(rawValue <= INT64_MAX) // rawValue always >= 0
232 kind = SK(INT64);
233 else if(rawValue <= UINT64_MAX)
234 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700235 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700236 return nullptr;
237 } else {
238 if(rawValue <= INT32_MAX) // rawValue always >= 0
239 kind = SK(INT32);
240 else
241 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700242 }
243 }
244 }
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700245
246 return new LiteralConstantExpression(kind, rawValue, value);
Yifan Hong57886972016-08-17 10:42:15 -0700247}
248
Timur Iskhakov7296af12017-08-09 21:52:48 +0000249void LiteralConstantExpression::evaluate() {
250 // Evaluated in constructor
251 CHECK(isEvaluated());
252}
Yifan Hongf24fa852016-09-23 11:03:15 -0700253
Timur Iskhakov7296af12017-08-09 21:52:48 +0000254void UnaryConstantExpression::evaluate() {
255 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700256 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000257 mIsEvaluated = true;
258
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700259 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000260
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700261#define CASE_UNARY(__type__) \
262 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000263 return;
Yifan Hong57886972016-08-17 10:42:15 -0700264
Yifan Hongf24fa852016-09-23 11:03:15 -0700265 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700266}
Yifan Hong57886972016-08-17 10:42:15 -0700267
Timur Iskhakov7296af12017-08-09 21:52:48 +0000268void BinaryConstantExpression::evaluate() {
269 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700270 CHECK(mLval->isEvaluated());
271 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000272 mIsEvaluated = true;
273
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700274 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
275
276 // CASE 1: + - * / % | ^ & < > <= >= == !=
277 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
278 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700279 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
280 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700281 // result kind.
282 mValueKind = isArithmeticOrBitflip
283 ? promoted // arithmetic or bitflip operators generates promoted type
284 : SK(BOOL); // comparison operators generates bool
285
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700286#define CASE_BINARY_COMMON(__type__) \
287 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
288 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000289 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700290
Yifan Hongf24fa852016-09-23 11:03:15 -0700291 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700292 }
293
294 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700295 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700296 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700297 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700298 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700299 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700300 if(numBits < 0) {
301 // shifting with negative number of bits is undefined in C. In HIDL it
302 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000303 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700304 numBits = -numBits;
305 }
306
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700307#define CASE_SHIFT(__type__) \
308 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000309 return;
Yifan Hong57886972016-08-17 10:42:15 -0700310
Yifan Hongf24fa852016-09-23 11:03:15 -0700311 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700312 }
Yifan Hong57886972016-08-17 10:42:15 -0700313
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700314 // CASE 3: && ||
315 if(OP_IS_BIN_LOGICAL) {
316 mValueKind = SK(BOOL);
317 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700318 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700319 return;
320 }
Yifan Hong57886972016-08-17 10:42:15 -0700321
Yifan Hongf24fa852016-09-23 11:03:15 -0700322 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700323}
324
Timur Iskhakov7296af12017-08-09 21:52:48 +0000325void TernaryConstantExpression::evaluate() {
326 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700327 CHECK(mCond->isEvaluated());
328 CHECK(mTrueVal->isEvaluated());
329 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000330 mIsEvaluated = true;
331
Timur Iskhakov891a8662017-08-25 21:53:48 -0700332 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700333 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700334
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700335#define CASE_TERNARY(__type__) \
336 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
337 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000338 return;
Yifan Hong57886972016-08-17 10:42:15 -0700339
Yifan Hongf24fa852016-09-23 11:03:15 -0700340 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700341}
342
Timur Iskhakov7296af12017-08-09 21:52:48 +0000343void ReferenceConstantExpression::evaluate() {
344 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700345 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000346
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700347 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700348 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000349
350 mValueKind = expr->mValueKind;
351 mValue = expr->mValue;
352 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700353}
Yifan Hong57886972016-08-17 10:42:15 -0700354
Steven Moreland12f0ab12018-11-02 17:27:37 -0700355status_t AttributeConstantExpression::validate() const {
356 if (mTag == "len") {
357 if (!mReference->isEnum()) {
358 std::cerr << "ERROR: " << mExpr << " refers to " << mReference->typeName()
359 << " but should refer to an enum." << std::endl;
360 return UNKNOWN_ERROR;
361 }
362 } else {
363 std::cerr << "ERROR: " << mExpr << " is not a supported tag" << std::endl;
364 return UNKNOWN_ERROR;
365 }
366
367 return OK;
368}
369
370void AttributeConstantExpression::evaluate() {
371 if (isEvaluated()) return;
372
373 CHECK(mTag == "len");
374 CHECK(mReference->isEnum());
375
376 EnumType* enumType = static_cast<EnumType*>(mReference.get());
377 mValue = enumType->numValueNames();
378
379 if (mValue <= INT32_MAX)
380 mValueKind = SK(INT32);
381 else
382 mValueKind = SK(INT64);
383
384 mIsEvaluated = true;
385}
386
Timur Iskhakov7296af12017-08-09 21:52:48 +0000387std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
388 auto ret = std::make_unique<BinaryConstantExpression>(
389 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000390 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700391}
392
Yifan Hongfc610cd2016-09-22 13:34:45 -0700393std::string ConstantExpression::value() const {
Steven Morelandf21962d2018-08-09 12:44:40 -0700394 return value(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700395}
396
Yifan Hongc07b2022016-11-08 12:44:24 -0800397std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000398 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700399 return rawValue(castKind) + descriptionSuffix();
Yifan Hongc07b2022016-11-08 12:44:24 -0800400}
401
Yifan Hongf24fa852016-09-23 11:03:15 -0700402std::string ConstantExpression::cppValue() const {
403 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700404}
405
Yifan Hongfc610cd2016-09-22 13:34:45 -0700406std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000407 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700408 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700409 // this is a hack to translate
410 // enum x : int64_t { y = 1l << 63 };
411 // into
412 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
413 // by adding the explicit cast.
414 // Because 9223372036854775808 is uint64_t, and
415 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
416 // be narrowed to int64_t.
417 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700418 literal = "static_cast<" +
419 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
420 + ">(" + literal + "ull)";
421 } else {
422 // add suffix if necessary.
423 if (castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
424 if (castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700425 }
Yifan Hong57886972016-08-17 10:42:15 -0700426
Steven Morelandf21962d2018-08-09 12:44:40 -0700427 return literal + descriptionSuffix();
Yifan Hong57886972016-08-17 10:42:15 -0700428}
429
Yifan Hongf24fa852016-09-23 11:03:15 -0700430std::string ConstantExpression::javaValue() const {
431 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700432}
433
Yifan Hongf24fa852016-09-23 11:03:15 -0700434std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000435 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700436 std::string literal;
437
Yifan Hongf24fa852016-09-23 11:03:15 -0700438 switch(castKind) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700439 case SK(UINT64):
440 literal = rawValue(SK(INT64)) + "L";
441 break;
442 case SK(INT64):
443 literal = rawValue(SK(INT64)) + "L";
444 break;
445 case SK(UINT32):
446 literal = rawValue(SK(INT32));
447 break;
448 case SK(UINT16):
449 literal = rawValue(SK(INT16));
450 break;
451 case SK(UINT8):
452 literal = rawValue(SK(INT8));
453 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700454 case SK(BOOL) :
Steven Morelandf21962d2018-08-09 12:44:40 -0700455 literal = this->cast<bool>() ? "true" : "false";
456 break;
457 default:
458 literal = rawValue(castKind);
459 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700460 }
Steven Morelandf21962d2018-08-09 12:44:40 -0700461
462 return literal + descriptionSuffix();
463}
464
465const std::string& ConstantExpression::expression() const {
Steven Morelandf21962d2018-08-09 12:44:40 -0700466 return mExpr;
467}
468
469std::string ConstantExpression::rawValue() const {
470 return rawValue(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700471}
472
473std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000474 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700475
Yifan Hongfc610cd2016-09-22 13:34:45 -0700476#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700477
Yi Kongd7f8ab32018-07-24 11:27:02 -0700478 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return nullptr; );
Yifan Hong57886972016-08-17 10:42:15 -0700479}
480
Yifan Hong19ca75a2016-08-31 10:20:03 -0700481template<typename T>
482T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000483 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700484
Yifan Hong19ca75a2016-08-31 10:20:03 -0700485#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700486
Yifan Hongf24fa852016-09-23 11:03:15 -0700487 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700488}
489
Steven Morelandf21962d2018-08-09 12:44:40 -0700490std::string ConstantExpression::descriptionSuffix() const {
491 CHECK(isEvaluated());
492
493 if (!mTrivialDescription) {
494 CHECK(!mExpr.empty());
495
496 return " /* " + mExpr + " */";
497 }
498 return "";
499}
500
Yifan Honge77ca132016-09-27 10:49:05 -0700501size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000502 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700503 return this->cast<size_t>();
504}
505
Timur Iskhakova6d33882017-09-01 13:02:09 -0700506bool ConstantExpression::isReferenceConstantExpression() const {
507 return false;
508}
509
Steven Moreland12f0ab12018-11-02 17:27:37 -0700510status_t ConstantExpression::validate() const {
511 return OK;
512}
513
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700514std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
515 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
516 std::vector<ConstantExpression*> ret(constRet.size());
517 std::transform(constRet.begin(), constRet.end(), ret.begin(),
518 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
519 return ret;
520}
521
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700522std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
523 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
524 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
525 std::transform(constRet.begin(), constRet.end(), ret.begin(),
526 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
527 return ret;
528}
529
530std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
531 return {};
532}
533
Steven Moreland12f0ab12018-11-02 17:27:37 -0700534std::vector<Reference<Type>*> ConstantExpression::getTypeReferences() {
535 const auto& constRet = static_cast<const ConstantExpression*>(this)->getTypeReferences();
536 std::vector<Reference<Type>*> ret(constRet.size());
537 std::transform(constRet.begin(), constRet.end(), ret.begin(),
538 [](const auto* ce) { return const_cast<Reference<Type>*>(ce); });
539 return ret;
540}
541
542std::vector<const Reference<Type>*> ConstantExpression::getTypeReferences() const {
543 return {};
544}
545
Timur Iskhakov891a8662017-08-25 21:53:48 -0700546status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700547 std::unordered_set<const ConstantExpression*>* visited,
548 bool processBeforeDependencies) {
Timur Iskhakov35930c42017-08-28 18:49:54 -0700549 if (mIsPostParseCompleted) return OK;
550
Timur Iskhakov891a8662017-08-25 21:53:48 -0700551 if (visited->find(this) != visited->end()) return OK;
552 visited->insert(this);
553
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700554 if (processBeforeDependencies) {
555 status_t err = func(this);
556 if (err != OK) return err;
557 }
558
Timur Iskhakov891a8662017-08-25 21:53:48 -0700559 for (auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700560 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700561 if (err != OK) return err;
562 }
563
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700564 for (auto* nextRef : getReferences()) {
565 auto* nextCE = nextRef->shallowGet()->constExpr();
566 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700567 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700568 if (err != OK) return err;
569 }
570
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700571 if (!processBeforeDependencies) {
572 status_t err = func(this);
573 if (err != OK) return err;
574 }
Timur Iskhakov891a8662017-08-25 21:53:48 -0700575
576 return OK;
577}
578
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700579status_t ConstantExpression::recursivePass(
580 const std::function<status_t(const ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700581 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700582 if (mIsPostParseCompleted) return OK;
583
584 if (visited->find(this) != visited->end()) return OK;
585 visited->insert(this);
586
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700587 if (processBeforeDependencies) {
588 status_t err = func(this);
589 if (err != OK) return err;
590 }
591
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700592 for (const auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700593 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700594 if (err != OK) return err;
595 }
596
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700597 for (const auto* nextRef : getReferences()) {
598 const auto* nextCE = nextRef->shallowGet()->constExpr();
599 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700600 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700601 if (err != OK) return err;
602 }
603
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700604 if (!processBeforeDependencies) {
605 status_t err = func(this);
606 if (err != OK) return err;
607 }
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700608
609 return OK;
610}
611
Timur Iskhakova6d33882017-09-01 13:02:09 -0700612ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
613 status_t status, const ConstantExpression* cycleEnd,
614 const ReferenceConstantExpression* lastReference)
615 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700616 CHECK(cycleEnd == nullptr || status != OK);
Timur Iskhakova6d33882017-09-01 13:02:09 -0700617 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700618}
619
620ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
621 std::unordered_set<const ConstantExpression*>* visited,
622 std::unordered_set<const ConstantExpression*>* stack) const {
623 if (stack->find(this) != stack->end()) {
Timur Iskhakova6d33882017-09-01 13:02:09 -0700624 CHECK(isReferenceConstantExpression())
625 << "Only reference constant expression could be the cycle end";
626
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700627 std::cerr << "ERROR: Cyclic declaration:\n";
Timur Iskhakova6d33882017-09-01 13:02:09 -0700628 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
629 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700630 }
631
632 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
633 visited->insert(this);
634 stack->insert(this);
635
636 for (const auto* nextCE : getConstantExpressions()) {
637 auto err = nextCE->checkAcyclic(visited, stack);
638 if (err.status != OK) {
639 return err;
640 }
641 }
642
643 for (const auto* nextRef : getReferences()) {
644 const auto* nextCE = nextRef->shallowGet()->constExpr();
645 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
646 auto err = nextCE->checkAcyclic(visited, stack);
647
648 if (err.status != OK) {
649 if (err.cycleEnd == nullptr) return err;
650
651 // Only ReferenceConstantExpression has references,
Timur Iskhakova6d33882017-09-01 13:02:09 -0700652 CHECK(isReferenceConstantExpression())
653 << "Only reference constant expression could have refereneces";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700654
Timur Iskhakova6d33882017-09-01 13:02:09 -0700655 // mExpr is defined explicitly before evaluation
656 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
657 << nextRef->location() << "\n";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700658
659 if (err.cycleEnd == this) {
660 return CheckAcyclicStatus(err.status);
661 }
Timur Iskhakova6d33882017-09-01 13:02:09 -0700662 return CheckAcyclicStatus(err.status, err.cycleEnd,
663 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700664 }
665 }
666
667 CHECK(stack->find(this) != stack->end());
668 stack->erase(this);
669 return CheckAcyclicStatus(OK);
670}
671
Timur Iskhakov35930c42017-08-28 18:49:54 -0700672void ConstantExpression::setPostParseCompleted() {
673 CHECK(!mIsPostParseCompleted);
674 mIsPostParseCompleted = true;
675}
676
Neel Mehta1ca3e782019-07-18 15:16:22 -0700677void ConstantExpression::surroundWithParens() {
678 mExpr = "(" + mExpr + ")";
679}
680
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700681std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700682 return {};
683}
684
Timur Iskhakov7296af12017-08-09 21:52:48 +0000685UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700686 : ConstantExpression(op + value->mExpr), mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000687
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700688std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700689 return {mUnary};
690}
691
Timur Iskhakov7296af12017-08-09 21:52:48 +0000692BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
693 ConstantExpression* rval)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700694 : ConstantExpression(lval->mExpr + " " + op + " " + rval->mExpr),
Neel Mehta3b414a82019-07-02 15:47:48 -0700695 mLval(lval),
696 mRval(rval),
697 mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000698
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700699std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700700 return {mLval, mRval};
701}
702
Timur Iskhakov7296af12017-08-09 21:52:48 +0000703TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
704 ConstantExpression* trueVal,
705 ConstantExpression* falseVal)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700706 : ConstantExpression(cond->mExpr + "?" + trueVal->mExpr + ":" + falseVal->mExpr),
Neel Mehta3b414a82019-07-02 15:47:48 -0700707 mCond(cond),
708 mTrueVal(trueVal),
709 mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000710
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700711std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700712 return {mCond, mTrueVal, mFalseVal};
713}
714
Timur Iskhakov7296af12017-08-09 21:52:48 +0000715ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
716 const std::string& expr)
Neel Mehta3b414a82019-07-02 15:47:48 -0700717 : ConstantExpression(expr), mReference(value) {
Timur Iskhakov505e5612017-08-27 18:26:48 -0700718 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000719}
720
Timur Iskhakova6d33882017-09-01 13:02:09 -0700721bool ReferenceConstantExpression::isReferenceConstantExpression() const {
722 return true;
723}
724
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700725std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700726 // Returns reference instead
727 return {};
728}
729
730std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
731 return {&mReference};
Timur Iskhakov891a8662017-08-25 21:53:48 -0700732}
733
Steven Moreland12f0ab12018-11-02 17:27:37 -0700734AttributeConstantExpression::AttributeConstantExpression(const Reference<Type>& value,
735 const std::string& fqname,
736 const std::string& tag)
Neel Mehta3b414a82019-07-02 15:47:48 -0700737 : ConstantExpression(fqname + "#" + tag), mReference(value), mTag(tag) {}
Steven Moreland12f0ab12018-11-02 17:27:37 -0700738
739std::vector<const ConstantExpression*> AttributeConstantExpression::getConstantExpressions() const {
740 // Returns reference instead
741 return {};
742}
743
744std::vector<const Reference<Type>*> AttributeConstantExpression::getTypeReferences() const {
745 return {&mReference};
746}
747
Yifan Hong57886972016-08-17 10:42:15 -0700748/*
749
750Evaluating expressions in HIDL language
751
752The following rules are mostly like that in:
753http://en.cppreference.com/w/cpp/language/operator_arithmetic
754http://en.cppreference.com/w/cpp/language/operator_logical
755http://en.cppreference.com/w/cpp/language/operator_comparison
756http://en.cppreference.com/w/cpp/language/operator_other
757
758The type of literal is the first type which the value
759can fit from the list of types depending on the suffix and bases.
760
761suffix decimal bases hexadecimal bases
762no suffix int32_t int32_t
763 int64_t uint32_t
764 int64_t
765 uint64_t
766
767u/U uint32_t (same as left)
768 uint64_t
769
770l/L int64_t int64_t
771
772ul/UL/uL/Ul uint64_t uint64_t
773
774
775Note: There are no negative integer literals.
776 -1 is the unary minus applied to 1.
777
778Unary arithmetic and bitwise operators (~ + -):
779 don't change the type of the argument.
780 (so -1u = -(1u) has type uint32_t)
781
782Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
7831. Integral promotion is first applied on both sides.
7842. If both operands have the same type, no promotion is necessary.
7853. Usual arithmetic conversions.
786
787Integral promotion: if an operand is of a type with less than 32 bits,
788(including bool), it is promoted to int32_t.
789
790Usual arithmetic conversions:
7911. If operands are both signed or both unsigned, lesser conversion rank is
792 converted to greater conversion rank.
7932. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
7943. Otherwise, if signed's type can hold all values in unsigned's type,
795 -> signed's type
7964. Otherwise, both converted to the unsigned counterpart of the signed operand's
797 type.
798rank: bool < int8_t < int16_t < int32_t < int64_t
799
800
801Shift operators (<< >>):
8021. Integral promotion is applied on both sides.
8032. For unsigned a, a << b discards bits that shifts out.
804 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
805 For signed negative a, a << b gives error.
8063. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
807 For signed negative a, a >> b discards bits that shifts out, and the signed
808 bit gets extended. ("arithmetic right shift")
8094. Shifting with negative number of bits is undefined. (Currently, the
810 parser will shift into the other direction. This behavior may change.)
8115. Shifting with number of bits exceeding the width of the type is undefined.
812 (Currently, 1 << 32 == 1. This behavior may change.)
813
814Logical operators (!, &&, ||):
8151. Convert first operand to bool. (true if non-zero, false otherwise)
8162. If short-circuited, return the result as type bool, value 1 or 0.
8173. Otherwise, convert second operand to bool, evaluate the result, and return
818 the result in the same fashion.
819
820Arithmetic comparison operators (< > <= >= == !=):
8211. Promote operands in the same way as binary arithmetic and bitwise operators.
822 (Integral promotion + Usual arithmetic conversions)
8232. Return type bool, value 0 or 1 the same way as logical operators.
824
825Ternary conditional operator (?:):
8261. Evaluate the conditional and evaluate the operands.
8272. Return type of expression is the type under usual arithmetic conversions on
828 the second and third operand. (No integral promotions necessary.)
829
830*/
831
Yifan Hong52165692016-08-12 18:06:40 -0700832} // namespace android
833