blob: 02fbf7605da9df6cdfbf08bb6a9961e7ca608d01 [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(!)
Yifan Hong2ddbe4b2020-02-20 17:30:00 -0800105
106// bitwise negation of a boolean expression always evaluates to 'true'
107#pragma clang diagnostic push
108#pragma clang diagnostic ignored "-Wbool-operation"
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700109 COMPUTE_UNARY(~)
Yifan Hong2ddbe4b2020-02-20 17:30:00 -0800110#pragma clang diagnostic pop
111
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700112 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700113 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700114 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700115}
116
117template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000118T handleBinaryCommon(T lval, const std::string& op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700119 COMPUTE_BINARY(+)
120 COMPUTE_BINARY(-)
121 COMPUTE_BINARY(*)
122 COMPUTE_BINARY(/)
123 COMPUTE_BINARY(%)
124 COMPUTE_BINARY(|)
125 COMPUTE_BINARY(^)
126 COMPUTE_BINARY(&)
127 // comparison operators: return 0 or 1 by nature.
128 COMPUTE_BINARY(==)
129 COMPUTE_BINARY(!=)
130 COMPUTE_BINARY(<)
131 COMPUTE_BINARY(>)
132 COMPUTE_BINARY(<=)
133 COMPUTE_BINARY(>=)
134 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700135 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
136 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700137 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700138}
139
140template <class T>
Timur Iskhakov7296af12017-08-09 21:52:48 +0000141T handleShift(T lval, const std::string& op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700142 // just cast rval to int64_t and it should fit.
143 COMPUTE_BINARY(>>)
144 COMPUTE_BINARY(<<)
145 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700146 SHOULD_NOT_REACH() << "Could not handleShift for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700147 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700148 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700149}
150
Timur Iskhakov7296af12017-08-09 21:52:48 +0000151bool handleLogical(bool lval, const std::string& op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700152 COMPUTE_BINARY(||);
153 COMPUTE_BINARY(&&);
154 // Should not reach here.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700155 SHOULD_NOT_REACH() << "Could not handleLogical for "
Yifan Hongf24fa852016-09-23 11:03:15 -0700156 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700157 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700158}
159
Timur Iskhakov7296af12017-08-09 21:52:48 +0000160std::unique_ptr<ConstantExpression> ConstantExpression::Zero(ScalarType::Kind kind) {
161 return ValueOf(kind, 0);
Yifan Hongf24fa852016-09-23 11:03:15 -0700162}
163
Timur Iskhakov7296af12017-08-09 21:52:48 +0000164std::unique_ptr<ConstantExpression> ConstantExpression::One(ScalarType::Kind kind) {
165 return ValueOf(kind, 1);
Yifan Hongf24fa852016-09-23 11:03:15 -0700166}
167
Timur Iskhakov7296af12017-08-09 21:52:48 +0000168std::unique_ptr<ConstantExpression> ConstantExpression::ValueOf(ScalarType::Kind kind,
169 uint64_t value) {
170 return std::make_unique<LiteralConstantExpression>(kind, value);
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700171}
172
Neel Mehta3b414a82019-07-02 15:47:48 -0700173ConstantExpression::ConstantExpression(const std::string& expr) : mExpr(expr) {}
174
Timur Iskhakov7296af12017-08-09 21:52:48 +0000175bool ConstantExpression::isEvaluated() const {
176 return mIsEvaluated;
177}
178
Neel Mehta3b414a82019-07-02 15:47:48 -0700179LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value,
180 const std::string& expr)
181 : ConstantExpression(expr) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700182 CHECK(!expr.empty());
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700183 CHECK(isSupported(kind));
Neel Mehta3b414a82019-07-02 15:47:48 -0700184
Steven Moreland77943692018-08-09 12:53:42 -0700185 mTrivialDescription = std::to_string(value) == expr;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000186 mValueKind = kind;
187 mValue = value;
188 mIsEvaluated = true;
Yifan Hongf24fa852016-09-23 11:03:15 -0700189}
190
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700191LiteralConstantExpression::LiteralConstantExpression(ScalarType::Kind kind, uint64_t value)
192 : LiteralConstantExpression(kind, value, std::to_string(value)) {}
193
194LiteralConstantExpression* LiteralConstantExpression::tryParse(const std::string& value) {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000195 CHECK(!value.empty());
Yifan Hongf24fa852016-09-23 11:03:15 -0700196
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700197 bool isLong = false, isUnsigned = false;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000198 bool isHex = (value[0] == '0' && value.length() > 1 && (value[1] == 'x' || value[1] == 'X'));
199
200 auto rbegin = value.rbegin();
201 auto rend = value.rend();
202 for (; rbegin != rend && (*rbegin == 'u' || *rbegin == 'U' || *rbegin == 'l' || *rbegin == 'L');
203 ++rbegin) {
204 isUnsigned |= (*rbegin == 'u' || *rbegin == 'U');
205 isLong |= (*rbegin == 'l' || *rbegin == 'L');
Yifan Hong57886972016-08-17 10:42:15 -0700206 }
Timur Iskhakov7296af12017-08-09 21:52:48 +0000207 std::string newVal(value.begin(), rbegin.base());
208 CHECK(!newVal.empty());
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700209
210 uint64_t rawValue = 0;
211
212 bool parseOK = base::ParseUint(newVal, &rawValue);
213 if (!parseOK) {
214 return nullptr;
215 }
216
217 ScalarType::Kind kind;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700218
219 // guess literal type.
220 if(isLong) {
221 if(isUnsigned) // ul
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700222 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700223 else // l
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700224 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700225 } else { // no l suffix
226 if(isUnsigned) { // u
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700227 if(rawValue <= UINT32_MAX)
228 kind = SK(UINT32);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700229 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700230 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700231 } else { // no suffix
232 if(isHex) {
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700233 if(rawValue <= INT32_MAX) // rawValue always >= 0
234 kind = SK(INT32);
235 else if(rawValue <= UINT32_MAX)
236 kind = SK(UINT32);
237 else if(rawValue <= INT64_MAX) // rawValue always >= 0
238 kind = SK(INT64);
239 else if(rawValue <= UINT64_MAX)
240 kind = SK(UINT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700241 else
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700242 return nullptr;
243 } else {
244 if(rawValue <= INT32_MAX) // rawValue always >= 0
245 kind = SK(INT32);
246 else
247 kind = SK(INT64);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700248 }
249 }
250 }
Steven Morelandd9d6dcb2017-09-20 15:55:39 -0700251
252 return new LiteralConstantExpression(kind, rawValue, value);
Yifan Hong57886972016-08-17 10:42:15 -0700253}
254
Timur Iskhakov7296af12017-08-09 21:52:48 +0000255void LiteralConstantExpression::evaluate() {
256 // Evaluated in constructor
257 CHECK(isEvaluated());
258}
Yifan Hongf24fa852016-09-23 11:03:15 -0700259
Timur Iskhakov7296af12017-08-09 21:52:48 +0000260void UnaryConstantExpression::evaluate() {
261 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700262 CHECK(mUnary->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000263 mIsEvaluated = true;
264
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700265 mValueKind = mUnary->mValueKind;
Timur Iskhakov7296af12017-08-09 21:52:48 +0000266
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700267#define CASE_UNARY(__type__) \
268 mValue = handleUnary(mOp, static_cast<__type__>(mUnary->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000269 return;
Yifan Hong57886972016-08-17 10:42:15 -0700270
Yifan Hongf24fa852016-09-23 11:03:15 -0700271 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700272}
Yifan Hong57886972016-08-17 10:42:15 -0700273
Timur Iskhakov7296af12017-08-09 21:52:48 +0000274void BinaryConstantExpression::evaluate() {
275 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700276 CHECK(mLval->isEvaluated());
277 CHECK(mRval->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000278 mIsEvaluated = true;
279
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700280 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
281
282 // CASE 1: + - * / % | ^ & < > <= >= == !=
283 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
284 // promoted kind for both operands.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700285 ScalarType::Kind promoted = usualArithmeticConversion(integralPromotion(mLval->mValueKind),
286 integralPromotion(mRval->mValueKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700287 // result kind.
288 mValueKind = isArithmeticOrBitflip
289 ? promoted // arithmetic or bitflip operators generates promoted type
290 : SK(BOOL); // comparison operators generates bool
291
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700292#define CASE_BINARY_COMMON(__type__) \
293 mValue = handleBinaryCommon(static_cast<__type__>(mLval->mValue), mOp, \
294 static_cast<__type__>(mRval->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000295 return;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700296
Yifan Hongf24fa852016-09-23 11:03:15 -0700297 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700298 }
299
300 // CASE 2: << >>
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700301 std::string newOp = mOp;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700302 if(OP_IS_BIN_SHIFT) {
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700303 mValueKind = integralPromotion(mLval->mValueKind);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700304 // instead of promoting rval, simply casting it to int64 should also be good.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700305 int64_t numBits = mRval->cast<int64_t>();
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700306 if(numBits < 0) {
307 // shifting with negative number of bits is undefined in C. In HIDL it
308 // is defined as shifting into the other direction.
Timur Iskhakov7296af12017-08-09 21:52:48 +0000309 newOp = OPEQ("<<") ? std::string(">>") : std::string("<<");
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700310 numBits = -numBits;
311 }
312
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700313#define CASE_SHIFT(__type__) \
314 mValue = handleShift(static_cast<__type__>(mLval->mValue), newOp, numBits); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000315 return;
Yifan Hong57886972016-08-17 10:42:15 -0700316
Yifan Hongf24fa852016-09-23 11:03:15 -0700317 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700318 }
Yifan Hong57886972016-08-17 10:42:15 -0700319
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700320 // CASE 3: && ||
321 if(OP_IS_BIN_LOGICAL) {
322 mValueKind = SK(BOOL);
323 // easy; everything is bool.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700324 mValue = handleLogical(mLval->mValue, mOp, mRval->mValue);
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700325 return;
326 }
Yifan Hong57886972016-08-17 10:42:15 -0700327
Yifan Hongf24fa852016-09-23 11:03:15 -0700328 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700329}
330
Timur Iskhakov7296af12017-08-09 21:52:48 +0000331void TernaryConstantExpression::evaluate() {
332 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700333 CHECK(mCond->isEvaluated());
334 CHECK(mTrueVal->isEvaluated());
335 CHECK(mFalseVal->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000336 mIsEvaluated = true;
337
Timur Iskhakov891a8662017-08-25 21:53:48 -0700338 // note: for ?:, unlike arithmetic ops, integral promotion is not processed.
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700339 mValueKind = usualArithmeticConversion(mTrueVal->mValueKind, mFalseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700340
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700341#define CASE_TERNARY(__type__) \
342 mValue = mCond->mValue ? (static_cast<__type__>(mTrueVal->mValue)) \
343 : (static_cast<__type__>(mFalseVal->mValue)); \
Timur Iskhakov7296af12017-08-09 21:52:48 +0000344 return;
Yifan Hong57886972016-08-17 10:42:15 -0700345
Yifan Hongf24fa852016-09-23 11:03:15 -0700346 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700347}
348
Timur Iskhakov7296af12017-08-09 21:52:48 +0000349void ReferenceConstantExpression::evaluate() {
350 if (isEvaluated()) return;
Timur Iskhakov891a8662017-08-25 21:53:48 -0700351 CHECK(mReference->constExpr() != nullptr);
Timur Iskhakov7296af12017-08-09 21:52:48 +0000352
Timur Iskhakovd27580c2017-08-09 20:14:52 -0700353 ConstantExpression* expr = mReference->constExpr();
Timur Iskhakov891a8662017-08-25 21:53:48 -0700354 CHECK(expr->isEvaluated());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000355
356 mValueKind = expr->mValueKind;
357 mValue = expr->mValue;
358 mIsEvaluated = true;
Yifan Hong52165692016-08-12 18:06:40 -0700359}
Yifan Hong57886972016-08-17 10:42:15 -0700360
Steven Moreland12f0ab12018-11-02 17:27:37 -0700361status_t AttributeConstantExpression::validate() const {
362 if (mTag == "len") {
363 if (!mReference->isEnum()) {
364 std::cerr << "ERROR: " << mExpr << " refers to " << mReference->typeName()
365 << " but should refer to an enum." << std::endl;
366 return UNKNOWN_ERROR;
367 }
368 } else {
369 std::cerr << "ERROR: " << mExpr << " is not a supported tag" << std::endl;
370 return UNKNOWN_ERROR;
371 }
372
373 return OK;
374}
375
376void AttributeConstantExpression::evaluate() {
377 if (isEvaluated()) return;
378
379 CHECK(mTag == "len");
380 CHECK(mReference->isEnum());
381
382 EnumType* enumType = static_cast<EnumType*>(mReference.get());
383 mValue = enumType->numValueNames();
384
385 if (mValue <= INT32_MAX)
386 mValueKind = SK(INT32);
387 else
388 mValueKind = SK(INT64);
389
390 mIsEvaluated = true;
391}
392
Timur Iskhakov7296af12017-08-09 21:52:48 +0000393std::unique_ptr<ConstantExpression> ConstantExpression::addOne(ScalarType::Kind baseKind) {
394 auto ret = std::make_unique<BinaryConstantExpression>(
395 this, "+", ConstantExpression::One(baseKind).release());
Timur Iskhakov7296af12017-08-09 21:52:48 +0000396 return ret;
Yifan Hongf24fa852016-09-23 11:03:15 -0700397}
398
Yifan Hongfc610cd2016-09-22 13:34:45 -0700399std::string ConstantExpression::value() const {
Steven Morelandf21962d2018-08-09 12:44:40 -0700400 return value(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700401}
402
Yifan Hongc07b2022016-11-08 12:44:24 -0800403std::string ConstantExpression::value(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000404 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700405 return rawValue(castKind) + descriptionSuffix();
Yifan Hongc07b2022016-11-08 12:44:24 -0800406}
407
Yifan Hongf24fa852016-09-23 11:03:15 -0700408std::string ConstantExpression::cppValue() const {
409 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700410}
411
Yifan Hongfc610cd2016-09-22 13:34:45 -0700412std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000413 CHECK(isEvaluated());
Yifan Hongf24fa852016-09-23 11:03:15 -0700414 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700415 // this is a hack to translate
416 // enum x : int64_t { y = 1l << 63 };
417 // into
418 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
419 // by adding the explicit cast.
420 // Because 9223372036854775808 is uint64_t, and
421 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
422 // be narrowed to int64_t.
423 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700424 literal = "static_cast<" +
425 ScalarType(SK(INT64), nullptr /* parent */).getCppStackType() // "int64_t"
426 + ">(" + literal + "ull)";
427 } else {
428 // add suffix if necessary.
429 if (castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
430 if (castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700431 }
Yifan Hong57886972016-08-17 10:42:15 -0700432
Steven Morelandf21962d2018-08-09 12:44:40 -0700433 return literal + descriptionSuffix();
Yifan Hong57886972016-08-17 10:42:15 -0700434}
435
Yifan Hongf24fa852016-09-23 11:03:15 -0700436std::string ConstantExpression::javaValue() const {
437 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700438}
439
Yifan Hongf24fa852016-09-23 11:03:15 -0700440std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000441 CHECK(isEvaluated());
Steven Morelandf21962d2018-08-09 12:44:40 -0700442 std::string literal;
443
Yifan Hongf24fa852016-09-23 11:03:15 -0700444 switch(castKind) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700445 case SK(UINT64):
446 literal = rawValue(SK(INT64)) + "L";
447 break;
448 case SK(INT64):
449 literal = rawValue(SK(INT64)) + "L";
450 break;
451 case SK(UINT32):
452 literal = rawValue(SK(INT32));
453 break;
454 case SK(UINT16):
455 literal = rawValue(SK(INT16));
456 break;
457 case SK(UINT8):
458 literal = rawValue(SK(INT8));
459 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700460 case SK(BOOL) :
Steven Morelandf21962d2018-08-09 12:44:40 -0700461 literal = this->cast<bool>() ? "true" : "false";
462 break;
463 default:
464 literal = rawValue(castKind);
465 break;
Yifan Hongf24fa852016-09-23 11:03:15 -0700466 }
Steven Morelandf21962d2018-08-09 12:44:40 -0700467
468 return literal + descriptionSuffix();
469}
470
471const std::string& ConstantExpression::expression() const {
Steven Morelandf21962d2018-08-09 12:44:40 -0700472 return mExpr;
473}
474
475std::string ConstantExpression::rawValue() const {
476 return rawValue(mValueKind);
Yifan Hongf24fa852016-09-23 11:03:15 -0700477}
478
479std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000480 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700481
Yifan Hongfc610cd2016-09-22 13:34:45 -0700482#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700483
Yi Kongd7f8ab32018-07-24 11:27:02 -0700484 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return nullptr; );
Yifan Hong57886972016-08-17 10:42:15 -0700485}
486
Yifan Hong19ca75a2016-08-31 10:20:03 -0700487template<typename T>
488T ConstantExpression::cast() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000489 CHECK(isEvaluated());
Yifan Hong57886972016-08-17 10:42:15 -0700490
Yifan Hong19ca75a2016-08-31 10:20:03 -0700491#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700492
Yifan Hongf24fa852016-09-23 11:03:15 -0700493 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700494}
495
Steven Morelandf21962d2018-08-09 12:44:40 -0700496std::string ConstantExpression::descriptionSuffix() const {
497 CHECK(isEvaluated());
498
499 if (!mTrivialDescription) {
500 CHECK(!mExpr.empty());
501
502 return " /* " + mExpr + " */";
503 }
504 return "";
505}
506
Yifan Honge77ca132016-09-27 10:49:05 -0700507size_t ConstantExpression::castSizeT() const {
Timur Iskhakov7296af12017-08-09 21:52:48 +0000508 CHECK(isEvaluated());
Yifan Honge77ca132016-09-27 10:49:05 -0700509 return this->cast<size_t>();
510}
511
Timur Iskhakova6d33882017-09-01 13:02:09 -0700512bool ConstantExpression::isReferenceConstantExpression() const {
513 return false;
514}
515
Steven Moreland12f0ab12018-11-02 17:27:37 -0700516status_t ConstantExpression::validate() const {
517 return OK;
518}
519
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700520std::vector<ConstantExpression*> ConstantExpression::getConstantExpressions() {
521 const auto& constRet = static_cast<const ConstantExpression*>(this)->getConstantExpressions();
522 std::vector<ConstantExpression*> ret(constRet.size());
523 std::transform(constRet.begin(), constRet.end(), ret.begin(),
524 [](const auto* ce) { return const_cast<ConstantExpression*>(ce); });
525 return ret;
526}
527
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700528std::vector<Reference<LocalIdentifier>*> ConstantExpression::getReferences() {
529 const auto& constRet = static_cast<const ConstantExpression*>(this)->getReferences();
530 std::vector<Reference<LocalIdentifier>*> ret(constRet.size());
531 std::transform(constRet.begin(), constRet.end(), ret.begin(),
532 [](const auto* ce) { return const_cast<Reference<LocalIdentifier>*>(ce); });
533 return ret;
534}
535
536std::vector<const Reference<LocalIdentifier>*> ConstantExpression::getReferences() const {
537 return {};
538}
539
Steven Moreland12f0ab12018-11-02 17:27:37 -0700540std::vector<Reference<Type>*> ConstantExpression::getTypeReferences() {
541 const auto& constRet = static_cast<const ConstantExpression*>(this)->getTypeReferences();
542 std::vector<Reference<Type>*> ret(constRet.size());
543 std::transform(constRet.begin(), constRet.end(), ret.begin(),
544 [](const auto* ce) { return const_cast<Reference<Type>*>(ce); });
545 return ret;
546}
547
548std::vector<const Reference<Type>*> ConstantExpression::getTypeReferences() const {
549 return {};
550}
551
Timur Iskhakov891a8662017-08-25 21:53:48 -0700552status_t ConstantExpression::recursivePass(const std::function<status_t(ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700553 std::unordered_set<const ConstantExpression*>* visited,
554 bool processBeforeDependencies) {
Timur Iskhakov35930c42017-08-28 18:49:54 -0700555 if (mIsPostParseCompleted) return OK;
556
Timur Iskhakov891a8662017-08-25 21:53:48 -0700557 if (visited->find(this) != visited->end()) return OK;
558 visited->insert(this);
559
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700560 if (processBeforeDependencies) {
561 status_t err = func(this);
562 if (err != OK) return err;
563 }
564
Timur Iskhakov891a8662017-08-25 21:53:48 -0700565 for (auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700566 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov891a8662017-08-25 21:53:48 -0700567 if (err != OK) return err;
568 }
569
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700570 for (auto* nextRef : getReferences()) {
571 auto* nextCE = nextRef->shallowGet()->constExpr();
572 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700573 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700574 if (err != OK) return err;
575 }
576
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700577 if (!processBeforeDependencies) {
578 status_t err = func(this);
579 if (err != OK) return err;
580 }
Timur Iskhakov891a8662017-08-25 21:53:48 -0700581
582 return OK;
583}
584
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700585status_t ConstantExpression::recursivePass(
586 const std::function<status_t(const ConstantExpression*)>& func,
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700587 std::unordered_set<const ConstantExpression*>* visited, bool processBeforeDependencies) const {
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700588 if (mIsPostParseCompleted) return OK;
589
590 if (visited->find(this) != visited->end()) return OK;
591 visited->insert(this);
592
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700593 if (processBeforeDependencies) {
594 status_t err = func(this);
595 if (err != OK) return err;
596 }
597
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700598 for (const auto* nextCE : getConstantExpressions()) {
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700599 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700600 if (err != OK) return err;
601 }
602
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700603 for (const auto* nextRef : getReferences()) {
604 const auto* nextCE = nextRef->shallowGet()->constExpr();
605 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700606 status_t err = nextCE->recursivePass(func, visited, processBeforeDependencies);
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700607 if (err != OK) return err;
608 }
609
Timur Iskhakov82c048e2017-09-09 01:20:53 -0700610 if (!processBeforeDependencies) {
611 status_t err = func(this);
612 if (err != OK) return err;
613 }
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700614
615 return OK;
616}
617
Timur Iskhakova6d33882017-09-01 13:02:09 -0700618ConstantExpression::CheckAcyclicStatus::CheckAcyclicStatus(
619 status_t status, const ConstantExpression* cycleEnd,
620 const ReferenceConstantExpression* lastReference)
621 : status(status), cycleEnd(cycleEnd), lastReference(lastReference) {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700622 CHECK(cycleEnd == nullptr || status != OK);
Timur Iskhakova6d33882017-09-01 13:02:09 -0700623 CHECK((cycleEnd == nullptr) == (lastReference == nullptr));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700624}
625
626ConstantExpression::CheckAcyclicStatus ConstantExpression::checkAcyclic(
627 std::unordered_set<const ConstantExpression*>* visited,
628 std::unordered_set<const ConstantExpression*>* stack) const {
629 if (stack->find(this) != stack->end()) {
Timur Iskhakova6d33882017-09-01 13:02:09 -0700630 CHECK(isReferenceConstantExpression())
631 << "Only reference constant expression could be the cycle end";
632
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700633 std::cerr << "ERROR: Cyclic declaration:\n";
Timur Iskhakova6d33882017-09-01 13:02:09 -0700634 return CheckAcyclicStatus(UNKNOWN_ERROR, this,
635 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700636 }
637
638 if (visited->find(this) != visited->end()) return CheckAcyclicStatus(OK);
639 visited->insert(this);
640 stack->insert(this);
641
642 for (const auto* nextCE : getConstantExpressions()) {
643 auto err = nextCE->checkAcyclic(visited, stack);
644 if (err.status != OK) {
645 return err;
646 }
647 }
648
649 for (const auto* nextRef : getReferences()) {
650 const auto* nextCE = nextRef->shallowGet()->constExpr();
651 CHECK(nextCE != nullptr) << "Local identifier is not a constant expression";
652 auto err = nextCE->checkAcyclic(visited, stack);
653
654 if (err.status != OK) {
655 if (err.cycleEnd == nullptr) return err;
656
657 // Only ReferenceConstantExpression has references,
Timur Iskhakova6d33882017-09-01 13:02:09 -0700658 CHECK(isReferenceConstantExpression())
659 << "Only reference constant expression could have refereneces";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700660
Timur Iskhakova6d33882017-09-01 13:02:09 -0700661 // mExpr is defined explicitly before evaluation
662 std::cerr << " '" << err.lastReference->mExpr << "' in '" << mExpr << "' at "
663 << nextRef->location() << "\n";
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700664
665 if (err.cycleEnd == this) {
666 return CheckAcyclicStatus(err.status);
667 }
Timur Iskhakova6d33882017-09-01 13:02:09 -0700668 return CheckAcyclicStatus(err.status, err.cycleEnd,
669 static_cast<const ReferenceConstantExpression*>(this));
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700670 }
671 }
672
673 CHECK(stack->find(this) != stack->end());
674 stack->erase(this);
675 return CheckAcyclicStatus(OK);
676}
677
Timur Iskhakov35930c42017-08-28 18:49:54 -0700678void ConstantExpression::setPostParseCompleted() {
679 CHECK(!mIsPostParseCompleted);
680 mIsPostParseCompleted = true;
681}
682
Neel Mehta1ca3e782019-07-18 15:16:22 -0700683void ConstantExpression::surroundWithParens() {
684 mExpr = "(" + mExpr + ")";
685}
686
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700687std::vector<const ConstantExpression*> LiteralConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700688 return {};
689}
690
Timur Iskhakov7296af12017-08-09 21:52:48 +0000691UnaryConstantExpression::UnaryConstantExpression(const std::string& op, ConstantExpression* value)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700692 : ConstantExpression(op + value->mExpr), mUnary(value), mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000693
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700694std::vector<const ConstantExpression*> UnaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700695 return {mUnary};
696}
697
Timur Iskhakov7296af12017-08-09 21:52:48 +0000698BinaryConstantExpression::BinaryConstantExpression(ConstantExpression* lval, const std::string& op,
699 ConstantExpression* rval)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700700 : ConstantExpression(lval->mExpr + " " + op + " " + rval->mExpr),
Neel Mehta3b414a82019-07-02 15:47:48 -0700701 mLval(lval),
702 mRval(rval),
703 mOp(op) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000704
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700705std::vector<const ConstantExpression*> BinaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700706 return {mLval, mRval};
707}
708
Timur Iskhakov7296af12017-08-09 21:52:48 +0000709TernaryConstantExpression::TernaryConstantExpression(ConstantExpression* cond,
710 ConstantExpression* trueVal,
711 ConstantExpression* falseVal)
Neel Mehta1ca3e782019-07-18 15:16:22 -0700712 : ConstantExpression(cond->mExpr + "?" + trueVal->mExpr + ":" + falseVal->mExpr),
Neel Mehta3b414a82019-07-02 15:47:48 -0700713 mCond(cond),
714 mTrueVal(trueVal),
715 mFalseVal(falseVal) {}
Timur Iskhakov7296af12017-08-09 21:52:48 +0000716
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700717std::vector<const ConstantExpression*> TernaryConstantExpression::getConstantExpressions() const {
Timur Iskhakov891a8662017-08-25 21:53:48 -0700718 return {mCond, mTrueVal, mFalseVal};
719}
720
Timur Iskhakov7296af12017-08-09 21:52:48 +0000721ReferenceConstantExpression::ReferenceConstantExpression(const Reference<LocalIdentifier>& value,
722 const std::string& expr)
Neel Mehta3b414a82019-07-02 15:47:48 -0700723 : ConstantExpression(expr), mReference(value) {
Timur Iskhakov505e5612017-08-27 18:26:48 -0700724 mTrivialDescription = mExpr.empty();
Timur Iskhakov7296af12017-08-09 21:52:48 +0000725}
726
Timur Iskhakova6d33882017-09-01 13:02:09 -0700727bool ReferenceConstantExpression::isReferenceConstantExpression() const {
728 return true;
729}
730
Timur Iskhakovb58f4182017-08-29 15:19:24 -0700731std::vector<const ConstantExpression*> ReferenceConstantExpression::getConstantExpressions() const {
Timur Iskhakov77dd65c2017-08-31 22:46:56 -0700732 // Returns reference instead
733 return {};
734}
735
736std::vector<const Reference<LocalIdentifier>*> ReferenceConstantExpression::getReferences() const {
737 return {&mReference};
Timur Iskhakov891a8662017-08-25 21:53:48 -0700738}
739
Steven Moreland12f0ab12018-11-02 17:27:37 -0700740AttributeConstantExpression::AttributeConstantExpression(const Reference<Type>& value,
741 const std::string& fqname,
742 const std::string& tag)
Neel Mehta3b414a82019-07-02 15:47:48 -0700743 : ConstantExpression(fqname + "#" + tag), mReference(value), mTag(tag) {}
Steven Moreland12f0ab12018-11-02 17:27:37 -0700744
745std::vector<const ConstantExpression*> AttributeConstantExpression::getConstantExpressions() const {
746 // Returns reference instead
747 return {};
748}
749
750std::vector<const Reference<Type>*> AttributeConstantExpression::getTypeReferences() const {
751 return {&mReference};
752}
753
Yifan Hong57886972016-08-17 10:42:15 -0700754/*
755
756Evaluating expressions in HIDL language
757
758The following rules are mostly like that in:
759http://en.cppreference.com/w/cpp/language/operator_arithmetic
760http://en.cppreference.com/w/cpp/language/operator_logical
761http://en.cppreference.com/w/cpp/language/operator_comparison
762http://en.cppreference.com/w/cpp/language/operator_other
763
764The type of literal is the first type which the value
765can fit from the list of types depending on the suffix and bases.
766
767suffix decimal bases hexadecimal bases
768no suffix int32_t int32_t
769 int64_t uint32_t
770 int64_t
771 uint64_t
772
773u/U uint32_t (same as left)
774 uint64_t
775
776l/L int64_t int64_t
777
778ul/UL/uL/Ul uint64_t uint64_t
779
780
781Note: There are no negative integer literals.
782 -1 is the unary minus applied to 1.
783
784Unary arithmetic and bitwise operators (~ + -):
785 don't change the type of the argument.
786 (so -1u = -(1u) has type uint32_t)
787
788Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
7891. Integral promotion is first applied on both sides.
7902. If both operands have the same type, no promotion is necessary.
7913. Usual arithmetic conversions.
792
793Integral promotion: if an operand is of a type with less than 32 bits,
794(including bool), it is promoted to int32_t.
795
796Usual arithmetic conversions:
7971. If operands are both signed or both unsigned, lesser conversion rank is
798 converted to greater conversion rank.
7992. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
8003. Otherwise, if signed's type can hold all values in unsigned's type,
801 -> signed's type
8024. Otherwise, both converted to the unsigned counterpart of the signed operand's
803 type.
804rank: bool < int8_t < int16_t < int32_t < int64_t
805
806
807Shift operators (<< >>):
8081. Integral promotion is applied on both sides.
8092. For unsigned a, a << b discards bits that shifts out.
810 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
811 For signed negative a, a << b gives error.
8123. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
813 For signed negative a, a >> b discards bits that shifts out, and the signed
814 bit gets extended. ("arithmetic right shift")
8154. Shifting with negative number of bits is undefined. (Currently, the
816 parser will shift into the other direction. This behavior may change.)
8175. Shifting with number of bits exceeding the width of the type is undefined.
818 (Currently, 1 << 32 == 1. This behavior may change.)
819
820Logical operators (!, &&, ||):
8211. Convert first operand to bool. (true if non-zero, false otherwise)
8222. If short-circuited, return the result as type bool, value 1 or 0.
8233. Otherwise, convert second operand to bool, evaluate the result, and return
824 the result in the same fashion.
825
826Arithmetic comparison operators (< > <= >= == !=):
8271. Promote operands in the same way as binary arithmetic and bitwise operators.
828 (Integral promotion + Usual arithmetic conversions)
8292. Return type bool, value 0 or 1 the same way as logical operators.
830
831Ternary conditional operator (?:):
8321. Evaluate the conditional and evaluate the operands.
8332. Return type of expression is the type under usual arithmetic conversions on
834 the second and third operand. (No integral promotions necessary.)
835
836*/
837
Yifan Hong52165692016-08-12 18:06:40 -0700838} // namespace android
839