blob: 8b116ae4963f0b9b67a27f7230b0903dbf784573 [file] [log] [blame]
Anders Carlssonc7436af2008-07-03 04:20:39 +00001//===--- Expr.cpp - Expression Constant Evaluator -------------------------===//
2//
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"
16#include "clang/AST/Expr.h"
Anders Carlssoncad17b52008-07-08 05:13:58 +000017#include "clang/AST/STmtVisitor.h"
18#include "llvm/Support/Compiler.h"
Anders Carlssonc7436af2008-07-03 04:20:39 +000019
20using namespace clang;
21
Anders Carlssoncad17b52008-07-08 05:13:58 +000022#define USE_NEW_EVALUATOR 0
Anders Carlssonc7436af2008-07-03 04:20:39 +000023
24static bool CalcFakeICEVal(const Expr* Expr,
25 llvm::APSInt& Result,
26 ASTContext& Context) {
27 // Calculate the value of an expression that has a calculatable
28 // value, but isn't an ICE. Currently, this only supports
29 // a very narrow set of extensions, but it can be expanded if needed.
30 if (const ParenExpr *PE = dyn_cast<ParenExpr>(Expr))
31 return CalcFakeICEVal(PE->getSubExpr(), Result, Context);
32
33 if (const CastExpr *CE = dyn_cast<CastExpr>(Expr)) {
34 QualType CETy = CE->getType();
35 if ((CETy->isIntegralType() && !CETy->isBooleanType()) ||
36 CETy->isPointerType()) {
37 if (CalcFakeICEVal(CE->getSubExpr(), Result, Context)) {
38 Result.extOrTrunc(Context.getTypeSize(CETy));
39 // FIXME: This assumes pointers are signed.
40 Result.setIsSigned(CETy->isSignedIntegerType() ||
41 CETy->isPointerType());
42 return true;
43 }
44 }
45 }
46
47 if (Expr->getType()->isIntegralType())
48 return Expr->isIntegerConstantExpr(Result, Context);
49
50 return false;
51}
52
Anders Carlssoncad17b52008-07-08 05:13:58 +000053namespace {
54class VISIBILITY_HIDDEN IntExprEvaluator
55 : public StmtVisitor<IntExprEvaluator, APValue> {
56 ASTContext &Ctx;
57
58 IntExprEvaluator(ASTContext &ctx)
59 : Ctx(ctx) {}
60
61public:
62 static bool Evaluate(const Expr* E, APValue& Result, ASTContext &Ctx) {
63 Result = IntExprEvaluator(Ctx).Visit(const_cast<Expr*>(E));
64 return Result.isSInt();
65 }
66
67 //===--------------------------------------------------------------------===//
68 // Visitor Methods
69 //===--------------------------------------------------------------------===//
70 APValue VisitStmt(Stmt *S) {
71 // FIXME: Remove this when we support more expressions.
72 printf("Unhandled statement\n");
73 S->dump();
74 return APValue();
75 }
76
77 APValue VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }
78
79};
80}
81
Anders Carlssonc7436af2008-07-03 04:20:39 +000082bool Expr::tryEvaluate(APValue& Result, ASTContext &Ctx) const
83{
84 llvm::APSInt sInt(1);
85
Anders Carlssoncad17b52008-07-08 05:13:58 +000086#if USE_NEW_EVALUATOR
87 if (getType()->isIntegerType())
88 return IntExprEvaluator::Evaluate(this, Result, Ctx);
89 else
90 return false;
91
92#else
Anders Carlssonc7436af2008-07-03 04:20:39 +000093 if (CalcFakeICEVal(this, sInt, Ctx)) {
94 Result = APValue(sInt);
95 return true;
96 }
Anders Carlssoncad17b52008-07-08 05:13:58 +000097#endif
Anders Carlssonc7436af2008-07-03 04:20:39 +000098
99 return false;
100}