blob: 002bf5663f72125f39f18d671b72e32104ec95f7 [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
Timur Iskhakov7296af12017-08-09 21:52:48 +0000167bool ConstantExpression::isEvaluated() const {
168 return mIsEvaluated;
169}
170
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700171LiteralConstantExpression::LiteralConstantExpression(
172 ScalarType::Kind kind, uint64_t value, const std::string& expr) {
173
174 CHECK(!expr.empty());
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700175 CHECK(isSupported(kind));
Steven Moreland77943692018-08-09 12:53:42 -0700176 mTrivialDescription = std::to_string(value) == expr;
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700177 mExpr = expr;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000178 mValueKind = kind;
179 mValue = value;
180 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700181}
182
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700183LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
184 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
185
186LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000187 CHECK(!value.empty());
Yifan Hongf24fa852016-09-23 11:03:15 -0700188
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700189 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000190 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');
Yifan Hong57886972016-08-17 10:42:15 -0700198 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000199 std::string newVal(value.begin(), rbegin.base());
200 CHECK(!newVal.empty());
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700201
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;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700210
211 // guess literal type.
212 if(isLong) {
213 if(isUnsigned) // ul
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700214 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700215 else // l
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700216 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700217 } else { // no l suffix
218 if(isUnsigned) { // u
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700219 if(rawValue <= UINT32_MAX)
220 kind = SK(UINT32);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700221 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700222 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700223 } else { // no suffix
224 if(isHex) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700225 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);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700233 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700234 return nullptr;
235 } else {
236 if(rawValue <= INT32_MAX) // rawValue always >= 0
237 kind = SK(INT32);
238 else
239 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700240 }
241 }
242 }
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700243
244 return new LiteralConstantExpression(kind, rawValue, value);
Yifan Hong57886972016-08-17 10:42:15 -0700245}
246
Timur Iskhakov7296af12017-08-09 21:52:48 +0000247void LiteralConstantExpression::evaluate() {
248 // Evaluated in constructor
249 CHECK(isEvaluated());
250}
Yifan Hongf24fa852016-09-23 11:03:15 -0700251
Timur Iskhakov7296af12017-08-09 21:52:48 +0000252void UnaryConstantExpression::evaluate() {
253 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700254 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000255 mIsEvaluated = true;
256
Steven Morelandf21962d2018-08-09 12:44:40 -0700257 mExpr = std::string("(") + mOp + mUnary->mExpr + ")";
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700258 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000259
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700260#define CASE_UNARY(__type__) \
261 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000262 return;
Yifan Hong57886972016-08-17 10:42:15 -0700263
Yifan Hongf24fa852016-09-23 11:03:15 -0700264 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700265}
Yifan Hong57886972016-08-17 10:42:15 -0700266
Timur Iskhakov7296af12017-08-09 21:52:48 +0000267void BinaryConstantExpression::evaluate() {
268 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700269 CHECK(mLval->isEvaluated());
270 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000271 mIsEvaluated = true;
272
Steven Morelandf21962d2018-08-09 12:44:40 -0700273 mExpr = std::string("(") + mLval->mExpr + " " + mOp + " " + mRval->mExpr + ")";
Yifan Hong57886972016-08-17 10:42:15 -0700274
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700275 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.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700280 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
281 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700282 // result kind.
283 mValueKind = isArithmeticOrBitflip
284 ? promoted // arithmetic or bitflip operators generates promoted type
285 : SK(BOOL); // comparison operators generates bool
286
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700287#define CASE_BINARY_COMMON(__type__) \
288 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
289 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000290 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700291
Yifan Hongf24fa852016-09-23 11:03:15 -0700292 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700293 }
294
295 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700296 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700297 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700298 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700299 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700300 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700301 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.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000304 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700305 numBits = -numBits;
306 }
307
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700308#define CASE_SHIFT(__type__) \
309 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000310 return;
Yifan Hong57886972016-08-17 10:42:15 -0700311
Yifan Hongf24fa852016-09-23 11:03:15 -0700312 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700313 }
Yifan Hong57886972016-08-17 10:42:15 -0700314
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700315 // CASE 3: && ||
316 if(OP_IS_BIN_LOGICAL) {
317 mValueKind = SK(BOOL);
318 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700319 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700320 return;
321 }
Yifan Hong57886972016-08-17 10:42:15 -0700322
Yifan Hongf24fa852016-09-23 11:03:15 -0700323 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700324}
325
Timur Iskhakov7296af12017-08-09 21:52:48 +0000326void TernaryConstantExpression::evaluate() {
327 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700328 CHECK(mCond->isEvaluated());
329 CHECK(mTrueVal->isEvaluated());
330 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000331 mIsEvaluated = true;
332
Steven Morelandf21962d2018-08-09 12:44:40 -0700333 mExpr = std::string("(") + mCond->mExpr + "?" + mTrueVal->mExpr + ":" + mFalseVal->mExpr + ")";
Yifan Hongf24fa852016-09-23 11:03:15 -0700334
Timur Iskhakov891a8662017-08-25 21:53:48 -0700335 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700336 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700337
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700338#define CASE_TERNARY(__type__) \
339 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
340 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000341 return;
Yifan Hong57886972016-08-17 10:42:15 -0700342
Yifan Hongf24fa852016-09-23 11:03:15 -0700343 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700344}
345
Timur Iskhakov7296af12017-08-09 21:52:48 +0000346void ReferenceConstantExpression::evaluate() {
347 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700348 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000349
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700350 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700351 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000352
353 mValueKind = expr->mValueKind;
354 mValue = expr->mValue;
355 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700356}
Yifan Hong57886972016-08-17 10:42:15 -0700357
Steven Moreland12f0ab12018-11-02 17:27:37 -0700358status_t AttributeConstantExpression::validate() const {
359 if (mTag == "len") {
360 if (!mReference->isEnum()) {
361 std::cerr << "ERROR: " << mExpr << " refers to " << mReference->typeName()
362 << " but should refer to an enum." << std::endl;
363 return UNKNOWN_ERROR;
364 }
365 } else {
366 std::cerr << "ERROR: " << mExpr << " is not a supported tag" << std::endl;
367 return UNKNOWN_ERROR;
368 }
369
370 return OK;
371}
372
373void AttributeConstantExpression::evaluate() {
374 if (isEvaluated()) return;
375
376 CHECK(mTag == "len");
377 CHECK(mReference->isEnum());
378
379 EnumType* enumType = static_cast<EnumType*>(mReference.get());
380 mValue = enumType->numValueNames();
381
382 if (mValue <= INT32_MAX)
383 mValueKind = SK(INT32);
384 else
385 mValueKind = SK(INT64);
386
387 mIsEvaluated = true;
388}
389
Timur Iskhakov7296af12017-08-09 21:52:48 +0000390std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
391 auto ret = std::make_unique<BinaryConstantExpression>(
392 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000393 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700394}
395
Yifan Hongfc610cd2016-09-22 13:34:45 -0700396std::string ConstantExpression::value() const {
Steven Morelandf21962d2018-08-09 12:44:40 -0700397 return value(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700398}
399
Yifan Hongc07b2022016-11-08 12:44:24 -0800400std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000401 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700402 return rawValue(castKind) + descriptionSuffix();
Yifan Hongc07b2022016-11-08 12:44:24 -0800403}
404
Yifan Hongf24fa852016-09-23 11:03:15 -0700405std::string ConstantExpression::cppValue() const {
406 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700407}
408
Yifan Hongfc610cd2016-09-22 13:34:45 -0700409std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000410 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700411 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700412 // this is a hack to translate
413 // enum x : int64_t { y = 1l << 63 };
414 // into
415 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
416 // by adding the explicit cast.
417 // Because 9223372036854775808 is uint64_t, and
418 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
419 // be narrowed to int64_t.
420 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700421 literal = "static_cast<" +
422 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
423 + ">(" + literal + "ull)";
424 } else {
425 // add suffix if necessary.
426 if (castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
427 if (castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700428 }
Yifan Hong57886972016-08-17 10:42:15 -0700429
Steven Morelandf21962d2018-08-09 12:44:40 -0700430 return literal + descriptionSuffix();
Yifan Hong57886972016-08-17 10:42:15 -0700431}
432
Yifan Hongf24fa852016-09-23 11:03:15 -0700433std::string ConstantExpression::javaValue() const {
434 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700435}
436
Yifan Hongf24fa852016-09-23 11:03:15 -0700437std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000438 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700439 std::string literal;
440
Yifan Hongf24fa852016-09-23 11:03:15 -0700441 switch(castKind) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700442 case SK(UINT64):
443 literal = rawValue(SK(INT64)) + "L";
444 break;
445 case SK(INT64):
446 literal = rawValue(SK(INT64)) + "L";
447 break;
448 case SK(UINT32):
449 literal = rawValue(SK(INT32));
450 break;
451 case SK(UINT16):
452 literal = rawValue(SK(INT16));
453 break;
454 case SK(UINT8):
455 literal = rawValue(SK(INT8));
456 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700457 case SK(BOOL) :
Steven Morelandf21962d2018-08-09 12:44:40 -0700458 literal = this->cast<bool>() ? "true" : "false";
459 break;
460 default:
461 literal = rawValue(castKind);
462 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700463 }
Steven Morelandf21962d2018-08-09 12:44:40 -0700464
465 return literal + descriptionSuffix();
466}
467
468const std::string& ConstantExpression::expression() const {
469 CHECK(isEvaluated());
470 return mExpr;
471}
472
473std::string ConstantExpression::rawValue() const {
474 return rawValue(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700475}
476
477std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000478 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700479
Yifan Hongfc610cd2016-09-22 13:34:45 -0700480#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700481
Yi Kongd7f8ab32018-07-24 11:27:02 -0700482 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return nullptr; );
Yifan Hong57886972016-08-17 10:42:15 -0700483}
484
Yifan Hong19ca75a2016-08-31 10:20:03 -0700485template<typename T>
486T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000487 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700488
Yifan Hong19ca75a2016-08-31 10:20:03 -0700489#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700490
Yifan Hongf24fa852016-09-23 11:03:15 -0700491 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700492}
493
Steven Morelandf21962d2018-08-09 12:44:40 -0700494std::string ConstantExpression::descriptionSuffix() const {
495 CHECK(isEvaluated());
496
497 if (!mTrivialDescription) {
498 CHECK(!mExpr.empty());
499
500 return " /* " + mExpr + " */";
501 }
502 return "";
503}
504
Yifan Honge77ca132016-09-27 10:49:05 -0700505size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000506 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700507 return this->cast<size_t>();
508}
509
Timur Iskhakova6d33882017-09-01 13:02:09 -0700510bool ConstantExpression::isReferenceConstantExpression() const {
511 return false;
512}
513
Steven Moreland12f0ab12018-11-02 17:27:37 -0700514status_t ConstantExpression::validate() const {
515 return OK;
516}
517
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700518std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
519 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
520 std::vector<ConstantExpression*> ret(constRet.size());
521 std::transform(constRet.begin(), constRet.end(), ret.begin(),
522 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
523 return ret;
524}
525
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700526std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
527 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
528 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
529 std::transform(constRet.begin(), constRet.end(), ret.begin(),
530 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
531 return ret;
532}
533
534std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
535 return {};
536}
537
Steven Moreland12f0ab12018-11-02 17:27:37 -0700538std::vector<Reference<Type>*> ConstantExpression::getTypeReferences() {
539 const auto& constRet = static_cast<const ConstantExpression*>(this)->getTypeReferences();
540 std::vector<Reference<Type>*> ret(constRet.size());
541 std::transform(constRet.begin(), constRet.end(), ret.begin(),
542 [](const auto* ce) { return const_cast<Reference<Type>*>(ce); });
543 return ret;
544}
545
546std::vector<const Reference<Type>*> ConstantExpression::getTypeReferences() const {
547 return {};
548}
549
Timur Iskhakov891a8662017-08-25 21:53:48 -0700550status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700551 std::unordered_set<const ConstantExpression*>* visited,
552 bool processBeforeDependencies) {
Timur Iskhakov35930c42017-08-28 18:49:54 -0700553 if (mIsPostParseCompleted) return OK;
554
Timur Iskhakov891a8662017-08-25 21:53:48 -0700555 if (visited->find(this) != visited->end()) return OK;
556 visited->insert(this);
557
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700558 if (processBeforeDependencies) {
559 status_t err = func(this);
560 if (err != OK) return err;
561 }
562
Timur Iskhakov891a8662017-08-25 21:53:48 -0700563 for (auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700564 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700565 if (err != OK) return err;
566 }
567
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700568 for (auto* nextRef : getReferences()) {
569 auto* nextCE = nextRef->shallowGet()->constExpr();
570 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700571 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700572 if (err != OK) return err;
573 }
574
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700575 if (!processBeforeDependencies) {
576 status_t err = func(this);
577 if (err != OK) return err;
578 }
Timur Iskhakov891a8662017-08-25 21:53:48 -0700579
580 return OK;
581}
582
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700583status_t ConstantExpression::recursivePass(
584 const std::function<status_t(const ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700585 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700586 if (mIsPostParseCompleted) return OK;
587
588 if (visited->find(this) != visited->end()) return OK;
589 visited->insert(this);
590
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700591 if (processBeforeDependencies) {
592 status_t err = func(this);
593 if (err != OK) return err;
594 }
595
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700596 for (const auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700597 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700598 if (err != OK) return err;
599 }
600
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700601 for (const auto* nextRef : getReferences()) {
602 const auto* nextCE = nextRef->shallowGet()->constExpr();
603 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700604 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700605 if (err != OK) return err;
606 }
607
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700608 if (!processBeforeDependencies) {
609 status_t err = func(this);
610 if (err != OK) return err;
611 }
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700612
613 return OK;
614}
615
Timur Iskhakova6d33882017-09-01 13:02:09 -0700616ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
617 status_t status, const ConstantExpression* cycleEnd,
618 const ReferenceConstantExpression* lastReference)
619 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700620 CHECK(cycleEnd == nullptr || status != OK);
Timur Iskhakova6d33882017-09-01 13:02:09 -0700621 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700622}
623
624ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
625 std::unordered_set<const ConstantExpression*>* visited,
626 std::unordered_set<const ConstantExpression*>* stack) const {
627 if (stack->find(this) != stack->end()) {
Timur Iskhakova6d33882017-09-01 13:02:09 -0700628 CHECK(isReferenceConstantExpression())
629 << "Only reference constant expression could be the cycle end";
630
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700631 std::cerr << "ERROR: Cyclic declaration:\n";
Timur Iskhakova6d33882017-09-01 13:02:09 -0700632 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
633 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700634 }
635
636 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
637 visited->insert(this);
638 stack->insert(this);
639
640 for (const auto* nextCE : getConstantExpressions()) {
641 auto err = nextCE->checkAcyclic(visited, stack);
642 if (err.status != OK) {
643 return err;
644 }
645 }
646
647 for (const auto* nextRef : getReferences()) {
648 const auto* nextCE = nextRef->shallowGet()->constExpr();
649 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
650 auto err = nextCE->checkAcyclic(visited, stack);
651
652 if (err.status != OK) {
653 if (err.cycleEnd == nullptr) return err;
654
655 // Only ReferenceConstantExpression has references,
Timur Iskhakova6d33882017-09-01 13:02:09 -0700656 CHECK(isReferenceConstantExpression())
657 << "Only reference constant expression could have refereneces";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700658
Timur Iskhakova6d33882017-09-01 13:02:09 -0700659 // mExpr is defined explicitly before evaluation
660 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
661 << nextRef->location() << "\n";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700662
663 if (err.cycleEnd == this) {
664 return CheckAcyclicStatus(err.status);
665 }
Timur Iskhakova6d33882017-09-01 13:02:09 -0700666 return CheckAcyclicStatus(err.status, err.cycleEnd,
667 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700668 }
669 }
670
671 CHECK(stack->find(this) != stack->end());
672 stack->erase(this);
673 return CheckAcyclicStatus(OK);
674}
675
Timur Iskhakov35930c42017-08-28 18:49:54 -0700676void ConstantExpression::setPostParseCompleted() {
677 CHECK(!mIsPostParseCompleted);
678 mIsPostParseCompleted = true;
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)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700686 : 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)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700694 : mLval(lval), mRval(rval), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000695
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700696std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700697 return {mLval, mRval};
698}
699
Timur Iskhakov7296af12017-08-09 21:52:48 +0000700TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
701 ConstantExpression* trueVal,
702 ConstantExpression* falseVal)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700703 : mCond(cond), mTrueVal(trueVal), mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000704
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700705std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700706 return {mCond, mTrueVal, mFalseVal};
707}
708
Timur Iskhakov7296af12017-08-09 21:52:48 +0000709ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
710 const std::string& expr)
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700711 : mReference(value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000712 mExpr = expr;
Timur Iskhakov505e5612017-08-27 18:26:48 -0700713 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000714}
715
Timur Iskhakova6d33882017-09-01 13:02:09 -0700716bool ReferenceConstantExpression::isReferenceConstantExpression() const {
717 return true;
718}
719
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700720std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700721 // Returns reference instead
722 return {};
723}
724
725std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
726 return {&mReference};
Timur Iskhakov891a8662017-08-25 21:53:48 -0700727}
728
Steven Moreland12f0ab12018-11-02 17:27:37 -0700729AttributeConstantExpression::AttributeConstantExpression(const Reference<Type>& value,
730 const std::string& fqname,
731 const std::string& tag)
732 : mReference(value), mTag(tag) {
733 mExpr = fqname + "#" + tag;
734}
735
736std::vector<const ConstantExpression*> AttributeConstantExpression::getConstantExpressions() const {
737 // Returns reference instead
738 return {};
739}
740
741std::vector<const Reference<Type>*> AttributeConstantExpression::getTypeReferences() const {
742 return {&mReference};
743}
744
Yifan Hong57886972016-08-17 10:42:15 -0700745/*
746
747Evaluating expressions in HIDL language
748
749The following rules are mostly like that in:
750http://en.cppreference.com/w/cpp/language/operator_arithmetic
751http://en.cppreference.com/w/cpp/language/operator_logical
752http://en.cppreference.com/w/cpp/language/operator_comparison
753http://en.cppreference.com/w/cpp/language/operator_other
754
755The type of literal is the first type which the value
756can fit from the list of types depending on the suffix and bases.
757
758suffix decimal bases hexadecimal bases
759no suffix int32_t int32_t
760 int64_t uint32_t
761 int64_t
762 uint64_t
763
764u/U uint32_t (same as left)
765 uint64_t
766
767l/L int64_t int64_t
768
769ul/UL/uL/Ul uint64_t uint64_t
770
771
772Note: There are no negative integer literals.
773 -1 is the unary minus applied to 1.
774
775Unary arithmetic and bitwise operators (~ + -):
776 don't change the type of the argument.
777 (so -1u = -(1u) has type uint32_t)
778
779Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
7801. Integral promotion is first applied on both sides.
7812. If both operands have the same type, no promotion is necessary.
7823. Usual arithmetic conversions.
783
784Integral promotion: if an operand is of a type with less than 32 bits,
785(including bool), it is promoted to int32_t.
786
787Usual arithmetic conversions:
7881. If operands are both signed or both unsigned, lesser conversion rank is
789 converted to greater conversion rank.
7902. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
7913. Otherwise, if signed's type can hold all values in unsigned's type,
792 -> signed's type
7934. Otherwise, both converted to the unsigned counterpart of the signed operand's
794 type.
795rank: bool < int8_t < int16_t < int32_t < int64_t
796
797
798Shift operators (<< >>):
7991. Integral promotion is applied on both sides.
8002. For unsigned a, a << b discards bits that shifts out.
801 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
802 For signed negative a, a << b gives error.
8033. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
804 For signed negative a, a >> b discards bits that shifts out, and the signed
805 bit gets extended. ("arithmetic right shift")
8064. Shifting with negative number of bits is undefined. (Currently, the
807 parser will shift into the other direction. This behavior may change.)
8085. Shifting with number of bits exceeding the width of the type is undefined.
809 (Currently, 1 << 32 == 1. This behavior may change.)
810
811Logical operators (!, &&, ||):
8121. Convert first operand to bool. (true if non-zero, false otherwise)
8132. If short-circuited, return the result as type bool, value 1 or 0.
8143. Otherwise, convert second operand to bool, evaluate the result, and return
815 the result in the same fashion.
816
817Arithmetic comparison operators (< > <= >= == !=):
8181. Promote operands in the same way as binary arithmetic and bitwise operators.
819 (Integral promotion + Usual arithmetic conversions)
8202. Return type bool, value 0 or 1 the same way as logical operators.
821
822Ternary conditional operator (?:):
8231. Evaluate the conditional and evaluate the operands.
8242. Return type of expression is the type under usual arithmetic conversions on
825 the second and third operand. (No integral promotions necessary.)
826
827*/
828
Yifan Hong52165692016-08-12 18:06:40 -0700829} // namespace android
830