[cfe-commits] r147318 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/ExprConstant.cpp lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenFunction.h lib/Sema/SemaChecking.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaType.cpp lib/StaticAnalyzer/Core/ExprEngineC.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Wed Dec 28 11:48:30 PST 2011
Author: rsmith
Date: Wed Dec 28 13:48:30 2011
New Revision: 147318
URL: http://llvm.org/viewvc/llvm-project?rev=147318&view=rev
Log:
Small refactoring and simplification of constant evaluation and some of its
clients. No functionality change.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/CodeGen/CGBuiltin.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Dec 28 13:48:30 2011
@@ -471,10 +471,12 @@
/// side-effects.
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const;
+ enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects };
+
/// EvaluateAsInt - Return true if this is a constant which we can fold and
- /// convert to an integer without side-effects, using any crazy technique that
- /// we want to.
- bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx) const;
+ /// convert to an integer, using any crazy technique that we want to.
+ bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// isEvaluatable - Call EvaluateAsRValue to see if this expression can be
/// constant folded without side-effects, but discard the result.
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Dec 28 13:48:30 2011
@@ -3658,6 +3658,61 @@
return -1;
}
+/// EvaluateBuiltinConstantPForLValue - Determine the result of
+/// __builtin_constant_p when applied to the given lvalue.
+///
+/// An lvalue is only "constant" if it is a pointer or reference to the first
+/// character of a string literal.
+template<typename LValue>
+static bool EvaluateBuiltinConstantPForLValue(const LValue &LV) {
+ const Expr *E = LV.getLValueBase().dyn_cast<const Expr*>();
+ return E && isa<StringLiteral>(E) && LV.getLValueOffset().isZero();
+}
+
+/// EvaluateBuiltinConstantP - Evaluate __builtin_constant_p as similarly to
+/// GCC as we can manage.
+static bool EvaluateBuiltinConstantP(ASTContext &Ctx, const Expr *Arg) {
+ QualType ArgType = Arg->getType();
+
+ // __builtin_constant_p always has one operand. The rules which gcc follows
+ // are not precisely documented, but are as follows:
+ //
+ // - If the operand is of integral, floating, complex or enumeration type,
+ // and can be folded to a known value of that type, it returns 1.
+ // - If the operand and can be folded to a pointer to the first character
+ // of a string literal (or such a pointer cast to an integral type), it
+ // returns 1.
+ //
+ // Otherwise, it returns 0.
+ //
+ // FIXME: GCC also intends to return 1 for literals of aggregate types, but
+ // its support for this does not currently work.
+ if (ArgType->isIntegralOrEnumerationType()) {
+ Expr::EvalResult Result;
+ if (!Arg->EvaluateAsRValue(Result, Ctx) || Result.HasSideEffects)
+ return false;
+
+ APValue &V = Result.Val;
+ if (V.getKind() == APValue::Int)
+ return true;
+
+ return EvaluateBuiltinConstantPForLValue(V);
+ } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) {
+ return Arg->isEvaluatable(Ctx);
+ } else if (ArgType->isPointerType() || Arg->isGLValue()) {
+ LValue LV;
+ Expr::EvalStatus Status;
+ EvalInfo Info(Ctx, Status);
+ if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, Info)
+ : EvaluatePointer(Arg, LV, Info)) &&
+ !Status.HasSideEffects)
+ return EvaluateBuiltinConstantPForLValue(LV);
+ }
+
+ // Anything else isn't considered to be sufficiently constant.
+ return false;
+}
+
/// Retrieves the "underlying object type" of the given expression,
/// as used by __builtin_object_size.
QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
@@ -3722,53 +3777,9 @@
case Builtin::BI__builtin_classify_type:
return Success(EvaluateBuiltinClassifyType(E), E);
- case Builtin::BI__builtin_constant_p: {
- const Expr *Arg = E->getArg(0);
- QualType ArgType = Arg->getType();
- // __builtin_constant_p always has one operand. The rules which gcc follows
- // are not precisely documented, but are as follows:
- //
- // - If the operand is of integral, floating, complex or enumeration type,
- // and can be folded to a known value of that type, it returns 1.
- // - If the operand and can be folded to a pointer to the first character
- // of a string literal (or such a pointer cast to an integral type), it
- // returns 1.
- //
- // Otherwise, it returns 0.
- //
- // FIXME: GCC also intends to return 1 for literals of aggregate types, but
- // its support for this does not currently work.
- int IsConstant = 0;
- if (ArgType->isIntegralOrEnumerationType()) {
- // Note, a pointer cast to an integral type is only a constant if it is
- // a pointer to the first character of a string literal.
- Expr::EvalResult Result;
- if (Arg->EvaluateAsRValue(Result, Info.Ctx) && !Result.HasSideEffects) {
- APValue &V = Result.Val;
- if (V.getKind() == APValue::LValue) {
- if (const Expr *E = V.getLValueBase().dyn_cast<const Expr*>())
- IsConstant = isa<StringLiteral>(E) && V.getLValueOffset().isZero();
- } else {
- IsConstant = 1;
- }
- }
- } else if (ArgType->isFloatingType() || ArgType->isAnyComplexType()) {
- IsConstant = Arg->isEvaluatable(Info.Ctx);
- } else if (ArgType->isPointerType() || Arg->isGLValue()) {
- LValue LV;
- // Use a separate EvalInfo: ignore constexpr parameter and 'this' bindings
- // during the check.
- Expr::EvalStatus Status;
- EvalInfo SubInfo(Info.Ctx, Status);
- if ((Arg->isGLValue() ? EvaluateLValue(Arg, LV, SubInfo)
- : EvaluatePointer(Arg, LV, SubInfo)) &&
- !Status.HasSideEffects)
- if (const Expr *E = LV.getLValueBase().dyn_cast<const Expr*>())
- IsConstant = isa<StringLiteral>(E) && LV.getLValueOffset().isZero();
- }
+ case Builtin::BI__builtin_constant_p:
+ return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E);
- return Success(IsConstant, E);
- }
case Builtin::BI__builtin_eh_return_data_regno: {
int Operand = E->getArg(0)->EvaluateKnownConstInt(Info.Ctx).getZExtValue();
Operand = Info.Ctx.getTargetInfo().getEHDataRegisterNumber(Operand);
@@ -5240,10 +5251,14 @@
Result);
}
-bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx) const {
+bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects) const {
+ if (!getType()->isIntegralOrEnumerationType())
+ return false;
+
EvalResult ExprResult;
- if (!EvaluateAsRValue(ExprResult, Ctx) || ExprResult.HasSideEffects ||
- !ExprResult.Val.isInt())
+ if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() ||
+ (!AllowSideEffects && ExprResult.HasSideEffects))
return false;
Result = ExprResult.Val.getInt();
@@ -5680,14 +5695,8 @@
// extension. See GCC PR38377 for discussion.
if (const CallExpr *CallCE
= dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts()))
- if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p) {
- Expr::EvalResult EVResult;
- if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects ||
- !EVResult.Val.isInt()) {
- return ICEDiag(2, E->getLocStart());
- }
- return NoDiag();
- }
+ if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p)
+ return CheckEvalInICE(E, Ctx);
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
if (CondResult.Val == 2)
return CondResult;
Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Dec 28 13:48:30 2011
@@ -16,7 +16,6 @@
#include "CodeGenModule.h"
#include "CGObjCRuntime.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/TargetBuiltins.h"
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed Dec 28 13:48:30 2011
@@ -1107,18 +1107,18 @@
CollectCXXBases(CXXDecl, Unit, EltTys, FwdDecl);
CollectVTableInfo(CXXDecl, Unit, EltTys);
}
-
+
// Collect static variables with initializers.
for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
I != E; ++I)
if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
- if (const Expr *Init = V->getInit()) {
- Expr::EvalResult Result;
- if (Init->EvaluateAsRValue(Result, CGM.getContext()) &&
- Result.Val.isInt()) {
- llvm::ConstantInt *CI
- = llvm::ConstantInt::get(CGM.getLLVMContext(), Result.Val.getInt());
-
+ llvm::SmallVector<PartialDiagnosticAt, 8> Notes;
+ if (V->getInit() && V->evaluateValue(Notes)) {
+ APValue *Value = V->getEvaluatedValue();
+ if (Value && Value->isInt()) {
+ llvm::ConstantInt *CI
+ = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
+
// Create the descriptor for static variable.
llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
StringRef VName = V->getName();
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Dec 28 13:48:30 2011
@@ -801,13 +801,13 @@
return Builder.CreateShuffleVector(V1, V2, SV, "shuffle");
}
Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
- Expr::EvalResult Result;
- if (E->EvaluateAsRValue(Result, CGF.getContext()) && Result.Val.isInt()) {
+ llvm::APSInt Value;
+ if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) {
if (E->isArrow())
CGF.EmitScalarExpr(E->getBase());
else
EmitLValue(E->getBase());
- return Builder.getInt(Result.Val.getInt());
+ return Builder.getInt(Value);
}
// Emit debug info for aggregate now, if it was delayed to reduce
@@ -1466,9 +1466,9 @@
Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
// Try folding the offsetof to a constant.
- Expr::EvalResult EvalResult;
- if (E->EvaluateAsRValue(EvalResult, CGF.getContext()))
- return Builder.getInt(EvalResult.Val.getInt());
+ llvm::APSInt Value;
+ if (E->EvaluateAsInt(Value, CGF.getContext()))
+ return Builder.getInt(Value);
// Loop over the components of the offsetof to compute the value.
unsigned n = E->getNumComponents();
@@ -1589,9 +1589,7 @@
// If this isn't sizeof(vla), the result must be constant; use the constant
// folding logic so we don't have to duplicate it here.
- Expr::EvalResult Result;
- E->EvaluateAsRValue(Result, CGF.getContext());
- return Builder.getInt(Result.Val.getInt());
+ return Builder.getInt(E->EvaluateKnownConstInt(CGF.getContext()));
}
Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) {
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Dec 28 13:48:30 2011
@@ -18,7 +18,6 @@
#include "CGDebugInfo.h"
#include "CGException.h"
#include "clang/Basic/TargetInfo.h"
-#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
@@ -520,15 +519,14 @@
ConstantFoldsToSimpleInteger(const Expr *Cond, llvm::APInt &ResultInt) {
// FIXME: Rename and handle conversion of other evaluatable things
// to bool.
- Expr::EvalResult Result;
- if (!Cond->EvaluateAsRValue(Result, getContext()) || !Result.Val.isInt() ||
- Result.HasSideEffects)
+ llvm::APSInt Int;
+ if (!Cond->EvaluateAsInt(Int, getContext()))
return false; // Not foldable, not integer or not fully evaluatable.
-
+
if (CodeGenFunction::ContainsLabel(Cond))
return false; // Contains a label.
-
- ResultInt = Result.Val.getInt();
+
+ ResultInt = Int;
return true;
}
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Wed Dec 28 13:48:30 2011
@@ -43,7 +43,6 @@
}
namespace clang {
- class APValue;
class ASTContext;
class BlockDecl;
class CXXDestructorDecl;
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Dec 28 13:48:30 2011
@@ -3662,12 +3662,10 @@
Expr *OriginalInit = Init->IgnoreParenImpCasts();
- Expr::EvalResult InitValue;
- if (!OriginalInit->EvaluateAsRValue(InitValue, S.Context) ||
- !InitValue.Val.isInt())
+ llvm::APSInt Value;
+ if (!OriginalInit->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects))
return false;
- const llvm::APSInt &Value = InitValue.Val.getInt();
unsigned OriginalWidth = Value.getBitWidth();
unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Dec 28 13:48:30 2011
@@ -16,7 +16,6 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
-#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclObjC.h"
@@ -664,20 +663,15 @@
// condition is constant.
llvm::APSInt ConstantCondValue;
bool HasConstantCond = false;
- bool ShouldCheckConstantCond = false;
if (!HasDependentValue && !TheDefaultStmt) {
- Expr::EvalResult Result;
HasConstantCond
- = CondExprBeforePromotion->EvaluateAsRValue(Result, Context);
- if (HasConstantCond) {
- assert(Result.Val.isInt() && "switch condition evaluated to non-int");
- ConstantCondValue = Result.Val.getInt();
- ShouldCheckConstantCond = true;
-
- assert(ConstantCondValue.getBitWidth() == CondWidth &&
- ConstantCondValue.isSigned() == CondIsSigned);
- }
+ = CondExprBeforePromotion->EvaluateAsInt(ConstantCondValue, Context,
+ Expr::SE_AllowSideEffects);
+ assert(!HasConstantCond ||
+ (ConstantCondValue.getBitWidth() == CondWidth &&
+ ConstantCondValue.isSigned() == CondIsSigned));
}
+ bool ShouldCheckConstantCond = HasConstantCond;
// Sort all the scalar case values so we can easily detect duplicates.
std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Wed Dec 28 13:48:30 2011
@@ -1180,13 +1180,9 @@
// If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
// value as an extension.
- Expr::EvalResult Result;
- if (S.LangOpts.GNUMode && ArraySize->EvaluateAsRValue(Result, S.Context)) {
- if (!Result.hasSideEffects() && Result.Val.isInt()) {
- SizeVal = Result.Val.getInt();
- S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
- return false;
- }
+ if (S.LangOpts.GNUMode && ArraySize->EvaluateAsInt(SizeVal, S.Context)) {
+ S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
+ return false;
}
return true;
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=147318&r1=147317&r2=147318&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Wed Dec 28 13:48:30 2011
@@ -482,9 +482,8 @@
VisitOffsetOfExpr(const OffsetOfExpr *OOE,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currentBuilderContext);
- Expr::EvalResult Res;
- if (OOE->EvaluateAsRValue(Res, getContext()) && Res.Val.isInt()) {
- const APSInt &IV = Res.Val.getInt();
+ APSInt IV;
+ if (OOE->EvaluateAsInt(IV, getContext())) {
assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
assert(OOE->getType()->isIntegerType());
assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType());
@@ -519,9 +518,8 @@
}
}
- Expr::EvalResult Result;
- Ex->EvaluateAsRValue(Result, getContext());
- CharUnits amt = CharUnits::fromQuantity(Result.Val.getInt().getZExtValue());
+ APSInt Value = Ex->EvaluateKnownConstInt(getContext());
+ CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue());
const ProgramState *state = Pred->getState();
state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(),
More information about the cfe-commits
mailing list