blob: 3fae5c90aaeca1fe4669b2a172dc4908b76d77af [file] [log] [blame]
Chris Lattnerb542afe2008-07-11 19:10:17 +00001//===--- ExprConstant.cpp - Expression Constant Evaluator -----------------===//
Anders Carlssonc44eec62008-07-03 04:20:39 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expr constant evaluator.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/APValue.h"
15#include "clang/AST/ASTContext.h"
Seo Sanghyeon0fe52e12008-07-08 07:23:12 +000016#include "clang/AST/StmtVisitor.h"
Chris Lattner54176fd2008-07-12 00:14:42 +000017#include "clang/Basic/Diagnostic.h"
Anders Carlsson06a36752008-07-08 05:49:43 +000018#include "clang/Basic/TargetInfo.h"
Anders Carlssonc754aa62008-07-08 05:13:58 +000019#include "llvm/Support/Compiler.h"
Anders Carlssonc44eec62008-07-03 04:20:39 +000020using namespace clang;
Chris Lattnerf5eeb052008-07-11 18:11:29 +000021using llvm::APSInt;
Anders Carlssonc44eec62008-07-03 04:20:39 +000022
Chris Lattner87eae5e2008-07-11 22:52:41 +000023/// EvalInfo - This is a private struct used by the evaluator to capture
24/// information about a subexpression as it is folded. It retains information
25/// about the AST context, but also maintains information about the folded
26/// expression.
27///
28/// If an expression could be evaluated, it is still possible it is not a C
29/// "integer constant expression" or constant expression. If not, this struct
30/// captures information about how and why not.
31///
32/// One bit of information passed *into* the request for constant folding
33/// indicates whether the subexpression is "evaluated" or not according to C
34/// rules. For example, the RHS of (0 && foo()) is not evaluated. We can
35/// evaluate the expression regardless of what the RHS is, but C only allows
36/// certain things in certain situations.
37struct EvalInfo {
38 ASTContext &Ctx;
39
40 /// isEvaluated - True if the subexpression is required to be evaluated, false
41 /// if it is short-circuited (according to C rules).
42 bool isEvaluated;
43
Chris Lattner54176fd2008-07-12 00:14:42 +000044 /// ICEDiag - If the expression is unfoldable, then ICEDiag contains the
45 /// error diagnostic indicating why it is not foldable and DiagLoc indicates a
46 /// caret position for the error. If it is foldable, but the expression is
47 /// not an integer constant expression, ICEDiag contains the extension
48 /// diagnostic to emit which describes why it isn't an integer constant
49 /// expression. If this expression *is* an integer-constant-expr, then
50 /// ICEDiag is zero.
Chris Lattner87eae5e2008-07-11 22:52:41 +000051 ///
Chris Lattner54176fd2008-07-12 00:14:42 +000052 /// The caller can choose to emit this diagnostic or not, depending on whether
53 /// they require an i-c-e or a constant or not. DiagLoc indicates the caret
54 /// position for the report.
55 ///
56 /// If ICEDiag is zero, then this expression is an i-c-e.
Chris Lattner87eae5e2008-07-11 22:52:41 +000057 unsigned ICEDiag;
58 SourceLocation DiagLoc;
59
60 EvalInfo(ASTContext &ctx) : Ctx(ctx), isEvaluated(true), ICEDiag(0) {}
61};
62
63
64static bool EvaluatePointer(const Expr *E, APValue &Result, EvalInfo &Info);
65static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info);
Chris Lattnerf5eeb052008-07-11 18:11:29 +000066
67
68//===----------------------------------------------------------------------===//
69// Pointer Evaluation
70//===----------------------------------------------------------------------===//
71
Anders Carlssonc754aa62008-07-08 05:13:58 +000072namespace {
Anders Carlsson2bad1682008-07-08 14:30:00 +000073class VISIBILITY_HIDDEN PointerExprEvaluator
74 : public StmtVisitor<PointerExprEvaluator, APValue> {
Chris Lattner87eae5e2008-07-11 22:52:41 +000075 EvalInfo &Info;
Anders Carlsson2bad1682008-07-08 14:30:00 +000076public:
Anders Carlsson2bad1682008-07-08 14:30:00 +000077
Chris Lattner87eae5e2008-07-11 22:52:41 +000078 PointerExprEvaluator(EvalInfo &info) : Info(info) {}
Chris Lattnerf5eeb052008-07-11 18:11:29 +000079
Anders Carlsson2bad1682008-07-08 14:30:00 +000080 APValue VisitStmt(Stmt *S) {
81 // FIXME: Remove this when we support more expressions.
Anders Carlsson650c92f2008-07-08 15:34:11 +000082 printf("Unhandled pointer statement\n");
Anders Carlsson2bad1682008-07-08 14:30:00 +000083 S->dump();
84 return APValue();
85 }
86
87 APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
88
Anders Carlsson650c92f2008-07-08 15:34:11 +000089 APValue VisitBinaryOperator(const BinaryOperator *E);
90 APValue VisitCastExpr(const CastExpr* E);
Anders Carlsson650c92f2008-07-08 15:34:11 +000091};
Chris Lattnerf5eeb052008-07-11 18:11:29 +000092} // end anonymous namespace
Anders Carlsson650c92f2008-07-08 15:34:11 +000093
Chris Lattner87eae5e2008-07-11 22:52:41 +000094static bool EvaluatePointer(const Expr* E, APValue& Result, EvalInfo &Info) {
Chris Lattnerf5eeb052008-07-11 18:11:29 +000095 if (!E->getType()->isPointerType())
96 return false;
Chris Lattner87eae5e2008-07-11 22:52:41 +000097 Result = PointerExprEvaluator(Info).Visit(const_cast<Expr*>(E));
Chris Lattnerf5eeb052008-07-11 18:11:29 +000098 return Result.isLValue();
99}
100
101APValue PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
102 if (E->getOpcode() != BinaryOperator::Add &&
103 E->getOpcode() != BinaryOperator::Sub)
104 return APValue();
105
106 const Expr *PExp = E->getLHS();
107 const Expr *IExp = E->getRHS();
108 if (IExp->getType()->isPointerType())
109 std::swap(PExp, IExp);
110
111 APValue ResultLValue;
Chris Lattner87eae5e2008-07-11 22:52:41 +0000112 if (!EvaluatePointer(PExp, ResultLValue, Info))
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000113 return APValue();
114
115 llvm::APSInt AdditionalOffset(32);
Chris Lattner87eae5e2008-07-11 22:52:41 +0000116 if (!EvaluateInteger(IExp, AdditionalOffset, Info))
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000117 return APValue();
118
119 uint64_t Offset = ResultLValue.getLValueOffset();
120 if (E->getOpcode() == BinaryOperator::Add)
121 Offset += AdditionalOffset.getZExtValue();
122 else
123 Offset -= AdditionalOffset.getZExtValue();
124
125 return APValue(ResultLValue.getLValueBase(), Offset);
126}
127
128
Chris Lattnerb542afe2008-07-11 19:10:17 +0000129APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000130 const Expr* SubExpr = E->getSubExpr();
131
132 // Check for pointer->pointer cast
133 if (SubExpr->getType()->isPointerType()) {
134 APValue Result;
Chris Lattner87eae5e2008-07-11 22:52:41 +0000135 if (EvaluatePointer(SubExpr, Result, Info))
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000136 return Result;
137 return APValue();
138 }
139
Eli Friedmand9f4bcd2008-07-27 05:46:18 +0000140 if (SubExpr->getType()->isIntegralType()) {
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000141 llvm::APSInt Result(32);
Chris Lattner87eae5e2008-07-11 22:52:41 +0000142 if (EvaluateInteger(SubExpr, Result, Info)) {
143 Result.extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000144 return APValue(0, Result.getZExtValue());
145 }
146 }
147
148 assert(0 && "Unhandled cast");
149 return APValue();
150}
151
152
153//===----------------------------------------------------------------------===//
154// Integer Evaluation
155//===----------------------------------------------------------------------===//
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000156
157namespace {
Anders Carlssonc754aa62008-07-08 05:13:58 +0000158class VISIBILITY_HIDDEN IntExprEvaluator
Chris Lattnerb542afe2008-07-11 19:10:17 +0000159 : public StmtVisitor<IntExprEvaluator, bool> {
Chris Lattner87eae5e2008-07-11 22:52:41 +0000160 EvalInfo &Info;
Chris Lattnerb542afe2008-07-11 19:10:17 +0000161 APSInt &Result;
Anders Carlssonc754aa62008-07-08 05:13:58 +0000162public:
Chris Lattner87eae5e2008-07-11 22:52:41 +0000163 IntExprEvaluator(EvalInfo &info, APSInt &result)
164 : Info(info), Result(result) {}
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000165
Chris Lattner7a767782008-07-11 19:24:49 +0000166 unsigned getIntTypeSizeInBits(QualType T) const {
Chris Lattner54176fd2008-07-12 00:14:42 +0000167 return (unsigned)Info.Ctx.getIntWidth(T);
168 }
169
170 bool Extension(SourceLocation L, diag::kind D) {
171 Info.DiagLoc = L;
172 Info.ICEDiag = D;
173 return true; // still a constant.
174 }
175
176 bool Error(SourceLocation L, diag::kind D) {
177 // If this is in an unevaluated portion of the subexpression, ignore the
178 // error.
179 if (!Info.isEvaluated)
180 return true;
181
182 Info.DiagLoc = L;
183 Info.ICEDiag = D;
184 return false;
Chris Lattner7a767782008-07-11 19:24:49 +0000185 }
186
Anders Carlssonc754aa62008-07-08 05:13:58 +0000187 //===--------------------------------------------------------------------===//
188 // Visitor Methods
189 //===--------------------------------------------------------------------===//
Chris Lattner7a767782008-07-11 19:24:49 +0000190
Chris Lattnerb542afe2008-07-11 19:10:17 +0000191 bool VisitStmt(Stmt *S) {
Chris Lattner54176fd2008-07-12 00:14:42 +0000192 return Error(S->getLocStart(), diag::err_expr_not_constant);
Anders Carlssonc754aa62008-07-08 05:13:58 +0000193 }
194
Chris Lattnerb542afe2008-07-11 19:10:17 +0000195 bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
Anders Carlssonc754aa62008-07-08 05:13:58 +0000196
Chris Lattner4c4867e2008-07-12 00:38:25 +0000197 bool VisitIntegerLiteral(const IntegerLiteral *E) {
198 Result = E->getValue();
199 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
200 return true;
201 }
202 bool VisitCharacterLiteral(const CharacterLiteral *E) {
203 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
204 Result = E->getValue();
205 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
206 return true;
207 }
208 bool VisitTypesCompatibleExpr(const TypesCompatibleExpr *E) {
209 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
210 Result = Info.Ctx.typesAreCompatible(E->getArgType1(), E->getArgType2());
211 return true;
212 }
213 bool VisitDeclRefExpr(const DeclRefExpr *E);
214 bool VisitCallExpr(const CallExpr *E);
Chris Lattnerb542afe2008-07-11 19:10:17 +0000215 bool VisitBinaryOperator(const BinaryOperator *E);
216 bool VisitUnaryOperator(const UnaryOperator *E);
Anders Carlsson06a36752008-07-08 05:49:43 +0000217
Chris Lattner732b2232008-07-12 01:15:53 +0000218 bool VisitCastExpr(CastExpr* E) {
219 return HandleCast(E->getLParenLoc(), E->getSubExpr(), E->getType());
Anders Carlsson650c92f2008-07-08 15:34:11 +0000220 }
Chris Lattner732b2232008-07-12 01:15:53 +0000221 bool VisitImplicitCastExpr(ImplicitCastExpr* E) {
222 return HandleCast(E->getLocStart(), E->getSubExpr(), E->getType());
Anders Carlsson650c92f2008-07-08 15:34:11 +0000223 }
Chris Lattnerfcee0012008-07-11 21:24:13 +0000224 bool VisitSizeOfAlignOfTypeExpr(const SizeOfAlignOfTypeExpr *E) {
Chris Lattner54176fd2008-07-12 00:14:42 +0000225 return EvaluateSizeAlignOf(E->isSizeOf(), E->getArgumentType(),
226 E->getType());
Chris Lattnerfcee0012008-07-11 21:24:13 +0000227 }
Chris Lattner4c4867e2008-07-12 00:38:25 +0000228
Chris Lattnerfcee0012008-07-11 21:24:13 +0000229private:
Chris Lattner732b2232008-07-12 01:15:53 +0000230 bool HandleCast(SourceLocation CastLoc, Expr *SubExpr, QualType DestType);
Chris Lattnerfcee0012008-07-11 21:24:13 +0000231 bool EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy, QualType DstTy);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000232};
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000233} // end anonymous namespace
Anders Carlsson650c92f2008-07-08 15:34:11 +0000234
Chris Lattner87eae5e2008-07-11 22:52:41 +0000235static bool EvaluateInteger(const Expr* E, APSInt &Result, EvalInfo &Info) {
236 return IntExprEvaluator(Info, Result).Visit(const_cast<Expr*>(E));
Anders Carlsson650c92f2008-07-08 15:34:11 +0000237}
Anders Carlsson650c92f2008-07-08 15:34:11 +0000238
Chris Lattner4c4867e2008-07-12 00:38:25 +0000239bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
240 // Enums are integer constant exprs.
241 if (const EnumConstantDecl *D = dyn_cast<EnumConstantDecl>(E->getDecl())) {
242 Result = D->getInitVal();
243 return true;
244 }
245
246 // Otherwise, random variable references are not constants.
247 return Error(E->getLocStart(), diag::err_expr_not_constant);
248}
249
250
251bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
252 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
253 // __builtin_type_compatible_p is a constant.
254 if (E->isBuiltinClassifyType(Result))
255 return true;
256
257 return Error(E->getLocStart(), diag::err_expr_not_constant);
258}
Anders Carlsson650c92f2008-07-08 15:34:11 +0000259
Chris Lattnerb542afe2008-07-11 19:10:17 +0000260bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000261 // The LHS of a constant expr is always evaluated and needed.
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000262 llvm::APSInt RHS(32);
Chris Lattner54176fd2008-07-12 00:14:42 +0000263 if (!Visit(E->getLHS()))
264 return false; // error in subexpression.
265
266 bool OldEval = Info.isEvaluated;
267
268 // The short-circuiting &&/|| operators don't necessarily evaluate their
269 // RHS. Make sure to pass isEvaluated down correctly.
270 if ((E->getOpcode() == BinaryOperator::LAnd && Result == 0) ||
271 (E->getOpcode() == BinaryOperator::LOr && Result != 0))
272 Info.isEvaluated = false;
Eli Friedmand9f4bcd2008-07-27 05:46:18 +0000273
274 // FIXME: Handle pointer subtraction
275
276 // FIXME Maybe we want to succeed even where we can't evaluate the
277 // right side of LAnd/LOr?
278 // For example, see http://llvm.org/bugs/show_bug.cgi?id=2525
Chris Lattner54176fd2008-07-12 00:14:42 +0000279 if (!EvaluateInteger(E->getRHS(), RHS, Info))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000280 return false;
Chris Lattner54176fd2008-07-12 00:14:42 +0000281 Info.isEvaluated = OldEval;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000282
283 switch (E->getOpcode()) {
Chris Lattner54176fd2008-07-12 00:14:42 +0000284 default: return Error(E->getOperatorLoc(), diag::err_expr_not_constant);
285 case BinaryOperator::Mul: Result *= RHS; return true;
286 case BinaryOperator::Add: Result += RHS; return true;
287 case BinaryOperator::Sub: Result -= RHS; return true;
288 case BinaryOperator::And: Result &= RHS; return true;
289 case BinaryOperator::Xor: Result ^= RHS; return true;
290 case BinaryOperator::Or: Result |= RHS; return true;
Chris Lattner75a48812008-07-11 22:15:16 +0000291 case BinaryOperator::Div:
Chris Lattner54176fd2008-07-12 00:14:42 +0000292 if (RHS == 0)
293 return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
Chris Lattner75a48812008-07-11 22:15:16 +0000294 Result /= RHS;
Chris Lattner54176fd2008-07-12 00:14:42 +0000295 return true;
Chris Lattner75a48812008-07-11 22:15:16 +0000296 case BinaryOperator::Rem:
Chris Lattner54176fd2008-07-12 00:14:42 +0000297 if (RHS == 0)
298 return Error(E->getOperatorLoc(), diag::err_expr_divide_by_zero);
Chris Lattner75a48812008-07-11 22:15:16 +0000299 Result %= RHS;
Chris Lattner54176fd2008-07-12 00:14:42 +0000300 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000301 case BinaryOperator::Shl:
Chris Lattner54176fd2008-07-12 00:14:42 +0000302 // FIXME: Warn about out of range shift amounts!
Chris Lattnerb542afe2008-07-11 19:10:17 +0000303 Result <<= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000304 break;
305 case BinaryOperator::Shr:
Chris Lattnerb542afe2008-07-11 19:10:17 +0000306 Result >>= (unsigned)RHS.getLimitedValue(Result.getBitWidth()-1);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000307 break;
Chris Lattnerb542afe2008-07-11 19:10:17 +0000308
Chris Lattnerac7cb602008-07-11 19:29:32 +0000309 case BinaryOperator::LT:
310 Result = Result < RHS;
311 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
312 break;
313 case BinaryOperator::GT:
314 Result = Result > RHS;
315 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
316 break;
317 case BinaryOperator::LE:
318 Result = Result <= RHS;
319 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
320 break;
321 case BinaryOperator::GE:
322 Result = Result >= RHS;
323 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
324 break;
325 case BinaryOperator::EQ:
326 Result = Result == RHS;
327 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
328 break;
329 case BinaryOperator::NE:
330 Result = Result != RHS;
331 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
332 break;
Chris Lattner54176fd2008-07-12 00:14:42 +0000333 case BinaryOperator::LAnd:
334 Result = Result != 0 && RHS != 0;
335 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
336 break;
337 case BinaryOperator::LOr:
338 Result = Result != 0 || RHS != 0;
339 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
340 break;
341
Anders Carlsson06a36752008-07-08 05:49:43 +0000342
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000343 case BinaryOperator::Comma:
Chris Lattner54176fd2008-07-12 00:14:42 +0000344 // Result of the comma is just the result of the RHS.
345 Result = RHS;
346
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000347 // C99 6.6p3: "shall not contain assignment, ..., or comma operators,
348 // *except* when they are contained within a subexpression that is not
349 // evaluated". Note that Assignment can never happen due to constraints
350 // on the LHS subexpr, so we don't need to check it here.
Chris Lattner54176fd2008-07-12 00:14:42 +0000351 if (!Info.isEvaluated)
352 return true;
353
354 // If the value is evaluated, we can accept it as an extension.
355 return Extension(E->getOperatorLoc(), diag::ext_comma_in_constant_expr);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000356 }
357
358 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
Chris Lattnerb542afe2008-07-11 19:10:17 +0000359 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000360}
361
Chris Lattnerfcee0012008-07-11 21:24:13 +0000362/// EvaluateSizeAlignOf - Evaluate sizeof(SrcTy) or alignof(SrcTy) with a result
363/// as a DstTy type.
364bool IntExprEvaluator::EvaluateSizeAlignOf(bool isSizeOf, QualType SrcTy,
365 QualType DstTy) {
366 // Return the result in the right width.
367 Result.zextOrTrunc(getIntTypeSizeInBits(DstTy));
368 Result.setIsUnsigned(DstTy->isUnsignedIntegerType());
369
370 // sizeof(void) and __alignof__(void) = 1 as a gcc extension.
371 if (SrcTy->isVoidType())
372 Result = 1;
373
374 // sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
375 if (!SrcTy->isConstantSizeType()) {
376 // FIXME: Should we attempt to evaluate this?
377 return false;
378 }
379
380 // GCC extension: sizeof(function) = 1.
381 if (SrcTy->isFunctionType()) {
382 // FIXME: AlignOf shouldn't be unconditionally 4!
383 Result = isSizeOf ? 1 : 4;
384 return true;
385 }
386
387 // Get information about the size or align.
Chris Lattner87eae5e2008-07-11 22:52:41 +0000388 unsigned CharSize = Info.Ctx.Target.getCharWidth();
Chris Lattnerfcee0012008-07-11 21:24:13 +0000389 if (isSizeOf)
390 Result = getIntTypeSizeInBits(SrcTy) / CharSize;
391 else
Chris Lattner87eae5e2008-07-11 22:52:41 +0000392 Result = Info.Ctx.getTypeAlign(SrcTy) / CharSize;
Chris Lattnerfcee0012008-07-11 21:24:13 +0000393 return true;
394}
395
Chris Lattnerb542afe2008-07-11 19:10:17 +0000396bool IntExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
Chris Lattner4c4867e2008-07-12 00:38:25 +0000397 // Special case unary operators that do not need their subexpression
398 // evaluated. offsetof/sizeof/alignof are all special.
Chris Lattner75a48812008-07-11 22:15:16 +0000399 if (E->isOffsetOfOp()) {
Chris Lattner4c4867e2008-07-12 00:38:25 +0000400 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
Chris Lattner87eae5e2008-07-11 22:52:41 +0000401 Result = E->evaluateOffsetOf(Info.Ctx);
Chris Lattner75a48812008-07-11 22:15:16 +0000402 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
403 return true;
404 }
405
406 if (E->isSizeOfAlignOfOp())
Chris Lattnerfcee0012008-07-11 21:24:13 +0000407 return EvaluateSizeAlignOf(E->getOpcode() == UnaryOperator::SizeOf,
408 E->getSubExpr()->getType(), E->getType());
Chris Lattner75a48812008-07-11 22:15:16 +0000409
Chris Lattner87eae5e2008-07-11 22:52:41 +0000410 // Get the operand value into 'Result'.
411 if (!Visit(E->getSubExpr()))
Chris Lattner75a48812008-07-11 22:15:16 +0000412 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000413
Chris Lattner75a48812008-07-11 22:15:16 +0000414 switch (E->getOpcode()) {
Chris Lattner4c4867e2008-07-12 00:38:25 +0000415 default:
Chris Lattner75a48812008-07-11 22:15:16 +0000416 // Address, indirect, pre/post inc/dec, etc are not valid constant exprs.
417 // See C99 6.6p3.
Chris Lattner4c4867e2008-07-12 00:38:25 +0000418 return Error(E->getOperatorLoc(), diag::err_expr_not_constant);
Chris Lattner75a48812008-07-11 22:15:16 +0000419 case UnaryOperator::LNot: {
420 bool Val = Result == 0;
421 Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
422 Result = Val;
423 break;
424 }
425 case UnaryOperator::Extension:
Chris Lattner4c4867e2008-07-12 00:38:25 +0000426 // FIXME: Should extension allow i-c-e extension expressions in its scope?
427 // If so, we could clear the diagnostic ID.
Chris Lattner75a48812008-07-11 22:15:16 +0000428 case UnaryOperator::Plus:
Chris Lattner4c4867e2008-07-12 00:38:25 +0000429 // The result is always just the subexpr.
Chris Lattner75a48812008-07-11 22:15:16 +0000430 break;
431 case UnaryOperator::Minus:
432 Result = -Result;
433 break;
434 case UnaryOperator::Not:
435 Result = ~Result;
436 break;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000437 }
438
439 Result.setIsUnsigned(E->getType()->isUnsignedIntegerType());
Chris Lattnerb542afe2008-07-11 19:10:17 +0000440 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000441}
442
Chris Lattner732b2232008-07-12 01:15:53 +0000443/// HandleCast - This is used to evaluate implicit or explicit casts where the
444/// result type is integer.
445bool IntExprEvaluator::HandleCast(SourceLocation CastLoc,
446 Expr *SubExpr, QualType DestType) {
Chris Lattner7a767782008-07-11 19:24:49 +0000447 unsigned DestWidth = getIntTypeSizeInBits(DestType);
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000448
449 // Handle simple integer->integer casts.
450 if (SubExpr->getType()->isIntegerType()) {
Chris Lattner732b2232008-07-12 01:15:53 +0000451 if (!Visit(SubExpr))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000452 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000453
454 // Figure out if this is a truncate, extend or noop cast.
455 // If the input is signed, do a sign extend, noop, or truncate.
456 if (DestType->isBooleanType()) {
457 // Conversion to bool compares against zero.
458 Result = Result != 0;
459 Result.zextOrTrunc(DestWidth);
Chris Lattner7a767782008-07-11 19:24:49 +0000460 } else
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000461 Result.extOrTrunc(DestWidth);
Chris Lattner732b2232008-07-12 01:15:53 +0000462 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
463 return true;
464 }
465
466 // FIXME: Clean this up!
467 if (SubExpr->getType()->isPointerType()) {
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000468 APValue LV;
Chris Lattner87eae5e2008-07-11 22:52:41 +0000469 if (!EvaluatePointer(SubExpr, LV, Info))
Chris Lattnerb542afe2008-07-11 19:10:17 +0000470 return false;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000471 if (LV.getLValueBase())
Chris Lattnerb542afe2008-07-11 19:10:17 +0000472 return false;
Anders Carlsson06a36752008-07-08 05:49:43 +0000473
Anders Carlsson559e56b2008-07-08 16:49:00 +0000474 Result.extOrTrunc(DestWidth);
475 Result = LV.getLValueOffset();
Chris Lattner732b2232008-07-12 01:15:53 +0000476 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
477 return true;
Anders Carlsson2bad1682008-07-08 14:30:00 +0000478 }
479
Chris Lattner732b2232008-07-12 01:15:53 +0000480 if (!SubExpr->getType()->isRealFloatingType())
481 return Error(CastLoc, diag::err_expr_not_constant);
482
483 // FIXME: Generalize floating point constant folding! For now we just permit
484 // which is allowed by integer constant expressions.
485
486 // Allow floating constants that are the immediate operands of casts or that
487 // are parenthesized.
488 const Expr *Operand = SubExpr;
489 while (const ParenExpr *PE = dyn_cast<ParenExpr>(Operand))
490 Operand = PE->getSubExpr();
491
492 // If this isn't a floating literal, we can't handle it.
493 const FloatingLiteral *FL = dyn_cast<FloatingLiteral>(Operand);
494 if (!FL)
495 return Error(CastLoc, diag::err_expr_not_constant);
496
497 // If the destination is boolean, compare against zero.
498 if (DestType->isBooleanType()) {
499 Result = !FL->getValue().isZero();
500 Result.zextOrTrunc(DestWidth);
501 Result.setIsUnsigned(DestType->isUnsignedIntegerType());
502 return true;
503 }
504
505 // Determine whether we are converting to unsigned or signed.
506 bool DestSigned = DestType->isSignedIntegerType();
507
508 // FIXME: Warning for overflow.
509 uint64_t Space[4];
510 (void)FL->getValue().convertToInteger(Space, DestWidth, DestSigned,
511 llvm::APFloat::rmTowardZero);
512 Result = llvm::APInt(DestWidth, 4, Space);
513 Result.setIsUnsigned(!DestSigned);
Chris Lattnerb542afe2008-07-11 19:10:17 +0000514 return true;
Anders Carlssona25ae3d2008-07-08 14:35:21 +0000515}
Anders Carlsson2bad1682008-07-08 14:30:00 +0000516
Chris Lattnerf5eeb052008-07-11 18:11:29 +0000517//===----------------------------------------------------------------------===//
518// Top level TryEvaluate.
519//===----------------------------------------------------------------------===//
520
Chris Lattnerb542afe2008-07-11 19:10:17 +0000521bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const {
Chris Lattnercf0f51d2008-07-11 19:19:21 +0000522 llvm::APSInt sInt(32);
Anders Carlsson165a70f2008-08-10 17:03:01 +0000523
Chris Lattner87eae5e2008-07-11 22:52:41 +0000524 EvalInfo Info(Ctx);
Anders Carlsson06a36752008-07-08 05:49:43 +0000525 if (getType()->isIntegerType()) {
Chris Lattner87eae5e2008-07-11 22:52:41 +0000526 if (EvaluateInteger(this, sInt, Info)) {
Anders Carlsson06a36752008-07-08 05:49:43 +0000527 Result = APValue(sInt);
528 return true;
529 }
530 } else
Anders Carlssonc754aa62008-07-08 05:13:58 +0000531 return false;
Anders Carlsson165a70f2008-08-10 17:03:01 +0000532
Anders Carlssonc44eec62008-07-03 04:20:39 +0000533 return false;
534}