blob: 850faf8e1c78083116a5426968c174af3c739a03 [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 <stdio.h>
20#include <string>
Yifan Hong57886972016-08-17 10:42:15 -070021#include <android-base/parseint.h>
22#include <android-base/logging.h>
23#include <sstream>
24
Yifan Hongf24fa852016-09-23 11:03:15 -070025#include "EnumType.h"
26
Yifan Hong57886972016-08-17 10:42:15 -070027// The macros are really nasty here. Consider removing
28// as many macros as possible.
29
30#define STREQ(__x__, __y__) (strcmp((__x__), (__y__)) == 0)
31#define OPEQ(__y__) STREQ(op, __y__)
32#define COMPUTE_UNARY(__op__) if(OPEQ(#__op__)) return __op__ val;
33#define COMPUTE_BINARY(__op__) if(OPEQ(#__op__)) return lval __op__ rval;
34#define OP_IS_BIN_ARITHMETIC (OPEQ("+") || OPEQ("-") || OPEQ("*") || OPEQ("/") || OPEQ("%"))
35#define OP_IS_BIN_BITFLIP (OPEQ("|") || OPEQ("^") || OPEQ("&"))
36#define OP_IS_BIN_COMP (OPEQ("<") || OPEQ(">") || OPEQ("<=") || OPEQ(">=") || OPEQ("==") || OPEQ("!="))
37#define OP_IS_BIN_SHIFT (OPEQ(">>") || OPEQ("<<"))
38#define OP_IS_BIN_LOGICAL (OPEQ("||") || OPEQ("&&"))
39#define SK(__x__) ScalarType::Kind::KIND_##__x__
Yifan Hongf24fa852016-09-23 11:03:15 -070040#define SHOULD_NOT_REACH() CHECK(false) << __LINE__ << ": should not reach here: "
Yifan Hong57886972016-08-17 10:42:15 -070041
42#define SWITCH_KIND(__cond__, __action__, __def__) \
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070043 switch(__cond__) { \
44 case SK(BOOL): __action__(bool) \
45 case SK(UINT8): __action__(uint8_t) \
46 case SK(INT8): __action__(int8_t) \
47 case SK(UINT16): __action__(uint16_t) \
48 case SK(INT16): __action__(int16_t) \
49 case SK(UINT32): __action__(uint32_t) \
50 case SK(INT32): __action__(int32_t) \
51 case SK(UINT64): __action__(uint64_t) \
52 case SK(INT64): __action__(int64_t) \
53 default: __def__ \
54 } \
Yifan Hong52165692016-08-12 18:06:40 -070055
56namespace android {
57
Yifan Hongf24fa852016-09-23 11:03:15 -070058static inline bool isSupported(ScalarType::Kind kind) {
59 return SK(BOOL) == kind || ScalarType(kind).isValidEnumStorageType();
60}
61
Yifan Hong57886972016-08-17 10:42:15 -070062/* See docs at the end for details on integral promotion. */
63ScalarType::Kind integralPromotion(ScalarType::Kind in) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070064 return SK(INT32) < in ? in : SK(INT32); // note that KIND_INT32 < KIND_UINT32
Yifan Hong52165692016-08-12 18:06:40 -070065}
66
Yifan Hong57886972016-08-17 10:42:15 -070067/* See docs at the end for details on usual arithmetic conversion. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070068ScalarType::Kind usualArithmeticConversion(ScalarType::Kind lft,
69 ScalarType::Kind rgt) {
Yifan Hongf24fa852016-09-23 11:03:15 -070070 CHECK(isSupported(lft) && isSupported(rgt));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070071 // Kinds in concern: bool, (u)int[8|16|32|64]
72 if(lft == rgt) return lft; // easy case
73 if(lft == SK(BOOL)) return rgt;
74 if(rgt == SK(BOOL)) return lft;
75 bool isLftSigned = (lft == SK(INT8)) || (lft == SK(INT16))
76 || (lft == SK(INT32)) || (lft == SK(INT64));
77 bool isRgtSigned = (rgt == SK(INT8)) || (rgt == SK(INT16))
78 || (rgt == SK(INT32)) || (rgt == SK(INT64));
79 if(isLftSigned == isRgtSigned) return lft < rgt ? rgt : lft;
80 ScalarType::Kind unsignedRank = isLftSigned ? rgt : lft;
81 ScalarType::Kind signedRank = isLftSigned ? lft : rgt;
82 if(unsignedRank >= signedRank) return unsignedRank;
83 if(signedRank > unsignedRank) return signedRank;
Yifan Hong57886972016-08-17 10:42:15 -070084
Yifan Hong2bd3c1f2016-09-22 13:20:05 -070085 // Although there is such rule to return "the unsigned counterpart of
86 // the signed operand", it should not reach here in our HIDL grammar.
87 LOG(FATAL) << "Could not do usual arithmetic conversion for type "
88 << lft << "and" << rgt;
89 switch(signedRank) {
90 case SK(INT8): return SK(UINT8);
91 case SK(INT16): return SK(UINT16);
92 case SK(INT32): return SK(UINT32);
93 case SK(INT64): return SK(UINT64);
94 default: return SK(UINT64);
95 }
Yifan Hong52165692016-08-12 18:06:40 -070096}
Yifan Hong57886972016-08-17 10:42:15 -070097
98template <class T>
99T handleUnary(const char *op, T val) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700100 COMPUTE_UNARY(+)
101 COMPUTE_UNARY(-)
102 COMPUTE_UNARY(!)
103 COMPUTE_UNARY(~)
104 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700105 SHOULD_NOT_REACH() << "Could not handleUnary for " << op << " " << val;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700106 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700107}
108
109template <class T>
110T handleBinaryCommon(T lval, const char *op, T rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700111 COMPUTE_BINARY(+)
112 COMPUTE_BINARY(-)
113 COMPUTE_BINARY(*)
114 COMPUTE_BINARY(/)
115 COMPUTE_BINARY(%)
116 COMPUTE_BINARY(|)
117 COMPUTE_BINARY(^)
118 COMPUTE_BINARY(&)
119 // comparison operators: return 0 or 1 by nature.
120 COMPUTE_BINARY(==)
121 COMPUTE_BINARY(!=)
122 COMPUTE_BINARY(<)
123 COMPUTE_BINARY(>)
124 COMPUTE_BINARY(<=)
125 COMPUTE_BINARY(>=)
126 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700127 SHOULD_NOT_REACH() << "Could not handleBinaryCommon for "
128 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700129 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700130}
131
132template <class T>
133T handleShift(T lval, const char *op, int64_t rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700134 // just cast rval to int64_t and it should fit.
135 COMPUTE_BINARY(>>)
136 COMPUTE_BINARY(<<)
137 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700138 SHOULD_NOT_REACH() << "Could not handleShift for"
139 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700140 return static_cast<T>(0xdeadbeef);
Yifan Hong57886972016-08-17 10:42:15 -0700141}
142
143bool handleLogical(bool lval, const char *op, bool rval) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700144 COMPUTE_BINARY(||);
145 COMPUTE_BINARY(&&);
146 // Should not reach here.
Yifan Hongf24fa852016-09-23 11:03:15 -0700147 SHOULD_NOT_REACH() << "Could not handleLogical for"
148 << lval << " " << op << " " << rval;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700149 return false;
Yifan Hong57886972016-08-17 10:42:15 -0700150}
151
Yifan Hongf24fa852016-09-23 11:03:15 -0700152ConstantExpression::ConstantExpression() {
153}
154
155ConstantExpression ConstantExpression::Zero(ScalarType::Kind kind) {
156 ConstantExpression ce("0");
157 CHECK(isSupported(kind));
158 ce.mValueKind = kind;
159 return ce;
160}
161ConstantExpression ConstantExpression::One(ScalarType::Kind kind) {
162 ConstantExpression ce("1");
163 CHECK(isSupported(kind));
164 ce.mValueKind = kind;
165 return ce;
166}
167
168ConstantExpression::ConstantExpression(const ConstantExpression& other) {
169 *this = other;
170}
171
Yifan Hong5706a432016-11-02 09:44:18 -0700172/* Copy constructor, with the expr overriden and treated non-trivial */
Yifan Hongf24fa852016-09-23 11:03:15 -0700173ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
174 *this = other;
175 mExpr = expr;
Yifan Hong5706a432016-11-02 09:44:18 -0700176 mTrivialDescription = false;
Yifan Hongf24fa852016-09-23 11:03:15 -0700177}
178
179ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
180 mType = other.mType;
181 mValueKind = other.mValueKind;
182 mValue = other.mValue;
183 mExpr = other.mExpr;
Yifan Hong5706a432016-11-02 09:44:18 -0700184 mTrivialDescription = other.mTrivialDescription;
Yifan Hongf24fa852016-09-23 11:03:15 -0700185 return *this;
186}
187
Yifan Hong57886972016-08-17 10:42:15 -0700188/* Literals. */
Yifan Hongf24fa852016-09-23 11:03:15 -0700189ConstantExpression::ConstantExpression(const char *value)
Yifan Hong5706a432016-11-02 09:44:18 -0700190 : mExpr(value), mType(kConstExprLiteral), mTrivialDescription(true) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700191 const char* head = value, *tail = head + strlen(value) - 1;
192 bool isLong = false, isUnsigned = false;
193 bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
194 while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700195 isUnsigned |= (*tail == 'u' || *tail == 'U');
196 isLong |= (*tail == 'l' || *tail == 'L');
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700197 tail--;
Yifan Hong57886972016-08-17 10:42:15 -0700198 }
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700199 char *newVal = strndup(value, tail - head + 1);
200 bool parseOK = base::ParseUint(newVal, &mValue);
201 free(newVal);
Yifan Hongf24fa852016-09-23 11:03:15 -0700202 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700203
204 // guess literal type.
205 if(isLong) {
206 if(isUnsigned) // ul
207 mValueKind = SK(UINT64);
208 else // l
209 mValueKind = SK(INT64);
210 } else { // no l suffix
211 if(isUnsigned) { // u
212 if(mValue <= UINT32_MAX)
213 mValueKind = SK(UINT32);
214 else
215 mValueKind = SK(UINT64);
216 } else { // no suffix
217 if(isHex) {
218 if(mValue <= INT32_MAX) // mValue always >= 0
219 mValueKind = SK(INT32);
220 else if(mValue <= UINT32_MAX)
221 mValueKind = SK(UINT32);
222 else if(mValue <= INT64_MAX) // mValue always >= 0
223 mValueKind = SK(INT64);
224 else if(mValue <= UINT64_MAX)
225 mValueKind = SK(UINT64);
226 } else {
227 if(mValue <= INT32_MAX) // mValue always >= 0
228 mValueKind = SK(INT32);
229 else
230 mValueKind = SK(INT64);
231 }
232 }
233 }
Yifan Hong57886972016-08-17 10:42:15 -0700234}
235
236/* Unary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700237ConstantExpression::ConstantExpression(const char *op,
238 const ConstantExpression *value)
Yifan Hongf24fa852016-09-23 11:03:15 -0700239 : mExpr(std::string("(") + op + value->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700240 mType(kConstExprUnary),
241 mValueKind(value->mValueKind) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700242
Yifan Hong57886972016-08-17 10:42:15 -0700243#define CASE_UNARY(__type__)\
244 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
245
Yifan Hongf24fa852016-09-23 11:03:15 -0700246 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700247}
Yifan Hong57886972016-08-17 10:42:15 -0700248
249/* Binary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700250ConstantExpression::ConstantExpression(const ConstantExpression *lval,
251 const char *op,
252 const ConstantExpression* rval)
Yifan Hongf24fa852016-09-23 11:03:15 -0700253 : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700254 mType(kConstExprBinary)
Yifan Hong57886972016-08-17 10:42:15 -0700255{
Yifan Hong57886972016-08-17 10:42:15 -0700256
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700257 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
258
259 // CASE 1: + - * / % | ^ & < > <= >= == !=
260 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
261 // promoted kind for both operands.
262 ScalarType::Kind promoted = usualArithmeticConversion(
263 integralPromotion(lval->mValueKind),
264 integralPromotion(rval->mValueKind));
265 // result kind.
266 mValueKind = isArithmeticOrBitflip
267 ? promoted // arithmetic or bitflip operators generates promoted type
268 : SK(BOOL); // comparison operators generates bool
269
270#define CASE_BINARY_COMMON(__type__)\
271 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
272
Yifan Hongf24fa852016-09-23 11:03:15 -0700273 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700274 }
275
276 // CASE 2: << >>
277 if(OP_IS_BIN_SHIFT) {
278 mValueKind = integralPromotion(lval->mValueKind);
279 // instead of promoting rval, simply casting it to int64 should also be good.
280 int64_t numBits = rval->cast<int64_t>();
281 if(numBits < 0) {
282 // shifting with negative number of bits is undefined in C. In HIDL it
283 // is defined as shifting into the other direction.
284 op = OPEQ("<<") ? ">>" : "<<";
285 numBits = -numBits;
286 }
287
Yifan Hong57886972016-08-17 10:42:15 -0700288#define CASE_SHIFT(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700289 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
Yifan Hong57886972016-08-17 10:42:15 -0700290
Yifan Hongf24fa852016-09-23 11:03:15 -0700291 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700292 }
Yifan Hong57886972016-08-17 10:42:15 -0700293
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700294 // CASE 3: && ||
295 if(OP_IS_BIN_LOGICAL) {
296 mValueKind = SK(BOOL);
297 // easy; everything is bool.
298 mValue = handleLogical(lval->mValue, op, rval->mValue);
299 return;
300 }
Yifan Hong57886972016-08-17 10:42:15 -0700301
Yifan Hongf24fa852016-09-23 11:03:15 -0700302 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700303}
304
305/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700306ConstantExpression::ConstantExpression(const ConstantExpression *cond,
307 const ConstantExpression *trueVal,
308 const ConstantExpression *falseVal)
Yifan Hongf24fa852016-09-23 11:03:15 -0700309 : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
310 + ":" + falseVal->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700311 mType(kConstExprTernary) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700312
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700313 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
314 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
315 falseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700316
317#define CASE_TERNARY(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700318 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
Yifan Hong57886972016-08-17 10:42:15 -0700319
Yifan Hongf24fa852016-09-23 11:03:15 -0700320 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700321}
322
Yifan Hongf24fa852016-09-23 11:03:15 -0700323ConstantExpression ConstantExpression::addOne() const {
324 ConstantExpression myOne = ConstantExpression::One(mValueKind);
325 return ConstantExpression(this, "+", &myOne).toLiteral();
Yifan Hong52165692016-08-12 18:06:40 -0700326}
Yifan Hong57886972016-08-17 10:42:15 -0700327
Yifan Hongf24fa852016-09-23 11:03:15 -0700328ConstantExpression &ConstantExpression::toLiteral() {
329 mExpr = value();
330 mType = kConstExprLiteral;
331 return *this;
332}
333
334const std::string &ConstantExpression::description() const {
335 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700336}
337
Yifan Hong5706a432016-11-02 09:44:18 -0700338bool ConstantExpression::descriptionIsTrivial() const {
339 return mTrivialDescription;
340}
341
Yifan Hongfc610cd2016-09-22 13:34:45 -0700342std::string ConstantExpression::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700343 return rawValue(mValueKind);
344}
345
Yifan Hongc07b2022016-11-08 12:44:24 -0800346std::string ConstantExpression::value(ScalarType::Kind castKind) const {
347 return rawValue(castKind);
348}
349
Yifan Hongf24fa852016-09-23 11:03:15 -0700350std::string ConstantExpression::cppValue() const {
351 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700352}
353
Yifan Hongfc610cd2016-09-22 13:34:45 -0700354std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700355 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700356 // this is a hack to translate
357 // enum x : int64_t { y = 1l << 63 };
358 // into
359 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
360 // by adding the explicit cast.
361 // Because 9223372036854775808 is uint64_t, and
362 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
363 // be narrowed to int64_t.
364 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700365 return strdup(("static_cast<"
366 + ScalarType(SK(INT64)).getCppStackType() // "int64_t"
367 + ">(" + literal + "ull)").c_str());
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700368 }
Yifan Hong57886972016-08-17 10:42:15 -0700369
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700370 // add suffix if necessary.
371 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
372 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700373 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700374}
375
Yifan Hongf24fa852016-09-23 11:03:15 -0700376std::string ConstantExpression::javaValue() const {
377 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700378}
379
Yifan Hongf24fa852016-09-23 11:03:15 -0700380std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
381 switch(castKind) {
382 case SK(UINT64): return rawValue(SK(INT64)) + "L";
383 case SK(INT64): return rawValue(SK(INT64)) + "L";
384 case SK(UINT32): return rawValue(SK(INT32));
385 case SK(UINT16): return rawValue(SK(INT16));
386 case SK(UINT8) : return rawValue(SK(INT8));
387 case SK(BOOL) :
388 return this->cast<bool>() ? strdup("true") : strdup("false");
389 default: break;
390 }
391 return rawValue(castKind);
392}
393
394std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Yifan Hong57886972016-08-17 10:42:15 -0700395
Yifan Hongfc610cd2016-09-22 13:34:45 -0700396#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700397
Yifan Hongf24fa852016-09-23 11:03:15 -0700398 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700399}
400
Yifan Hong19ca75a2016-08-31 10:20:03 -0700401template<typename T>
402T ConstantExpression::cast() const {
Yifan Hong57886972016-08-17 10:42:15 -0700403
Yifan Hong19ca75a2016-08-31 10:20:03 -0700404#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700405
Yifan Hongf24fa852016-09-23 11:03:15 -0700406 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700407}
408
Yifan Honge77ca132016-09-27 10:49:05 -0700409size_t ConstantExpression::castSizeT() const {
410 return this->cast<size_t>();
411}
412
Yifan Hong57886972016-08-17 10:42:15 -0700413/*
414
415Evaluating expressions in HIDL language
416
417The following rules are mostly like that in:
418http://en.cppreference.com/w/cpp/language/operator_arithmetic
419http://en.cppreference.com/w/cpp/language/operator_logical
420http://en.cppreference.com/w/cpp/language/operator_comparison
421http://en.cppreference.com/w/cpp/language/operator_other
422
423The type of literal is the first type which the value
424can fit from the list of types depending on the suffix and bases.
425
426suffix decimal bases hexadecimal bases
427no suffix int32_t int32_t
428 int64_t uint32_t
429 int64_t
430 uint64_t
431
432u/U uint32_t (same as left)
433 uint64_t
434
435l/L int64_t int64_t
436
437ul/UL/uL/Ul uint64_t uint64_t
438
439
440Note: There are no negative integer literals.
441 -1 is the unary minus applied to 1.
442
443Unary arithmetic and bitwise operators (~ + -):
444 don't change the type of the argument.
445 (so -1u = -(1u) has type uint32_t)
446
447Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4481. Integral promotion is first applied on both sides.
4492. If both operands have the same type, no promotion is necessary.
4503. Usual arithmetic conversions.
451
452Integral promotion: if an operand is of a type with less than 32 bits,
453(including bool), it is promoted to int32_t.
454
455Usual arithmetic conversions:
4561. If operands are both signed or both unsigned, lesser conversion rank is
457 converted to greater conversion rank.
4582. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4593. Otherwise, if signed's type can hold all values in unsigned's type,
460 -> signed's type
4614. Otherwise, both converted to the unsigned counterpart of the signed operand's
462 type.
463rank: bool < int8_t < int16_t < int32_t < int64_t
464
465
466Shift operators (<< >>):
4671. Integral promotion is applied on both sides.
4682. For unsigned a, a << b discards bits that shifts out.
469 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
470 For signed negative a, a << b gives error.
4713. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
472 For signed negative a, a >> b discards bits that shifts out, and the signed
473 bit gets extended. ("arithmetic right shift")
4744. Shifting with negative number of bits is undefined. (Currently, the
475 parser will shift into the other direction. This behavior may change.)
4765. Shifting with number of bits exceeding the width of the type is undefined.
477 (Currently, 1 << 32 == 1. This behavior may change.)
478
479Logical operators (!, &&, ||):
4801. Convert first operand to bool. (true if non-zero, false otherwise)
4812. If short-circuited, return the result as type bool, value 1 or 0.
4823. Otherwise, convert second operand to bool, evaluate the result, and return
483 the result in the same fashion.
484
485Arithmetic comparison operators (< > <= >= == !=):
4861. Promote operands in the same way as binary arithmetic and bitwise operators.
487 (Integral promotion + Usual arithmetic conversions)
4882. Return type bool, value 0 or 1 the same way as logical operators.
489
490Ternary conditional operator (?:):
4911. Evaluate the conditional and evaluate the operands.
4922. Return type of expression is the type under usual arithmetic conversions on
493 the second and third operand. (No integral promotions necessary.)
494
495*/
496
Yifan Hong52165692016-08-12 18:06:40 -0700497} // namespace android
498