blob: 9c98046997092985ce666dbecae4f1c5c2cc8f7e [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
172/* Copy constructor, with the expr overriden. */
173ConstantExpression::ConstantExpression(const ConstantExpression& other, std::string expr) {
174 *this = other;
175 mExpr = expr;
176}
177
178ConstantExpression& ConstantExpression::operator=(const ConstantExpression& other) {
179 mType = other.mType;
180 mValueKind = other.mValueKind;
181 mValue = other.mValue;
182 mExpr = other.mExpr;
183 return *this;
184}
185
Yifan Hong57886972016-08-17 10:42:15 -0700186/* Literals. */
Yifan Hongf24fa852016-09-23 11:03:15 -0700187ConstantExpression::ConstantExpression(const char *value)
188 : mExpr(value), mType(kConstExprLiteral) {
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700189 const char* head = value, *tail = head + strlen(value) - 1;
190 bool isLong = false, isUnsigned = false;
191 bool isHex = (value[0] == '0' && (value[1] == 'x' || value[1] == 'X'));
192 while(tail >= head && (*tail == 'u' || *tail == 'U' || *tail == 'l' || *tail == 'L')) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700193 isUnsigned |= (*tail == 'u' || *tail == 'U');
194 isLong |= (*tail == 'l' || *tail == 'L');
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700195 tail--;
Yifan Hong57886972016-08-17 10:42:15 -0700196 }
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700197 char *newVal = strndup(value, tail - head + 1);
198 bool parseOK = base::ParseUint(newVal, &mValue);
199 free(newVal);
Yifan Hongf24fa852016-09-23 11:03:15 -0700200 CHECK(parseOK) << "Could not parse as integer: " << value;
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700201
202 // guess literal type.
203 if(isLong) {
204 if(isUnsigned) // ul
205 mValueKind = SK(UINT64);
206 else // l
207 mValueKind = SK(INT64);
208 } else { // no l suffix
209 if(isUnsigned) { // u
210 if(mValue <= UINT32_MAX)
211 mValueKind = SK(UINT32);
212 else
213 mValueKind = SK(UINT64);
214 } else { // no suffix
215 if(isHex) {
216 if(mValue <= INT32_MAX) // mValue always >= 0
217 mValueKind = SK(INT32);
218 else if(mValue <= UINT32_MAX)
219 mValueKind = SK(UINT32);
220 else if(mValue <= INT64_MAX) // mValue always >= 0
221 mValueKind = SK(INT64);
222 else if(mValue <= UINT64_MAX)
223 mValueKind = SK(UINT64);
224 } else {
225 if(mValue <= INT32_MAX) // mValue always >= 0
226 mValueKind = SK(INT32);
227 else
228 mValueKind = SK(INT64);
229 }
230 }
231 }
Yifan Hong57886972016-08-17 10:42:15 -0700232}
233
234/* Unary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700235ConstantExpression::ConstantExpression(const char *op,
236 const ConstantExpression *value)
Yifan Hongf24fa852016-09-23 11:03:15 -0700237 : mExpr(std::string("(") + op + value->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700238 mType(kConstExprUnary),
239 mValueKind(value->mValueKind) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700240
Yifan Hong57886972016-08-17 10:42:15 -0700241#define CASE_UNARY(__type__)\
242 mValue = handleUnary(op, static_cast<__type__>(value->mValue)); return;
243
Yifan Hongf24fa852016-09-23 11:03:15 -0700244 SWITCH_KIND(mValueKind, CASE_UNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700245}
Yifan Hong57886972016-08-17 10:42:15 -0700246
247/* Binary operations. */
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700248ConstantExpression::ConstantExpression(const ConstantExpression *lval,
249 const char *op,
250 const ConstantExpression* rval)
Yifan Hongf24fa852016-09-23 11:03:15 -0700251 : mExpr(std::string("(") + lval->mExpr + " " + op + " " + rval->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700252 mType(kConstExprBinary)
Yifan Hong57886972016-08-17 10:42:15 -0700253{
Yifan Hong57886972016-08-17 10:42:15 -0700254
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700255 bool isArithmeticOrBitflip = OP_IS_BIN_ARITHMETIC || OP_IS_BIN_BITFLIP;
256
257 // CASE 1: + - * / % | ^ & < > <= >= == !=
258 if(isArithmeticOrBitflip || OP_IS_BIN_COMP) {
259 // promoted kind for both operands.
260 ScalarType::Kind promoted = usualArithmeticConversion(
261 integralPromotion(lval->mValueKind),
262 integralPromotion(rval->mValueKind));
263 // result kind.
264 mValueKind = isArithmeticOrBitflip
265 ? promoted // arithmetic or bitflip operators generates promoted type
266 : SK(BOOL); // comparison operators generates bool
267
268#define CASE_BINARY_COMMON(__type__)\
269 mValue = handleBinaryCommon(static_cast<__type__>(lval->mValue), op, static_cast<__type__>(rval->mValue)); return;
270
Yifan Hongf24fa852016-09-23 11:03:15 -0700271 SWITCH_KIND(promoted, CASE_BINARY_COMMON, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700272 }
273
274 // CASE 2: << >>
275 if(OP_IS_BIN_SHIFT) {
276 mValueKind = integralPromotion(lval->mValueKind);
277 // instead of promoting rval, simply casting it to int64 should also be good.
278 int64_t numBits = rval->cast<int64_t>();
279 if(numBits < 0) {
280 // shifting with negative number of bits is undefined in C. In HIDL it
281 // is defined as shifting into the other direction.
282 op = OPEQ("<<") ? ">>" : "<<";
283 numBits = -numBits;
284 }
285
Yifan Hong57886972016-08-17 10:42:15 -0700286#define CASE_SHIFT(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700287 mValue = handleShift(static_cast<__type__>(lval->mValue), op, numBits); return;
Yifan Hong57886972016-08-17 10:42:15 -0700288
Yifan Hongf24fa852016-09-23 11:03:15 -0700289 SWITCH_KIND(mValueKind, CASE_SHIFT, SHOULD_NOT_REACH(); return;)
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700290 }
Yifan Hong57886972016-08-17 10:42:15 -0700291
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700292 // CASE 3: && ||
293 if(OP_IS_BIN_LOGICAL) {
294 mValueKind = SK(BOOL);
295 // easy; everything is bool.
296 mValue = handleLogical(lval->mValue, op, rval->mValue);
297 return;
298 }
Yifan Hong57886972016-08-17 10:42:15 -0700299
Yifan Hongf24fa852016-09-23 11:03:15 -0700300 SHOULD_NOT_REACH();
Yifan Hong57886972016-08-17 10:42:15 -0700301}
302
303/* Ternary ?: operation. */
Yifan Hong52165692016-08-12 18:06:40 -0700304ConstantExpression::ConstantExpression(const ConstantExpression *cond,
305 const ConstantExpression *trueVal,
306 const ConstantExpression *falseVal)
Yifan Hongf24fa852016-09-23 11:03:15 -0700307 : mExpr(std::string("(") + cond->mExpr + "?" + trueVal->mExpr
308 + ":" + falseVal->mExpr + ")"),
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700309 mType(kConstExprTernary) {
Yifan Hongf24fa852016-09-23 11:03:15 -0700310
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700311 // note: for ?:, unlike arithmetic ops, integral promotion is not necessary.
312 mValueKind = usualArithmeticConversion(trueVal->mValueKind,
313 falseVal->mValueKind);
Yifan Hong57886972016-08-17 10:42:15 -0700314
315#define CASE_TERNARY(__type__)\
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700316 mValue = cond->mValue ? (static_cast<__type__>(trueVal->mValue)) : (static_cast<__type__>(falseVal->mValue)); return;
Yifan Hong57886972016-08-17 10:42:15 -0700317
Yifan Hongf24fa852016-09-23 11:03:15 -0700318 SWITCH_KIND(mValueKind, CASE_TERNARY, SHOULD_NOT_REACH(); return;)
Yifan Hong52165692016-08-12 18:06:40 -0700319}
320
Yifan Hongf24fa852016-09-23 11:03:15 -0700321ConstantExpression ConstantExpression::addOne() const {
322 ConstantExpression myOne = ConstantExpression::One(mValueKind);
323 return ConstantExpression(this, "+", &myOne).toLiteral();
Yifan Hong52165692016-08-12 18:06:40 -0700324}
Yifan Hong57886972016-08-17 10:42:15 -0700325
Yifan Hongf24fa852016-09-23 11:03:15 -0700326ConstantExpression &ConstantExpression::toLiteral() {
327 mExpr = value();
328 mType = kConstExprLiteral;
329 return *this;
330}
331
332const std::string &ConstantExpression::description() const {
333 return mExpr;
Yifan Hong57886972016-08-17 10:42:15 -0700334}
335
Yifan Hongfc610cd2016-09-22 13:34:45 -0700336std::string ConstantExpression::value() const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700337 return rawValue(mValueKind);
338}
339
340std::string ConstantExpression::cppValue() const {
341 return cppValue(mValueKind);
Yifan Hong52165692016-08-12 18:06:40 -0700342}
343
Yifan Hongfc610cd2016-09-22 13:34:45 -0700344std::string ConstantExpression::cppValue(ScalarType::Kind castKind) const {
Yifan Hongf24fa852016-09-23 11:03:15 -0700345 std::string literal(rawValue(castKind));
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700346 // this is a hack to translate
347 // enum x : int64_t { y = 1l << 63 };
348 // into
349 // enum class x : int64_t { y = (int64_t)-9223372036854775808ull };
350 // by adding the explicit cast.
351 // Because 9223372036854775808 is uint64_t, and
352 // -(uint64_t)9223372036854775808 == 9223372036854775808 could not
353 // be narrowed to int64_t.
354 if(castKind == SK(INT64) && (int64_t)mValue == INT64_MIN) {
355 std::string extra;
356 return strdup(("("
357 + ScalarType(SK(INT64)).getCppType(
358 android::Type::StorageMode_Stack,
359 &extra,
360 true /* specify namespaces */) // "int64_t"
361 + ")(" + literal + "ull)").c_str());
362 }
Yifan Hong57886972016-08-17 10:42:15 -0700363
Yifan Hong2bd3c1f2016-09-22 13:20:05 -0700364 // add suffix if necessary.
365 if(castKind == SK(UINT32) || castKind == SK(UINT64)) literal += "u";
366 if(castKind == SK(UINT64) || castKind == SK(INT64)) literal += "ll";
Yifan Hongfc610cd2016-09-22 13:34:45 -0700367 return literal;
Yifan Hong57886972016-08-17 10:42:15 -0700368}
369
Yifan Hongf24fa852016-09-23 11:03:15 -0700370std::string ConstantExpression::javaValue() const {
371 return javaValue(mValueKind);
Yifan Hong19ca75a2016-08-31 10:20:03 -0700372}
373
Yifan Hongf24fa852016-09-23 11:03:15 -0700374std::string ConstantExpression::javaValue(ScalarType::Kind castKind) const {
375 switch(castKind) {
376 case SK(UINT64): return rawValue(SK(INT64)) + "L";
377 case SK(INT64): return rawValue(SK(INT64)) + "L";
378 case SK(UINT32): return rawValue(SK(INT32));
379 case SK(UINT16): return rawValue(SK(INT16));
380 case SK(UINT8) : return rawValue(SK(INT8));
381 case SK(BOOL) :
382 return this->cast<bool>() ? strdup("true") : strdup("false");
383 default: break;
384 }
385 return rawValue(castKind);
386}
387
388std::string ConstantExpression::rawValue(ScalarType::Kind castKind) const {
Yifan Hong57886972016-08-17 10:42:15 -0700389
Yifan Hongfc610cd2016-09-22 13:34:45 -0700390#define CASE_STR(__type__) return std::to_string(this->cast<__type__>());
Yifan Hong57886972016-08-17 10:42:15 -0700391
Yifan Hongf24fa852016-09-23 11:03:15 -0700392 SWITCH_KIND(castKind, CASE_STR, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700393}
394
Yifan Hong19ca75a2016-08-31 10:20:03 -0700395template<typename T>
396T ConstantExpression::cast() const {
Yifan Hong57886972016-08-17 10:42:15 -0700397
Yifan Hong19ca75a2016-08-31 10:20:03 -0700398#define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(mValue));
Yifan Hong57886972016-08-17 10:42:15 -0700399
Yifan Hongf24fa852016-09-23 11:03:15 -0700400 SWITCH_KIND(mValueKind, CASE_CAST_T, SHOULD_NOT_REACH(); return 0; );
Yifan Hong57886972016-08-17 10:42:15 -0700401}
402
Yifan Honge77ca132016-09-27 10:49:05 -0700403size_t ConstantExpression::castSizeT() const {
404 return this->cast<size_t>();
405}
406
Yifan Hong57886972016-08-17 10:42:15 -0700407/*
408
409Evaluating expressions in HIDL language
410
411The following rules are mostly like that in:
412http://en.cppreference.com/w/cpp/language/operator_arithmetic
413http://en.cppreference.com/w/cpp/language/operator_logical
414http://en.cppreference.com/w/cpp/language/operator_comparison
415http://en.cppreference.com/w/cpp/language/operator_other
416
417The type of literal is the first type which the value
418can fit from the list of types depending on the suffix and bases.
419
420suffix decimal bases hexadecimal bases
421no suffix int32_t int32_t
422 int64_t uint32_t
423 int64_t
424 uint64_t
425
426u/U uint32_t (same as left)
427 uint64_t
428
429l/L int64_t int64_t
430
431ul/UL/uL/Ul uint64_t uint64_t
432
433
434Note: There are no negative integer literals.
435 -1 is the unary minus applied to 1.
436
437Unary arithmetic and bitwise operators (~ + -):
438 don't change the type of the argument.
439 (so -1u = -(1u) has type uint32_t)
440
441Binary arithmetic and bitwise operators (except shifts) (+ - * / % & | ^):
4421. Integral promotion is first applied on both sides.
4432. If both operands have the same type, no promotion is necessary.
4443. Usual arithmetic conversions.
445
446Integral promotion: if an operand is of a type with less than 32 bits,
447(including bool), it is promoted to int32_t.
448
449Usual arithmetic conversions:
4501. If operands are both signed or both unsigned, lesser conversion rank is
451 converted to greater conversion rank.
4522. Otherwise, if unsigned's rank >= signed's rank, -> unsigned's type
4533. Otherwise, if signed's type can hold all values in unsigned's type,
454 -> signed's type
4554. Otherwise, both converted to the unsigned counterpart of the signed operand's
456 type.
457rank: bool < int8_t < int16_t < int32_t < int64_t
458
459
460Shift operators (<< >>):
4611. Integral promotion is applied on both sides.
4622. For unsigned a, a << b discards bits that shifts out.
463 For signed non-negative a, a << b is legal if no bits shifts out, otherwise error.
464 For signed negative a, a << b gives error.
4653. For unsigned and signed non-negative a, a >> b discards bits that shifts out.
466 For signed negative a, a >> b discards bits that shifts out, and the signed
467 bit gets extended. ("arithmetic right shift")
4684. Shifting with negative number of bits is undefined. (Currently, the
469 parser will shift into the other direction. This behavior may change.)
4705. Shifting with number of bits exceeding the width of the type is undefined.
471 (Currently, 1 << 32 == 1. This behavior may change.)
472
473Logical operators (!, &&, ||):
4741. Convert first operand to bool. (true if non-zero, false otherwise)
4752. If short-circuited, return the result as type bool, value 1 or 0.
4763. Otherwise, convert second operand to bool, evaluate the result, and return
477 the result in the same fashion.
478
479Arithmetic comparison operators (< > <= >= == !=):
4801. Promote operands in the same way as binary arithmetic and bitwise operators.
481 (Integral promotion + Usual arithmetic conversions)
4822. Return type bool, value 0 or 1 the same way as logical operators.
483
484Ternary conditional operator (?:):
4851. Evaluate the conditional and evaluate the operands.
4862. Return type of expression is the type under usual arithmetic conversions on
487 the second and third operand. (No integral promotions necessary.)
488
489*/
490
Yifan Hong52165692016-08-12 18:06:40 -0700491} // namespace android
492