From 019f4e858e78587f2241ff1a76c747d7bcd7578c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 6 Oct 2008 05:28:25 +0000 Subject: [PATCH] Add a comment that describes tryEvaluate. Make tryEvaluate fold __builtin_constant_p properly, and add some scaffolding for FloatExprEvaluator to eventually handle huge_val and inf. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57152 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 4 ++++ lib/AST/Expr.cpp | 2 +- lib/AST/ExprConstant.cpp | 42 +++++++++++++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 3db866bcde..39a51bc1f4 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -119,6 +119,10 @@ public: /// isConstantExpr - Return true if this expression is a valid constant expr. bool isConstantExpr(ASTContext &Ctx, SourceLocation *Loc) const; + /// tryEvaluate - Return true if this is a constant which we can fold using + /// any crazy technique (that has nothing to do with language standards) that + /// we want to. If this function returns true, it returns the folded constant + /// in Result. bool tryEvaluate(APValue& Result, ASTContext &Ctx) const; /// hasGlobalStorage - Return true if this expression has static storage diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 562cf12c4d..bd1578fe20 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -171,7 +171,7 @@ bool CallExpr::isBuiltinClassifyType(llvm::APSInt &Result) const { if (isBuiltinCall() != Builtin::BI__builtin_classify_type) return false; - // The following enum mimics gcc's internal "typeclass.h" file. + // The following enum mimics the values returned by GCC. enum gcc_type_class { no_type_class = -1, void_type_class, integer_type_class, char_type_class, diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index e987617811..45724d318c 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -245,14 +245,25 @@ bool IntExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) { return Error(E->getLocStart(), diag::err_expr_not_constant); } - bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); - // __builtin_type_compatible_p is a constant. - if (E->isBuiltinClassifyType(Result)) - return true; - return Error(E->getLocStart(), diag::err_expr_not_constant); + switch (E->isBuiltinCall()) { + default: + return Error(E->getLocStart(), diag::err_expr_not_constant); + case Builtin::BI__builtin_classify_type: + // __builtin_type_compatible_p is a constant. Return its value. + E->isBuiltinClassifyType(Result); + return true; + + case Builtin::BI__builtin_constant_p: { + // __builtin_constant_p always has one operand: it returns true if that + // operand can be folded, false otherwise. + APValue Res; + Result = E->getArg(0)->tryEvaluate(Res, Info.Ctx); + return true; + } + } } bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { @@ -520,6 +531,7 @@ public: } bool VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); } + bool VisitCallExpr(const CallExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitFloatingLiteral(const FloatingLiteral *E); @@ -530,6 +542,22 @@ static bool EvaluateFloat(const Expr* E, APFloat& Result, EvalInfo &Info) { return FloatExprEvaluator(Info, Result).Visit(const_cast(E)); } +bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { + //Result.zextOrTrunc(getIntTypeSizeInBits(E->getType())); + + switch (E->isBuiltinCall()) { + case Builtin::BI__builtin_huge_val: + case Builtin::BI__builtin_huge_valf: + case Builtin::BI__builtin_huge_vall: + case Builtin::BI__builtin_inf: + case Builtin::BI__builtin_inff: + case Builtin::BI__builtin_infl: + // FIXME: Implement me. + default: return false; + } +} + + bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { // FIXME: Diagnostics? I really don't understand how the warnings // and errors are supposed to work. @@ -568,6 +596,10 @@ bool FloatExprEvaluator::VisitFloatingLiteral(const FloatingLiteral *E) { // Top level TryEvaluate. //===----------------------------------------------------------------------===// +/// tryEvaluate - Return true if this is a constant which we can fold using +/// any crazy technique (that has nothing to do with language standards) that +/// we want to. If this function returns true, it returns the folded constant +/// in Result. bool Expr::tryEvaluate(APValue &Result, ASTContext &Ctx) const { EvalInfo Info(Ctx); if (getType()->isIntegerType()) { -- 2.40.0