From: Daniel Dunbar Date: Wed, 18 Feb 2009 00:47:45 +0000 (+0000) Subject: isICE was evaluating ?: incorrectly with missing-gcc-LHS extension. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d6744ff04c1690a1485178d550d2fab84a0270b;p=clang isICE was evaluating ?: incorrectly with missing-gcc-LHS extension. Add assert to isICE that, on success, result must be the same as EvaluateAsInt()... this enforces a minimum level of sanity. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64865 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6579b595e5..cb1400c079 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -180,6 +180,9 @@ public: bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, SourceLocation *Loc = 0, bool isEvaluated = true) const; + bool isIntegerConstantExprInternal(llvm::APSInt &Result, ASTContext &Ctx, + SourceLocation *Loc = 0, + bool isEvaluated = true) const; bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const { llvm::APSInt X; return isIntegerConstantExpr(X, Ctx, Loc); @@ -190,7 +193,7 @@ public: /// EvalResult is a struct with detailed info about an evaluated expression. struct EvalResult { - /// Val - This is the scalar value the expression can be folded to. + /// Val - This is the value the expression can be folded to. APValue Val; /// HasSideEffects - Whether the evaluated expression has side effects. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c1117e8c88..0cd68ce3b8 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -871,6 +871,15 @@ bool Expr::isConstantInitializer(ASTContext &Ctx) const { /// cast+dereference. bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, SourceLocation *Loc, bool isEvaluated) const { + if (!isIntegerConstantExprInternal(Result, Ctx, Loc, isEvaluated)) + return false; + assert(Result == EvaluateAsInt(Ctx) && "Inconsistent Evaluate() result!"); + return true; +} + +bool Expr::isIntegerConstantExprInternal(llvm::APSInt &Result, ASTContext &Ctx, + SourceLocation *Loc, bool isEvaluated) const { + // Pretest for integral type; some parts of the code crash for types that // can't be sized. if (!getType()->isIntegralType()) { @@ -885,6 +894,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, return cast(this)->getSubExpr()-> isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated); case IntegerLiteralClass: + // NOTE: getValue() returns an APInt, we must set sign. Result = cast(this)->getValue(); Result.setIsUnsigned(getType()->isUnsignedIntegerType()); break; @@ -1107,7 +1117,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, // The result of the constant expr is the RHS. Result = RHS; - return true; + break; } assert(!Exp->isAssignmentOp() && "LHS can't be a constant expr!"); @@ -1208,9 +1218,12 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, } // Evaluate the false one first, discard the result. - if (FalseExp && !FalseExp->isIntegerConstantExpr(Result, Ctx, Loc, false)) + llvm::APSInt Tmp; + if (FalseExp && !FalseExp->isIntegerConstantExpr(Tmp, Ctx, Loc, false)) return false; - // Evalute the true one, capture the result. + // Evalute the true one, capture the result. Note that if TrueExp + // is False then this is an instant of the gcc missing LHS + // extension, and we will just reuse Result. if (TrueExp && !TrueExp->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated)) return false; diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c index 71f76228d1..7307aea791 100644 --- a/test/Sema/const-eval.c +++ b/test/Sema/const-eval.c @@ -29,3 +29,6 @@ void f() // FIXME: Turn into EVAL_EXPR test once we have more folding. _Complex float g16 = (1.0f + 1.0fi); + +// ?: in constant expressions. +int g17[(3?:1) - 2];