Revert "Revert r347417 "Re-Reinstate 347294 with a fix for the failures.""

It seems the two failing tests can be simply fixed after r348037

Fix 3 cases in Analysis/builtin-functions.cpp
Delete the bad CodeGen/builtin-constant-p.c for now

llvm-svn: 348053
This commit is contained in:
Fangrui Song 2018-11-30 23:41:18 +00:00
parent cada498038
commit 407659ab0a
35 changed files with 396 additions and 194 deletions

View File

@ -583,7 +583,8 @@ public:
/// this function returns true, it returns the folded constant in Result. If /// this function returns true, it returns the folded constant in Result. If
/// the expression is a glvalue, an lvalue-to-rvalue conversion will be /// the expression is a glvalue, an lvalue-to-rvalue conversion will be
/// applied. /// applied.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
bool InConstantContext = false) const;
/// EvaluateAsBooleanCondition - Return true if this is a constant /// EvaluateAsBooleanCondition - Return true if this is a constant
/// which we can fold and convert to a boolean condition using /// which we can fold and convert to a boolean condition using
@ -600,7 +601,7 @@ public:
/// EvaluateAsInt - Return true if this is a constant which we can fold and /// EvaluateAsInt - Return true if this is a constant which we can fold and
/// convert to an integer, using any crazy technique that we want to. /// convert to an integer, using any crazy technique that we want to.
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; SideEffectsKind AllowSideEffects = SE_NoSideEffects) const;
/// EvaluateAsFloat - Return true if this is a constant which we can fold and /// EvaluateAsFloat - Return true if this is a constant which we can fold and
@ -901,10 +902,15 @@ public:
/// ConstantExpr - An expression that occurs in a constant context. /// ConstantExpr - An expression that occurs in a constant context.
class ConstantExpr : public FullExpr { class ConstantExpr : public FullExpr {
public:
ConstantExpr(Expr *subexpr) ConstantExpr(Expr *subexpr)
: FullExpr(ConstantExprClass, subexpr) {} : FullExpr(ConstantExprClass, subexpr) {}
public:
static ConstantExpr *Create(const ASTContext &Context, Expr *E) {
assert(!isa<ConstantExpr>(E));
return new (Context) ConstantExpr(E);
}
/// Build an empty constant expression wrapper. /// Build an empty constant expression wrapper.
explicit ConstantExpr(EmptyShell Empty) explicit ConstantExpr(EmptyShell Empty)
: FullExpr(ConstantExprClass, Empty) {} : FullExpr(ConstantExprClass, Empty) {}
@ -3087,8 +3093,8 @@ inline Expr *Expr::IgnoreImpCasts() {
while (true) while (true)
if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) if (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e))
e = ice->getSubExpr(); e = ice->getSubExpr();
else if (ConstantExpr *ce = dyn_cast<ConstantExpr>(e)) else if (FullExpr *fe = dyn_cast<FullExpr>(e))
e = ce->getSubExpr(); e = fe->getSubExpr();
else else
break; break;
return e; return e;

View File

@ -6388,7 +6388,7 @@ ExpectedStmt ASTNodeImporter::VisitConstantExpr(ConstantExpr *E) {
Expr *ToSubExpr; Expr *ToSubExpr;
std::tie(ToSubExpr) = *Imp; std::tie(ToSubExpr) = *Imp;
return new (Importer.getToContext()) ConstantExpr(ToSubExpr); return ConstantExpr::Create(Importer.getToContext(), ToSubExpr);
} }
ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) { ExpectedStmt ASTNodeImporter::VisitParenExpr(ParenExpr *E) {

View File

@ -2594,8 +2594,8 @@ Expr *Expr::IgnoreParenCasts() {
E = NTTP->getReplacement(); E = NTTP->getReplacement();
continue; continue;
} }
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
E = CE->getSubExpr(); E = FE->getSubExpr();
continue; continue;
} }
return E; return E;
@ -2619,8 +2619,8 @@ Expr *Expr::IgnoreCasts() {
E = NTTP->getReplacement(); E = NTTP->getReplacement();
continue; continue;
} }
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
E = CE->getSubExpr(); E = FE->getSubExpr();
continue; continue;
} }
return E; return E;
@ -2648,8 +2648,8 @@ Expr *Expr::IgnoreParenLValueCasts() {
= dyn_cast<SubstNonTypeTemplateParmExpr>(E)) { = dyn_cast<SubstNonTypeTemplateParmExpr>(E)) {
E = NTTP->getReplacement(); E = NTTP->getReplacement();
continue; continue;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E)) { } else if (FullExpr *FE = dyn_cast<FullExpr>(E)) {
E = CE->getSubExpr(); E = FE->getSubExpr();
continue; continue;
} }
break; break;
@ -2920,6 +2920,12 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
break; break;
} }
case ConstantExprClass: {
// FIXME: We should be able to return "true" here, but it can lead to extra
// error messages. E.g. in Sema/array-init.c.
const Expr *Exp = cast<ConstantExpr>(this)->getSubExpr();
return Exp->isConstantInitializer(Ctx, false, Culprit);
}
case CompoundLiteralExprClass: { case CompoundLiteralExprClass: {
// This handles gcc's extension that allows global initializers like // This handles gcc's extension that allows global initializers like
// "struct x {int x;} x = (struct x) {};". // "struct x {int x;} x = (struct x) {};".
@ -2959,8 +2965,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
const Expr *Elt = ILE->getInit(ElementNo++); const Expr *Elt = ILE->getInit(ElementNo++);
if (Field->isBitField()) { if (Field->isBitField()) {
// Bitfields have to evaluate to an integer. // Bitfields have to evaluate to an integer.
llvm::APSInt ResultTmp; EvalResult Result;
if (!Elt->EvaluateAsInt(ResultTmp, Ctx)) { if (!Elt->EvaluateAsInt(Result, Ctx)) {
if (Culprit) if (Culprit)
*Culprit = Elt; *Culprit = Elt;
return false; return false;

View File

@ -45,6 +45,7 @@
#include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h" #include "clang/Basic/Builtins.h"
#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetInfo.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include <cstring> #include <cstring>
#include <functional> #include <functional>
@ -721,6 +722,10 @@ namespace {
/// Whether or not we're currently speculatively evaluating. /// Whether or not we're currently speculatively evaluating.
bool IsSpeculativelyEvaluating; bool IsSpeculativelyEvaluating;
/// Whether or not we're in a context where the front end requires a
/// constant value.
bool InConstantContext;
enum EvaluationMode { enum EvaluationMode {
/// Evaluate as a constant expression. Stop if we find that the expression /// Evaluate as a constant expression. Stop if we find that the expression
/// is not a constant expression. /// is not a constant expression.
@ -782,7 +787,7 @@ namespace {
EvaluatingDecl((const ValueDecl *)nullptr), EvaluatingDecl((const ValueDecl *)nullptr),
EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false), EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false), HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
EvalMode(Mode) {} InConstantContext(false), EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) { void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base; EvaluatingDecl = Base;
@ -5625,8 +5630,10 @@ static bool getBytesReturnedByAllocSizeCall(const ASTContext &Ctx,
return false; return false;
auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) { auto EvaluateAsSizeT = [&](const Expr *E, APSInt &Into) {
if (!E->EvaluateAsInt(Into, Ctx, Expr::SE_AllowSideEffects)) Expr::EvalResult ExprResult;
if (!E->EvaluateAsInt(ExprResult, Ctx, Expr::SE_AllowSideEffects))
return false; return false;
Into = ExprResult.Val.getInt();
if (Into.isNegative() || !Into.isIntN(BitsInSizeT)) if (Into.isNegative() || !Into.isIntN(BitsInSizeT))
return false; return false;
Into = Into.zextOrSelf(BitsInSizeT); Into = Into.zextOrSelf(BitsInSizeT);
@ -7348,6 +7355,8 @@ public:
// Visitor Methods // Visitor Methods
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
bool VisitConstantExpr(const ConstantExpr *E);
bool VisitIntegerLiteral(const IntegerLiteral *E) { bool VisitIntegerLiteral(const IntegerLiteral *E) {
return Success(E->getValue(), E); return Success(E->getValue(), E);
} }
@ -8088,6 +8097,11 @@ static bool tryEvaluateBuiltinObjectSize(const Expr *E, unsigned Type,
return true; return true;
} }
bool IntExprEvaluator::VisitConstantExpr(const ConstantExpr *E) {
llvm::SaveAndRestore<bool> InConstantContext(Info.InConstantContext, true);
return ExprEvaluatorBaseTy::VisitConstantExpr(E);
}
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (unsigned BuiltinOp = E->getBuiltinCallee()) if (unsigned BuiltinOp = E->getBuiltinCallee())
return VisitBuiltinCallExpr(E, BuiltinOp); return VisitBuiltinCallExpr(E, BuiltinOp);
@ -8175,8 +8189,19 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.countLeadingZeros(), E); return Success(Val.countLeadingZeros(), E);
} }
case Builtin::BI__builtin_constant_p: case Builtin::BI__builtin_constant_p: {
return Success(EvaluateBuiltinConstantP(Info.Ctx, E->getArg(0)), E); auto Arg = E->getArg(0);
if (EvaluateBuiltinConstantP(Info.Ctx, Arg))
return Success(true, E);
auto ArgTy = Arg->IgnoreImplicit()->getType();
if (!Info.InConstantContext && !Arg->HasSideEffects(Info.Ctx) &&
!ArgTy->isAggregateType() && !ArgTy->isPointerType()) {
// We can delay calculation of __builtin_constant_p until after
// inlining. Note: This diagnostic won't be shown to the user.
Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
}
return Success(false, E);
}
case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzl:
@ -10746,19 +10771,46 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
return false; return false;
} }
static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result,
Expr::SideEffectsKind SEK) {
return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
(SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
}
static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
const ASTContext &Ctx, EvalInfo &Info) {
bool IsConst;
if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
return IsConst;
return EvaluateAsRValue(Info, E, Result.Val);
}
static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult,
const ASTContext &Ctx,
Expr::SideEffectsKind AllowSideEffects,
EvalInfo &Info) {
if (!E->getType()->isIntegralOrEnumerationType())
return false;
if (!::EvaluateAsRValue(E, ExprResult, Ctx, Info) ||
!ExprResult.Val.isInt() ||
hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
return false;
return true;
}
/// EvaluateAsRValue - Return true if this is a constant which we can fold using /// EvaluateAsRValue - Return true if this is a constant which we can fold using
/// any crazy technique (that has nothing to do with language standards) that /// 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 /// we want to. If this function returns true, it returns the folded constant
/// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion /// in Result. If this expression is a glvalue, an lvalue-to-rvalue conversion
/// will be applied to the result. /// will be applied to the result.
bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const { bool Expr::EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx,
bool IsConst; bool InConstantContext) const {
if (FastEvaluateAsRValue(this, Result, Ctx, IsConst))
return IsConst;
EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects); EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
return ::EvaluateAsRValue(Info, this, Result.Val); Info.InConstantContext = InConstantContext;
return ::EvaluateAsRValue(this, Result, Ctx, Info);
} }
bool Expr::EvaluateAsBooleanCondition(bool &Result, bool Expr::EvaluateAsBooleanCondition(bool &Result,
@ -10768,24 +10820,10 @@ bool Expr::EvaluateAsBooleanCondition(bool &Result,
HandleConversionToBool(Scratch.Val, Result); HandleConversionToBool(Scratch.Val, Result);
} }
static bool hasUnacceptableSideEffect(Expr::EvalStatus &Result, bool Expr::EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx,
Expr::SideEffectsKind SEK) {
return (SEK < Expr::SE_AllowSideEffects && Result.HasSideEffects) ||
(SEK < Expr::SE_AllowUndefinedBehavior && Result.HasUndefinedBehavior);
}
bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
SideEffectsKind AllowSideEffects) const { SideEffectsKind AllowSideEffects) const {
if (!getType()->isIntegralOrEnumerationType()) EvalInfo Info(Ctx, Result, EvalInfo::EM_IgnoreSideEffects);
return false; return ::EvaluateAsInt(this, Result, Ctx, AllowSideEffects, Info);
EvalResult ExprResult;
if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isInt() ||
hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
return false;
Result = ExprResult.Val.getInt();
return true;
} }
bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx, bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx,
@ -10843,6 +10881,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
? EvalInfo::EM_ConstantExpression ? EvalInfo::EM_ConstantExpression
: EvalInfo::EM_ConstantFold); : EvalInfo::EM_ConstantFold);
InitInfo.setEvaluatingDecl(VD, Value); InitInfo.setEvaluatingDecl(VD, Value);
InitInfo.InConstantContext = true;
LValue LVal; LValue LVal;
LVal.set(VD); LVal.set(VD);
@ -10872,41 +10911,46 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
/// constant folded, but discard the result. /// constant folded, but discard the result.
bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const { bool Expr::isEvaluatable(const ASTContext &Ctx, SideEffectsKind SEK) const {
EvalResult Result; EvalResult Result;
return EvaluateAsRValue(Result, Ctx) && return EvaluateAsRValue(Result, Ctx, /* in constant context */ true) &&
!hasUnacceptableSideEffect(Result, SEK); !hasUnacceptableSideEffect(Result, SEK);
} }
APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx, APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
SmallVectorImpl<PartialDiagnosticAt> *Diag) const { SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
EvalResult EvalResult; EvalResult EVResult;
EvalResult.Diag = Diag; EVResult.Diag = Diag;
bool Result = EvaluateAsRValue(EvalResult, Ctx); EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
Info.InConstantContext = true;
bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info);
(void)Result; (void)Result;
assert(Result && "Could not evaluate expression"); assert(Result && "Could not evaluate expression");
assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
return EvalResult.Val.getInt(); return EVResult.Val.getInt();
} }
APSInt Expr::EvaluateKnownConstIntCheckOverflow( APSInt Expr::EvaluateKnownConstIntCheckOverflow(
const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const { const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
EvalResult EvalResult; EvalResult EVResult;
EvalResult.Diag = Diag; EVResult.Diag = Diag;
EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
bool Result = ::EvaluateAsRValue(Info, this, EvalResult.Val); Info.InConstantContext = true;
bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val);
(void)Result; (void)Result;
assert(Result && "Could not evaluate expression"); assert(Result && "Could not evaluate expression");
assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer"); assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
return EvalResult.Val.getInt(); return EVResult.Val.getInt();
} }
void Expr::EvaluateForOverflow(const ASTContext &Ctx) const { void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
bool IsConst; bool IsConst;
EvalResult EvalResult; EvalResult EVResult;
if (!FastEvaluateAsRValue(this, EvalResult, Ctx, IsConst)) { if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow); EvalInfo Info(Ctx, EVResult, EvalInfo::EM_EvaluateForOverflow);
(void)::EvaluateAsRValue(Info, this, EvalResult.Val); (void)::EvaluateAsRValue(Info, this, EVResult.Val);
} }
} }
@ -10959,7 +11003,11 @@ static ICEDiag Worst(ICEDiag A, ICEDiag B) { return A.Kind >= B.Kind ? A : B; }
static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) { static ICEDiag CheckEvalInICE(const Expr* E, const ASTContext &Ctx) {
Expr::EvalResult EVResult; Expr::EvalResult EVResult;
if (!E->EvaluateAsRValue(EVResult, Ctx) || EVResult.HasSideEffects || Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression);
Info.InConstantContext = true;
if (!::EvaluateAsRValue(E, EVResult, Ctx, Info) || EVResult.HasSideEffects ||
!EVResult.Val.isInt()) !EVResult.Val.isInt())
return ICEDiag(IK_NotICE, E->getBeginLoc()); return ICEDiag(IK_NotICE, E->getBeginLoc());
@ -11397,12 +11445,20 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx,
if (!isIntegerConstantExpr(Ctx, Loc)) if (!isIntegerConstantExpr(Ctx, Loc))
return false; return false;
// The only possible side-effects here are due to UB discovered in the // The only possible side-effects here are due to UB discovered in the
// evaluation (for instance, INT_MAX + 1). In such a case, we are still // evaluation (for instance, INT_MAX + 1). In such a case, we are still
// required to treat the expression as an ICE, so we produce the folded // required to treat the expression as an ICE, so we produce the folded
// value. // value.
if (!EvaluateAsInt(Value, Ctx, SE_AllowSideEffects)) EvalResult ExprResult;
Expr::EvalStatus Status;
EvalInfo Info(Ctx, Status, EvalInfo::EM_IgnoreSideEffects);
Info.InConstantContext = true;
if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info))
llvm_unreachable("ICE cannot be evaluated!"); llvm_unreachable("ICE cannot be evaluated!");
Value = ExprResult.Val.getInt();
return true; return true;
} }
@ -11488,6 +11544,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
EvalInfo Info(FD->getASTContext(), Status, EvalInfo Info(FD->getASTContext(), Status,
EvalInfo::EM_PotentialConstantExpression); EvalInfo::EM_PotentialConstantExpression);
Info.InConstantContext = true;
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr; const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr;

View File

@ -1039,12 +1039,14 @@ private:
if (!areExprTypesCompatible(Expr1, Expr2)) if (!areExprTypesCompatible(Expr1, Expr2))
return {}; return {};
llvm::APSInt L1, L2; Expr::EvalResult L1Result, L2Result;
if (!Expr1->EvaluateAsInt(L1Result, *Context) ||
if (!Expr1->EvaluateAsInt(L1, *Context) || !Expr2->EvaluateAsInt(L2Result, *Context))
!Expr2->EvaluateAsInt(L2, *Context))
return {}; return {};
llvm::APSInt L1 = L1Result.Val.getInt();
llvm::APSInt L2 = L2Result.Val.getInt();
// Can't compare signed with unsigned or with different bit width. // Can't compare signed with unsigned or with different bit width.
if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth()) if (L1.isSigned() != L2.isSigned() || L1.getBitWidth() != L2.getBitWidth())
return {}; return {};
@ -1134,13 +1136,16 @@ private:
case BO_And: { case BO_And: {
// If either operand is zero, we know the value // If either operand is zero, we know the value
// must be false. // must be false.
llvm::APSInt IntVal; Expr::EvalResult LHSResult;
if (Bop->getLHS()->EvaluateAsInt(IntVal, *Context)) { if (Bop->getLHS()->EvaluateAsInt(LHSResult, *Context)) {
llvm::APSInt IntVal = LHSResult.Val.getInt();
if (!IntVal.getBoolValue()) { if (!IntVal.getBoolValue()) {
return TryResult(false); return TryResult(false);
} }
} }
if (Bop->getRHS()->EvaluateAsInt(IntVal, *Context)) { Expr::EvalResult RHSResult;
if (Bop->getRHS()->EvaluateAsInt(RHSResult, *Context)) {
llvm::APSInt IntVal = RHSResult.Val.getInt();
if (!IntVal.getBoolValue()) { if (!IntVal.getBoolValue()) {
return TryResult(false); return TryResult(false);
} }

View File

@ -1896,6 +1896,26 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI_rotr64: case Builtin::BI_rotr64:
return emitRotate(E, true); return emitRotate(E, true);
case Builtin::BI__builtin_constant_p: {
llvm::Type *ResultType = ConvertType(E->getType());
if (CGM.getCodeGenOpts().OptimizationLevel == 0)
// At -O0, we don't perform inlining, so we don't need to delay the
// processing.
return RValue::get(ConstantInt::get(ResultType, 0));
const Expr *Arg = E->getArg(0);
QualType ArgType = Arg->getType();
if (!hasScalarEvaluationKind(ArgType) || ArgType->isFunctionType())
// We can only reason about scalar types.
return RValue::get(ConstantInt::get(ResultType, 0));
Value *ArgValue = EmitScalarExpr(Arg);
Value *F = CGM.getIntrinsic(Intrinsic::is_constant, ConvertType(ArgType));
Value *Result = Builder.CreateCall(F, ArgValue);
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/false);
return RValue::get(Result);
}
case Builtin::BI__builtin_object_size: { case Builtin::BI__builtin_object_size: {
unsigned Type = unsigned Type =
E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue(); E->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
@ -2160,10 +2180,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin___memcpy_chk: { case Builtin::BI__builtin___memcpy_chk: {
// fold __builtin_memcpy_chk(x, y, cst1, cst2) to memcpy iff cst1<=cst2. // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memcpy iff cst1<=cst2.
llvm::APSInt Size, DstSize; Expr::EvalResult SizeResult, DstSizeResult;
if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
!E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break; break;
llvm::APSInt Size = SizeResult.Val.getInt();
llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize)) if (Size.ugt(DstSize))
break; break;
Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(0));
@ -2184,10 +2206,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin___memmove_chk: { case Builtin::BI__builtin___memmove_chk: {
// fold __builtin_memmove_chk(x, y, cst1, cst2) to memmove iff cst1<=cst2. // fold __builtin_memmove_chk(x, y, cst1, cst2) to memmove iff cst1<=cst2.
llvm::APSInt Size, DstSize; Expr::EvalResult SizeResult, DstSizeResult;
if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
!E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break; break;
llvm::APSInt Size = SizeResult.Val.getInt();
llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize)) if (Size.ugt(DstSize))
break; break;
Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(0));
@ -2222,10 +2246,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
} }
case Builtin::BI__builtin___memset_chk: { case Builtin::BI__builtin___memset_chk: {
// fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
llvm::APSInt Size, DstSize; Expr::EvalResult SizeResult, DstSizeResult;
if (!E->getArg(2)->EvaluateAsInt(Size, CGM.getContext()) || if (!E->getArg(2)->EvaluateAsInt(SizeResult, CGM.getContext()) ||
!E->getArg(3)->EvaluateAsInt(DstSize, CGM.getContext())) !E->getArg(3)->EvaluateAsInt(DstSizeResult, CGM.getContext()))
break; break;
llvm::APSInt Size = SizeResult.Val.getInt();
llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ugt(DstSize)) if (Size.ugt(DstSize))
break; break;
Address Dest = EmitPointerWithAlignment(E->getArg(0)); Address Dest = EmitPointerWithAlignment(E->getArg(0));
@ -5739,10 +5765,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,
llvm::FunctionType *FTy = llvm::FunctionType *FTy =
llvm::FunctionType::get(VoidTy, /*Variadic=*/false); llvm::FunctionType::get(VoidTy, /*Variadic=*/false);
APSInt Value; Expr::EvalResult Result;
if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
llvm_unreachable("Sema will ensure that the parameter is constant"); llvm_unreachable("Sema will ensure that the parameter is constant");
llvm::APSInt Value = Result.Val.getInt();
uint64_t ZExtValue = Value.zextOrTrunc(IsThumb ? 16 : 32).getZExtValue(); uint64_t ZExtValue = Value.zextOrTrunc(IsThumb ? 16 : 32).getZExtValue();
llvm::InlineAsm *Emit = llvm::InlineAsm *Emit =
@ -6845,10 +6872,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID,
} }
if (BuiltinID == AArch64::BI__getReg) { if (BuiltinID == AArch64::BI__getReg) {
APSInt Value; Expr::EvalResult Result;
if (!E->getArg(0)->EvaluateAsInt(Value, CGM.getContext())) if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext()))
llvm_unreachable("Sema will ensure that the parameter is constant"); llvm_unreachable("Sema will ensure that the parameter is constant");
llvm::APSInt Value = Result.Val.getInt();
LLVMContext &Context = CGM.getLLVMContext(); LLVMContext &Context = CGM.getLLVMContext();
std::string Reg = Value == 31 ? "sp" : "x" + Value.toString(10); std::string Reg = Value == 31 ? "sp" : "x" + Value.toString(10);

View File

@ -2523,9 +2523,9 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
Count = CAT->getSize().getZExtValue(); Count = CAT->getSize().getZExtValue();
else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) { else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
if (Expr *Size = VAT->getSizeExpr()) { if (Expr *Size = VAT->getSizeExpr()) {
llvm::APSInt V; Expr::EvalResult Result;
if (Size->EvaluateAsInt(V, CGM.getContext())) if (Size->EvaluateAsInt(Result, CGM.getContext()))
Count = V.getExtValue(); Count = Result.Val.getInt().getExtValue();
} }
} }

View File

@ -1717,8 +1717,9 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) {
CGF.EmitIgnoredExpr(E->getBase()); CGF.EmitIgnoredExpr(E->getBase());
return CGF.emitScalarConstant(Constant, E); return CGF.emitScalarConstant(Constant, E);
} else { } else {
llvm::APSInt Value; Expr::EvalResult Result;
if (E->EvaluateAsInt(Value, CGF.getContext(), Expr::SE_AllowSideEffects)) { if (E->EvaluateAsInt(Result, CGF.getContext(), Expr::SE_AllowSideEffects)) {
llvm::APSInt Value = Result.Val.getInt();
CGF.EmitIgnoredExpr(E->getBase()); CGF.EmitIgnoredExpr(E->getBase());
return Builder.getInt(Value); return Builder.getInt(Value);
} }
@ -2597,9 +2598,11 @@ Value *ScalarExprEmitter::VisitUnaryLNot(const UnaryOperator *E) {
Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) {
// Try folding the offsetof to a constant. // Try folding the offsetof to a constant.
llvm::APSInt Value; Expr::EvalResult EVResult;
if (E->EvaluateAsInt(Value, CGF.getContext())) if (E->EvaluateAsInt(EVResult, CGF.getContext())) {
llvm::APSInt Value = EVResult.Val.getInt();
return Builder.getInt(Value); return Builder.getInt(Value);
}
// Loop over the components of the offsetof to compute the value. // Loop over the components of the offsetof to compute the value.
unsigned n = E->getNumComponents(); unsigned n = E->getNumComponents();

View File

@ -6797,10 +6797,11 @@ private:
} }
// Check if the length evaluates to 1. // Check if the length evaluates to 1.
llvm::APSInt ConstLength; Expr::EvalResult Result;
if (!Length->EvaluateAsInt(ConstLength, CGF.getContext())) if (!Length->EvaluateAsInt(Result, CGF.getContext()))
return true; // Can have more that size 1. return true; // Can have more that size 1.
llvm::APSInt ConstLength = Result.Val.getInt();
return ConstLength.getSExtValue() != 1; return ConstLength.getSExtValue() != 1;
} }
@ -9164,8 +9165,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
ParamAttrTy &ParamAttr = ParamAttrs[Pos]; ParamAttrTy &ParamAttr = ParamAttrs[Pos];
ParamAttr.Kind = Linear; ParamAttr.Kind = Linear;
if (*SI) { if (*SI) {
if (!(*SI)->EvaluateAsInt(ParamAttr.StrideOrArg, C, Expr::EvalResult Result;
Expr::SE_AllowSideEffects)) { if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
if (const auto *DRE = if (const auto *DRE =
cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
@ -9174,6 +9175,8 @@ void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
ParamPositions[StridePVD->getCanonicalDecl()]); ParamPositions[StridePVD->getCanonicalDecl()]);
} }
} }
} else {
ParamAttr.StrideOrArg = Result.Val.getInt();
} }
} }
++SI; ++SI;

View File

@ -1821,9 +1821,9 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
// If this can't be a register or memory, i.e., has to be a constant // If this can't be a register or memory, i.e., has to be a constant
// (immediate or symbolic), try to emit it as such. // (immediate or symbolic), try to emit it as such.
if (!Info.allowsRegister() && !Info.allowsMemory()) { if (!Info.allowsRegister() && !Info.allowsMemory()) {
llvm::APSInt Result; Expr::EvalResult Result;
if (InputExpr->EvaluateAsInt(Result, getContext())) if (InputExpr->EvaluateAsInt(Result, getContext()))
return llvm::ConstantInt::get(getLLVMContext(), Result); return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt());
assert(!Info.requiresImmediateConstant() && assert(!Info.requiresImmediateConstant() &&
"Required-immediate inlineasm arg isn't constant?"); "Required-immediate inlineasm arg isn't constant?");
} }

View File

@ -2321,9 +2321,11 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(), Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
S.getIterationVariable()->getType(), S.getIterationVariable()->getType(),
S.getBeginLoc()); S.getBeginLoc());
llvm::APSInt EvaluatedChunk; Expr::EvalResult Result;
if (ChunkExpr->EvaluateAsInt(EvaluatedChunk, getContext())) if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
llvm::APSInt EvaluatedChunk = Result.Val.getInt();
HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1); HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
}
} }
const unsigned IVSize = getContext().getTypeSize(IVExpr->getType()); const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation(); const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();

View File

@ -1513,10 +1513,11 @@ bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
bool AllowLabels) { bool AllowLabels) {
// FIXME: Rename and handle conversion of other evaluatable things // FIXME: Rename and handle conversion of other evaluatable things
// to bool. // to bool.
llvm::APSInt Int; Expr::EvalResult Result;
if (!Cond->EvaluateAsInt(Int, getContext())) if (!Cond->EvaluateAsInt(Result, getContext()))
return false; // Not foldable, not integer or not fully evaluatable. return false; // Not foldable, not integer or not fully evaluatable.
llvm::APSInt Int = Result.Val.getInt();
if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond)) if (!AllowLabels && CodeGenFunction::ContainsLabel(Cond))
return false; // Contains a label. return false; // Contains a label.

View File

@ -1309,11 +1309,10 @@ static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
case Stmt::ObjCForCollectionStmtClass: case Stmt::ObjCForCollectionStmtClass:
return true; return true;
case Stmt::DoStmtClass: { case Stmt::DoStmtClass: {
const Expr *Cond = cast<DoStmt>(S)->getCond(); Expr::EvalResult Result;
llvm::APSInt Val; if (!cast<DoStmt>(S)->getCond()->EvaluateAsInt(Result, Ctx))
if (!Cond->EvaluateAsInt(Val, Ctx))
return true; return true;
return Val.getBoolValue(); return Result.Val.getInt().getBoolValue();
} }
default: default:
break; break;

View File

@ -2554,8 +2554,9 @@ void CastOperation::CheckCStyleCast() {
// OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type. // OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type.
if (Self.getLangOpts().OpenCL && DestType->isEventT()) { if (Self.getLangOpts().OpenCL && DestType->isEventT()) {
llvm::APSInt CastInt; Expr::EvalResult Result;
if (SrcExpr.get()->EvaluateAsInt(CastInt, Self.Context)) { if (SrcExpr.get()->EvaluateAsInt(Result, Self.Context)) {
llvm::APSInt CastInt = Result.Val.getInt();
if (0 == CastInt) { if (0 == CastInt) {
Kind = CK_ZeroToOCLOpaqueType; Kind = CK_ZeroToOCLOpaqueType;
return; return;

View File

@ -247,13 +247,16 @@ static void SemaBuiltinMemChkCall(Sema &S, FunctionDecl *FDecl,
const Expr *SizeArg = TheCall->getArg(SizeIdx); const Expr *SizeArg = TheCall->getArg(SizeIdx);
const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx); const Expr *DstSizeArg = TheCall->getArg(DstSizeIdx);
llvm::APSInt Size, DstSize; Expr::EvalResult SizeResult, DstSizeResult;
// find out if both sizes are known at compile time // find out if both sizes are known at compile time
if (!SizeArg->EvaluateAsInt(Size, S.Context) || if (!SizeArg->EvaluateAsInt(SizeResult, S.Context) ||
!DstSizeArg->EvaluateAsInt(DstSize, S.Context)) !DstSizeArg->EvaluateAsInt(DstSizeResult, S.Context))
return; return;
llvm::APSInt Size = SizeResult.Val.getInt();
llvm::APSInt DstSize = DstSizeResult.Val.getInt();
if (Size.ule(DstSize)) if (Size.ule(DstSize))
return; return;
@ -6481,13 +6484,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
return SLCT_NotALiteral; return SLCT_NotALiteral;
} }
case Stmt::BinaryOperatorClass: { case Stmt::BinaryOperatorClass: {
llvm::APSInt LResult;
llvm::APSInt RResult;
const BinaryOperator *BinOp = cast<BinaryOperator>(E); const BinaryOperator *BinOp = cast<BinaryOperator>(E);
// A string literal + an int offset is still a string literal. // A string literal + an int offset is still a string literal.
if (BinOp->isAdditiveOp()) { if (BinOp->isAdditiveOp()) {
Expr::EvalResult LResult, RResult;
bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context); bool LIsInt = BinOp->getLHS()->EvaluateAsInt(LResult, S.Context);
bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context); bool RIsInt = BinOp->getRHS()->EvaluateAsInt(RResult, S.Context);
@ -6496,12 +6498,12 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
if (LIsInt) { if (LIsInt) {
if (BinOpKind == BO_Add) { if (BinOpKind == BO_Add) {
sumOffsets(Offset, LResult, BinOpKind, RIsInt); sumOffsets(Offset, LResult.Val.getInt(), BinOpKind, RIsInt);
E = BinOp->getRHS(); E = BinOp->getRHS();
goto tryAgain; goto tryAgain;
} }
} else { } else {
sumOffsets(Offset, RResult, BinOpKind, RIsInt); sumOffsets(Offset, RResult.Val.getInt(), BinOpKind, RIsInt);
E = BinOp->getLHS(); E = BinOp->getLHS();
goto tryAgain; goto tryAgain;
} }
@ -6514,9 +6516,10 @@ checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef<const Expr *> Args,
const UnaryOperator *UnaOp = cast<UnaryOperator>(E); const UnaryOperator *UnaOp = cast<UnaryOperator>(E);
auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr()); auto ASE = dyn_cast<ArraySubscriptExpr>(UnaOp->getSubExpr());
if (UnaOp->getOpcode() == UO_AddrOf && ASE) { if (UnaOp->getOpcode() == UO_AddrOf && ASE) {
llvm::APSInt IndexResult; Expr::EvalResult IndexResult;
if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) { if (ASE->getRHS()->EvaluateAsInt(IndexResult, S.Context)) {
sumOffsets(Offset, IndexResult, BO_Add, /*RHS is int*/ true); sumOffsets(Offset, IndexResult.Val.getInt(), BO_Add,
/*RHS is int*/ true);
E = ASE->getBase(); E = ASE->getBase();
goto tryAgain; goto tryAgain;
} }
@ -10261,8 +10264,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
Expr *OriginalInit = Init->IgnoreParenImpCasts(); Expr *OriginalInit = Init->IgnoreParenImpCasts();
unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context);
llvm::APSInt Value; Expr::EvalResult Result;
if (!OriginalInit->EvaluateAsInt(Value, S.Context, if (!OriginalInit->EvaluateAsInt(Result, S.Context,
Expr::SE_AllowSideEffects)) { Expr::SE_AllowSideEffects)) {
// The RHS is not constant. If the RHS has an enum type, make sure the // The RHS is not constant. If the RHS has an enum type, make sure the
// bitfield is wide enough to hold all the values of the enum without // bitfield is wide enough to hold all the values of the enum without
@ -10318,6 +10321,8 @@ static bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init,
return false; return false;
} }
llvm::APSInt Value = Result.Val.getInt();
unsigned OriginalWidth = Value.getBitWidth(); unsigned OriginalWidth = Value.getBitWidth();
if (!Value.isSigned() || Value.isNegative()) if (!Value.isSigned() || Value.isNegative())
@ -10930,8 +10935,11 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
if (SourceRange.Width > TargetRange.Width) { if (SourceRange.Width > TargetRange.Width) {
// If the source is a constant, use a default-on diagnostic. // If the source is a constant, use a default-on diagnostic.
// TODO: this should happen for bitfield stores, too. // TODO: this should happen for bitfield stores, too.
llvm::APSInt Value(32); Expr::EvalResult Result;
if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects)) { if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects)) {
llvm::APSInt Value(32);
Value = Result.Val.getInt();
if (S.SourceMgr.isInSystemMacro(CC)) if (S.SourceMgr.isInSystemMacro(CC))
return; return;
@ -10975,9 +10983,10 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
// source value is exactly the width of the target type, which will // source value is exactly the width of the target type, which will
// cause a negative value to be stored. // cause a negative value to be stored.
llvm::APSInt Value; Expr::EvalResult Result;
if (E->EvaluateAsInt(Value, S.Context, Expr::SE_AllowSideEffects) && if (E->EvaluateAsInt(Result, S.Context, Expr::SE_AllowSideEffects) &&
!S.SourceMgr.isInSystemMacro(CC)) { !S.SourceMgr.isInSystemMacro(CC)) {
llvm::APSInt Value = Result.Val.getInt();
if (isSameWidthConstantConversion(S, E, T, CC)) { if (isSameWidthConstantConversion(S, E, T, CC)) {
std::string PrettySourceValue = Value.toString(10); std::string PrettySourceValue = Value.toString(10);
std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange);
@ -12264,9 +12273,11 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
if (!ArrayTy) if (!ArrayTy)
return; return;
llvm::APSInt index; Expr::EvalResult Result;
if (!IndexExpr->EvaluateAsInt(index, Context, Expr::SE_AllowSideEffects)) if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects))
return; return;
llvm::APSInt index = Result.Val.getInt();
if (IndexNegated) if (IndexNegated)
index = -index; index = -index;

View File

@ -5575,11 +5575,13 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
if (VLATy->getElementType()->isVariablyModifiedType()) if (VLATy->getElementType()->isVariablyModifiedType())
return QualType(); return QualType();
llvm::APSInt Res; Expr::EvalResult Result;
if (!VLATy->getSizeExpr() || if (!VLATy->getSizeExpr() ||
!VLATy->getSizeExpr()->EvaluateAsInt(Res, Context)) !VLATy->getSizeExpr()->EvaluateAsInt(Result, Context))
return QualType(); return QualType();
llvm::APSInt Res = Result.Val.getInt();
// Check whether the array size is negative. // Check whether the array size is negative.
if (Res.isSigned() && Res.isNegative()) { if (Res.isSigned() && Res.isNegative()) {
SizeIsNegative = true; SizeIsNegative = true;

View File

@ -13860,6 +13860,8 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
if (Converted.isInvalid()) if (Converted.isInvalid())
Failed = true; Failed = true;
else
Converted = ConstantExpr::Create(Context, Converted.get());
llvm::APSInt Cond; llvm::APSInt Cond;
if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond, if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,

View File

@ -4376,10 +4376,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
return ExprError(); return ExprError();
if (LowerBound && !OriginalTy->isAnyPointerType()) { if (LowerBound && !OriginalTy->isAnyPointerType()) {
llvm::APSInt LowerBoundValue; Expr::EvalResult Result;
if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) { if (LowerBound->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections] // OpenMP 4.5, [2.4 Array Sections]
// The array section must be a subset of the original array. // The array section must be a subset of the original array.
llvm::APSInt LowerBoundValue = Result.Val.getInt();
if (LowerBoundValue.isNegative()) { if (LowerBoundValue.isNegative()) {
Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array) Diag(LowerBound->getExprLoc(), diag::err_omp_section_not_subset_of_array)
<< LowerBound->getSourceRange(); << LowerBound->getSourceRange();
@ -4389,10 +4390,11 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
} }
if (Length) { if (Length) {
llvm::APSInt LengthValue; Expr::EvalResult Result;
if (Length->EvaluateAsInt(LengthValue, Context)) { if (Length->EvaluateAsInt(Result, Context)) {
// OpenMP 4.5, [2.4 Array Sections] // OpenMP 4.5, [2.4 Array Sections]
// The length must evaluate to non-negative integers. // The length must evaluate to non-negative integers.
llvm::APSInt LengthValue = Result.Val.getInt();
if (LengthValue.isNegative()) { if (LengthValue.isNegative()) {
Diag(Length->getExprLoc(), diag::err_omp_section_length_negative) Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
<< LengthValue.toString(/*Radix=*/10, /*Signed=*/true) << LengthValue.toString(/*Radix=*/10, /*Signed=*/true)
@ -5799,6 +5801,13 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
? VK_RValue ? VK_RValue
: VK_LValue; : VK_LValue;
if (isFileScope)
if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
Expr *Init = ILE->getInit(i);
ILE->setInit(i, ConstantExpr::Create(Context, Init));
}
Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, Expr *E = new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
VK, LiteralExpr, isFileScope); VK, LiteralExpr, isFileScope);
if (isFileScope) { if (isFileScope) {
@ -5807,7 +5816,6 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
!literalType->isDependentType()) // C99 6.5.2.5p3 !literalType->isDependentType()) // C99 6.5.2.5p3
if (CheckForConstantInitializer(LiteralExpr, literalType)) if (CheckForConstantInitializer(LiteralExpr, literalType))
return ExprError(); return ExprError();
E = new (Context) ConstantExpr(E);
} else if (literalType.getAddressSpace() != LangAS::opencl_private && } else if (literalType.getAddressSpace() != LangAS::opencl_private &&
literalType.getAddressSpace() != LangAS::Default) { literalType.getAddressSpace() != LangAS::Default) {
// Embedded-C extensions to C99 6.5.2.5: // Embedded-C extensions to C99 6.5.2.5:
@ -8403,8 +8411,8 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
// Reject cases where the value of the Int is unknown as that would // Reject cases where the value of the Int is unknown as that would
// possibly cause truncation, but accept cases where the scalar can be // possibly cause truncation, but accept cases where the scalar can be
// demoted without loss of precision. // demoted without loss of precision.
llvm::APSInt Result; Expr::EvalResult EVResult;
bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy); int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy);
bool IntSigned = IntTy->hasSignedIntegerRepresentation(); bool IntSigned = IntTy->hasSignedIntegerRepresentation();
bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation(); bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation();
@ -8412,6 +8420,7 @@ static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int,
if (CstInt) { if (CstInt) {
// If the scalar is constant and is of a higher order and has more active // If the scalar is constant and is of a higher order and has more active
// bits that the vector element type, reject it. // bits that the vector element type, reject it.
llvm::APSInt Result = EVResult.Val.getInt();
unsigned NumBits = IntSigned unsigned NumBits = IntSigned
? (Result.isNegative() ? Result.getMinSignedBits() ? (Result.isNegative() ? Result.getMinSignedBits()
: Result.getActiveBits()) : Result.getActiveBits())
@ -8439,8 +8448,9 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
// Determine if the integer constant can be expressed as a floating point // Determine if the integer constant can be expressed as a floating point
// number of the appropriate type. // number of the appropriate type.
llvm::APSInt Result; Expr::EvalResult EVResult;
bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); bool CstInt = Int->get()->EvaluateAsInt(EVResult, S.Context);
uint64_t Bits = 0; uint64_t Bits = 0;
if (CstInt) { if (CstInt) {
// Reject constants that would be truncated if they were converted to // Reject constants that would be truncated if they were converted to
@ -8448,6 +8458,7 @@ static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int,
// FIXME: Ideally the conversion to an APFloat and from an APFloat // FIXME: Ideally the conversion to an APFloat and from an APFloat
// could be avoided if there was a convertFromAPInt method // could be avoided if there was a convertFromAPInt method
// which could signal back if implicit truncation occurred. // which could signal back if implicit truncation occurred.
llvm::APSInt Result = EVResult.Val.getInt();
llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy)); llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy));
Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(), Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(),
llvm::APFloat::rmTowardZero); llvm::APFloat::rmTowardZero);
@ -8787,9 +8798,10 @@ static void DiagnoseBadDivideOrRemainderValues(Sema& S, ExprResult &LHS,
ExprResult &RHS, ExprResult &RHS,
SourceLocation Loc, bool IsDiv) { SourceLocation Loc, bool IsDiv) {
// Check for division/remainder by zero. // Check for division/remainder by zero.
llvm::APSInt RHSValue; Expr::EvalResult RHSValue;
if (!RHS.get()->isValueDependent() && if (!RHS.get()->isValueDependent() &&
RHS.get()->EvaluateAsInt(RHSValue, S.Context) && RHSValue == 0) RHS.get()->EvaluateAsInt(RHSValue, S.Context) &&
RHSValue.Val.getInt() == 0)
S.DiagRuntimeBehavior(Loc, RHS.get(), S.DiagRuntimeBehavior(Loc, RHS.get(),
S.PDiag(diag::warn_remainder_division_by_zero) S.PDiag(diag::warn_remainder_division_by_zero)
<< IsDiv << RHS.get()->getSourceRange()); << IsDiv << RHS.get()->getSourceRange());
@ -9031,8 +9043,9 @@ static void diagnoseStringPlusInt(Sema &Self, SourceLocation OpLoc,
if (!IsStringPlusInt || IndexExpr->isValueDependent()) if (!IsStringPlusInt || IndexExpr->isValueDependent())
return; return;
llvm::APSInt index; Expr::EvalResult Result;
if (IndexExpr->EvaluateAsInt(index, Self.getASTContext())) { if (IndexExpr->EvaluateAsInt(Result, Self.getASTContext())) {
llvm::APSInt index = Result.Val.getInt();
unsigned StrLenWithNull = StrExpr->getLength() + 1; unsigned StrLenWithNull = StrExpr->getLength() + 1;
if (index.isNonNegative() && if (index.isNonNegative() &&
index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull), index <= llvm::APSInt(llvm::APInt(index.getBitWidth(), StrLenWithNull),
@ -9176,10 +9189,11 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS,
if (PExp->IgnoreParenCasts()->isNullPointerConstant( if (PExp->IgnoreParenCasts()->isNullPointerConstant(
Context, Expr::NPC_ValueDependentIsNotNull)) { Context, Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined. // In C++ adding zero to a null pointer is defined.
llvm::APSInt KnownVal; Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus || if (!getLangOpts().CPlusPlus ||
(!IExp->isValueDependent() && (!IExp->isValueDependent() &&
(!IExp->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { (!IExp->EvaluateAsInt(KnownVal, Context) ||
KnownVal.Val.getInt() != 0))) {
// Check the conditions to see if this is the 'p = nullptr + n' idiom. // Check the conditions to see if this is the 'p = nullptr + n' idiom.
bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension( bool IsGNUIdiom = BinaryOperator::isNullPointerArithmeticExtension(
Context, BO_Add, PExp, IExp); Context, BO_Add, PExp, IExp);
@ -9254,10 +9268,11 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS,
if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context, if (LHS.get()->IgnoreParenCasts()->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNotNull)) { Expr::NPC_ValueDependentIsNotNull)) {
// In C++ adding zero to a null pointer is defined. // In C++ adding zero to a null pointer is defined.
llvm::APSInt KnownVal; Expr::EvalResult KnownVal;
if (!getLangOpts().CPlusPlus || if (!getLangOpts().CPlusPlus ||
(!RHS.get()->isValueDependent() && (!RHS.get()->isValueDependent() &&
(!RHS.get()->EvaluateAsInt(KnownVal, Context) || KnownVal != 0))) { (!RHS.get()->EvaluateAsInt(KnownVal, Context) ||
KnownVal.Val.getInt() != 0))) {
diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false); diagnoseArithmeticOnNullPointer(*this, Loc, LHS.get(), false);
} }
} }
@ -9333,11 +9348,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
if (S.getLangOpts().OpenCL) if (S.getLangOpts().OpenCL)
return; return;
llvm::APSInt Right;
// Check right/shifter operand // Check right/shifter operand
Expr::EvalResult RHSResult;
if (RHS.get()->isValueDependent() || if (RHS.get()->isValueDependent() ||
!RHS.get()->EvaluateAsInt(Right, S.Context)) !RHS.get()->EvaluateAsInt(RHSResult, S.Context))
return; return;
llvm::APSInt Right = RHSResult.Val.getInt();
if (Right.isNegative()) { if (Right.isNegative()) {
S.DiagRuntimeBehavior(Loc, RHS.get(), S.DiagRuntimeBehavior(Loc, RHS.get(),
@ -9360,11 +9376,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned
// integers have defined behavior modulo one more than the maximum value // integers have defined behavior modulo one more than the maximum value
// representable in the result type, so never warn for those. // representable in the result type, so never warn for those.
llvm::APSInt Left; Expr::EvalResult LHSResult;
if (LHS.get()->isValueDependent() || if (LHS.get()->isValueDependent() ||
LHSType->hasUnsignedIntegerRepresentation() || LHSType->hasUnsignedIntegerRepresentation() ||
!LHS.get()->EvaluateAsInt(Left, S.Context)) !LHS.get()->EvaluateAsInt(LHSResult, S.Context))
return; return;
llvm::APSInt Left = LHSResult.Val.getInt();
// If LHS does not have a signed type and non-negative value // If LHS does not have a signed type and non-negative value
// then, the behavior is undefined. Warn about it. // then, the behavior is undefined. Warn about it.
@ -10734,8 +10751,9 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
// that isn't 0 or 1 (which indicate a potential logical operation that // that isn't 0 or 1 (which indicate a potential logical operation that
// happened to fold to true/false) then warn. // happened to fold to true/false) then warn.
// Parens on the RHS are ignored. // Parens on the RHS are ignored.
llvm::APSInt Result; Expr::EvalResult EVResult;
if (RHS.get()->EvaluateAsInt(Result, Context)) if (RHS.get()->EvaluateAsInt(EVResult, Context)) {
llvm::APSInt Result = EVResult.Val.getInt();
if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() && if ((getLangOpts().Bool && !RHS.get()->getType()->isBooleanType() &&
!RHS.get()->getExprLoc().isMacroID()) || !RHS.get()->getExprLoc().isMacroID()) ||
(Result != 0 && Result != 1)) { (Result != 0 && Result != 1)) {
@ -10755,6 +10773,7 @@ inline QualType Sema::CheckLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()), SourceRange(getLocForEndOfToken(LHS.get()->getEndLoc()),
RHS.get()->getEndLoc())); RHS.get()->getEndLoc()));
} }
}
} }
if (!Context.getLangOpts().CPlusPlus) { if (!Context.getLangOpts().CPlusPlus) {
@ -14170,12 +14189,15 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
return ExprError(); return ExprError();
} }
if (!isa<ConstantExpr>(E))
E = ConstantExpr::Create(Context, E);
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice // Circumvent ICE checking in C++11 to avoid evaluating the expression twice
// in the non-ICE case. // in the non-ICE case.
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) { if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
if (Result) if (Result)
*Result = E->EvaluateKnownConstIntCheckOverflow(Context); *Result = E->EvaluateKnownConstIntCheckOverflow(Context);
return new (Context) ConstantExpr(E); return E;
} }
Expr::EvalResult EvalResult; Expr::EvalResult EvalResult;
@ -14193,7 +14215,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) { if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) {
if (Result) if (Result)
*Result = EvalResult.Val.getInt(); *Result = EvalResult.Val.getInt();
return new (Context) ConstantExpr(E); return E;
} }
// If our only note is the usual "invalid subexpression" note, just point // If our only note is the usual "invalid subexpression" note, just point
@ -14221,7 +14243,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
if (Result) if (Result)
*Result = EvalResult.Val.getInt(); *Result = EvalResult.Val.getInt();
return new (Context) ConstantExpr(E); return E;
} }
namespace { namespace {

View File

@ -8050,8 +8050,9 @@ ExprResult InitializationSequence::Perform(Sema &S,
break; break;
} }
llvm::APSInt Result; Expr::EvalResult EVResult;
Init->EvaluateAsInt(Result, S.Context); Init->EvaluateAsInt(EVResult, S.Context);
llvm::APSInt Result = EVResult.Val.getInt();
const uint64_t SamplerValue = Result.getLimitedValue(); const uint64_t SamplerValue = Result.getLimitedValue();
// 32-bit value of sampler's initializer is interpreted as // 32-bit value of sampler's initializer is interpreted as
// bit-field with the following structure: // bit-field with the following structure:

View File

@ -5048,15 +5048,16 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
unsigned NestedLoopCount = 1; unsigned NestedLoopCount = 1;
if (CollapseLoopCountExpr) { if (CollapseLoopCountExpr) {
// Found 'collapse' clause - calculate collapse number. // Found 'collapse' clause - calculate collapse number.
llvm::APSInt Result; Expr::EvalResult Result;
if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) if (CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext()))
NestedLoopCount = Result.getLimitedValue(); NestedLoopCount = Result.Val.getInt().getLimitedValue();
} }
unsigned OrderedLoopCount = 1; unsigned OrderedLoopCount = 1;
if (OrderedLoopCountExpr) { if (OrderedLoopCountExpr) {
// Found 'ordered' clause - calculate collapse number. // Found 'ordered' clause - calculate collapse number.
llvm::APSInt Result; Expr::EvalResult EVResult;
if (OrderedLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) { if (OrderedLoopCountExpr->EvaluateAsInt(EVResult, SemaRef.getASTContext())) {
llvm::APSInt Result = EVResult.Val.getInt();
if (Result.getLimitedValue() < NestedLoopCount) { if (Result.getLimitedValue() < NestedLoopCount) {
SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(), SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
diag::err_omp_wrong_ordered_loop_count) diag::err_omp_wrong_ordered_loop_count)
@ -5652,7 +5653,6 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
} }
if (Simdlen && Safelen) { if (Simdlen && Safelen) {
llvm::APSInt SimdlenRes, SafelenRes;
const Expr *SimdlenLength = Simdlen->getSimdlen(); const Expr *SimdlenLength = Simdlen->getSimdlen();
const Expr *SafelenLength = Safelen->getSafelen(); const Expr *SafelenLength = Safelen->getSafelen();
if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() || if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
@ -5663,8 +5663,11 @@ static bool checkSimdlenSafelenSpecified(Sema &S,
SafelenLength->isInstantiationDependent() || SafelenLength->isInstantiationDependent() ||
SafelenLength->containsUnexpandedParameterPack()) SafelenLength->containsUnexpandedParameterPack())
return false; return false;
SimdlenLength->EvaluateAsInt(SimdlenRes, S.Context); Expr::EvalResult SimdlenResult, SafelenResult;
SafelenLength->EvaluateAsInt(SafelenRes, S.Context); SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
// OpenMP 4.5 [2.8.1, simd Construct, Restrictions] // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
// If both simdlen and safelen clauses are specified, the value of the // If both simdlen and safelen clauses are specified, the value of the
// simdlen parameter must be less than or equal to the value of the safelen // simdlen parameter must be less than or equal to the value of the safelen
@ -10669,10 +10672,11 @@ static bool checkOMPArraySectionConstantForReduction(
SingleElement = true; SingleElement = true;
ArraySizes.push_back(llvm::APSInt::get(1)); ArraySizes.push_back(llvm::APSInt::get(1));
} else { } else {
llvm::APSInt ConstantLengthValue; Expr::EvalResult Result;
if (!Length->EvaluateAsInt(ConstantLengthValue, Context)) if (!Length->EvaluateAsInt(Result, Context))
return false; return false;
llvm::APSInt ConstantLengthValue = Result.Val.getInt();
SingleElement = (ConstantLengthValue.getSExtValue() == 1); SingleElement = (ConstantLengthValue.getSExtValue() == 1);
ArraySizes.push_back(ConstantLengthValue); ArraySizes.push_back(ConstantLengthValue);
} }
@ -10693,9 +10697,12 @@ static bool checkOMPArraySectionConstantForReduction(
// This is an array subscript which has implicit length 1! // This is an array subscript which has implicit length 1!
ArraySizes.push_back(llvm::APSInt::get(1)); ArraySizes.push_back(llvm::APSInt::get(1));
} else { } else {
llvm::APSInt ConstantLengthValue; Expr::EvalResult Result;
if (!Length->EvaluateAsInt(ConstantLengthValue, Context) || if (!Length->EvaluateAsInt(Result, Context))
ConstantLengthValue.getSExtValue() != 1) return false;
llvm::APSInt ConstantLengthValue = Result.Val.getInt();
if (ConstantLengthValue.getSExtValue() != 1)
return false; return false;
ArraySizes.push_back(ConstantLengthValue); ArraySizes.push_back(ConstantLengthValue);
@ -12218,9 +12225,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
// If there is a lower bound that does not evaluates to zero, we are not // If there is a lower bound that does not evaluates to zero, we are not
// covering the whole dimension. // covering the whole dimension.
if (LowerBound) { if (LowerBound) {
llvm::APSInt ConstLowerBound; Expr::EvalResult Result;
if (!LowerBound->EvaluateAsInt(ConstLowerBound, SemaRef.getASTContext())) if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant. return false; // Can't get the integer value as a constant.
llvm::APSInt ConstLowerBound = Result.Val.getInt();
if (ConstLowerBound.getSExtValue()) if (ConstLowerBound.getSExtValue())
return true; return true;
} }
@ -12240,10 +12249,11 @@ static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef,
if (!CATy) if (!CATy)
return false; return false;
llvm::APSInt ConstLength; Expr::EvalResult Result;
if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant. return false; // Can't get the integer value as a constant.
llvm::APSInt ConstLength = Result.Val.getInt();
return CATy->getSize().getSExtValue() != ConstLength.getSExtValue(); return CATy->getSize().getSExtValue() != ConstLength.getSExtValue();
} }
@ -12274,10 +12284,11 @@ static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef,
} }
// Check if the length evaluates to 1. // Check if the length evaluates to 1.
llvm::APSInt ConstLength; Expr::EvalResult Result;
if (!Length->EvaluateAsInt(ConstLength, SemaRef.getASTContext())) if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
return false; // Can't get the integer value as a constant. return false; // Can't get the integer value as a constant.
llvm::APSInt ConstLength = Result.Val.getInt();
return ConstLength.getSExtValue() != 1; return ConstLength.getSExtValue() != 1;
} }

View File

@ -5469,7 +5469,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
if (Notes.empty()) { if (Notes.empty()) {
// It's a constant expression. // It's a constant expression.
return new (S.Context) ConstantExpr(Result.get()); return ConstantExpr::Create(S.Context, Result.get());
} }
} }

View File

@ -945,8 +945,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
llvm::APSInt ConstantCondValue; llvm::APSInt ConstantCondValue;
bool HasConstantCond = false; bool HasConstantCond = false;
if (!HasDependentValue && !TheDefaultStmt) { if (!HasDependentValue && !TheDefaultStmt) {
HasConstantCond = CondExpr->EvaluateAsInt(ConstantCondValue, Context, Expr::EvalResult Result;
HasConstantCond = CondExpr->EvaluateAsInt(Result, Context,
Expr::SE_AllowSideEffects); Expr::SE_AllowSideEffects);
if (Result.Val.isInt())
ConstantCondValue = Result.Val.getInt();
assert(!HasConstantCond || assert(!HasConstantCond ||
(ConstantCondValue.getBitWidth() == CondWidth && (ConstantCondValue.getBitWidth() == CondWidth &&
ConstantCondValue.isSigned() == CondIsSigned)); ConstantCondValue.isSigned() == CondIsSigned));

View File

@ -378,11 +378,12 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
<< InputExpr->getSourceRange()); << InputExpr->getSourceRange());
} else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
if (!InputExpr->isValueDependent()) { if (!InputExpr->isValueDependent()) {
llvm::APSInt Result; Expr::EvalResult EVResult;
if (!InputExpr->EvaluateAsInt(Result, Context)) if (!InputExpr->EvaluateAsInt(EVResult, Context))
return StmtError( return StmtError(
Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
<< Info.getConstraintStr() << InputExpr->getSourceRange()); << Info.getConstraintStr() << InputExpr->getSourceRange());
llvm::APSInt Result = EVResult.Val.getInt();
if (!Info.isValidAsmImmediate(Result)) if (!Info.isValidAsmImmediate(Result))
return StmtError(Diag(InputExpr->getBeginLoc(), return StmtError(Diag(InputExpr->getBeginLoc(),
diag::err_invalid_asm_value_for_constraint) diag::err_invalid_asm_value_for_constraint)

View File

@ -178,6 +178,8 @@ getDeducedParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) {
while (true) { while (true) {
if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E)) if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
E = IC->getSubExpr(); E = IC->getSubExpr();
else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
E = CE->getSubExpr();
else if (SubstNonTypeTemplateParmExpr *Subst = else if (SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E)) dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement(); E = Subst->getReplacement();
@ -5225,6 +5227,8 @@ MarkUsedTemplateParameters(ASTContext &Ctx,
while (true) { while (true) {
if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
E = ICE->getSubExpr(); E = ICE->getSubExpr();
else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(E))
E = CE->getSubExpr();
else if (const SubstNonTypeTemplateParmExpr *Subst = else if (const SubstNonTypeTemplateParmExpr *Subst =
dyn_cast<SubstNonTypeTemplateParmExpr>(E)) dyn_cast<SubstNonTypeTemplateParmExpr>(E))
E = Subst->getReplacement(); E = Subst->getReplacement();

View File

@ -2234,10 +2234,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
} }
if (ArraySize && !CurContext->isFunctionOrMethod())
// A file-scoped array must have a constant array size.
ArraySize = new (Context) ConstantExpr(ArraySize);
// OpenCL v1.2 s6.9.d: variable length arrays are not supported. // OpenCL v1.2 s6.9.d: variable length arrays are not supported.
if (getLangOpts().OpenCL && T->isVariableArrayType()) { if (getLangOpts().OpenCL && T->isVariableArrayType()) {
Diag(Loc, diag::err_opencl_vla); Diag(Loc, diag::err_opencl_vla);

View File

@ -101,9 +101,10 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
// This must be resolvable at compile time, so we defer to the constant // This must be resolvable at compile time, so we defer to the constant
// evaluator for a value. // evaluator for a value.
SVal V = UnknownVal(); SVal V = UnknownVal();
llvm::APSInt Result; Expr::EvalResult EVResult;
if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) { if (CE->EvaluateAsInt(EVResult, C.getASTContext(), Expr::SE_NoSideEffects)) {
// Make sure the result has the correct type. // Make sure the result has the correct type.
llvm::APSInt Result = EVResult.Val.getInt();
SValBuilder &SVB = C.getSValBuilder(); SValBuilder &SVB = C.getSValBuilder();
BasicValueFactory &BVF = SVB.getBasicValueFactory(); BasicValueFactory &BVF = SVB.getBasicValueFactory();
BVF.getAPSIntType(CE->getType()).apply(Result); BVF.getAPSIntType(CE->getType()).apply(Result);

View File

@ -597,9 +597,10 @@ void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
unsigned suffix = 0; unsigned suffix = 0;
if (ArgSuffix.second >= 0) { if (ArgSuffix.second >= 0) {
const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second); const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
llvm::APSInt Result; Expr::EvalResult EVResult;
if (!suffixEx->EvaluateAsInt(Result, BR.getContext())) if (!suffixEx->EvaluateAsInt(EVResult, BR.getContext()))
return; return;
llvm::APSInt Result = EVResult.Val.getInt();
// FIXME: Issue a warning. // FIXME: Issue a warning.
if (Result.isNegative()) if (Result.isNegative())
return; return;

View File

@ -135,9 +135,9 @@ private:
bool isIntZeroExpr(const Expr *E) const { bool isIntZeroExpr(const Expr *E) const {
if (!E->getType()->isIntegralOrEnumerationType()) if (!E->getType()->isIntegralOrEnumerationType())
return false; return false;
llvm::APSInt Result; Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, Context)) if (E->EvaluateAsInt(Result, Context))
return Result == 0; return Result.Val.getInt() == 0;
return false; return false;
} }
@ -191,8 +191,11 @@ private:
if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) { if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(rhse)) {
if (BOp->getOpcode() == BO_Div) { if (BOp->getOpcode() == BO_Div) {
const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts(); const Expr *denom = BOp->getRHS()->IgnoreParenImpCasts();
if (denom->EvaluateAsInt(denomVal, Context)) Expr::EvalResult Result;
if (denom->EvaluateAsInt(Result, Context)) {
denomVal = Result.Val.getInt();
denomKnown = true; denomKnown = true;
}
const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts(); const Expr *numerator = BOp->getLHS()->IgnoreParenImpCasts();
if (numerator->isEvaluatable(Context)) if (numerator->isEvaluatable(Context))
numeratorKnown = true; numeratorKnown = true;

View File

@ -87,9 +87,10 @@ void Callback::run(const MatchFinder::MatchResult &Result) {
MacroIndicatesWeShouldSkipTheCheck = true; MacroIndicatesWeShouldSkipTheCheck = true;
} }
if (!MacroIndicatesWeShouldSkipTheCheck) { if (!MacroIndicatesWeShouldSkipTheCheck) {
llvm::APSInt Result; Expr::EvalResult EVResult;
if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt( if (CheckIfNull->IgnoreParenCasts()->EvaluateAsInt(
Result, ACtx, Expr::SE_AllowSideEffects)) { EVResult, ACtx, Expr::SE_AllowSideEffects)) {
llvm::APSInt Result = EVResult.Val.getInt();
if (Result == 0) { if (Result == 0) {
if (!C->Pedantic) if (!C->Pedantic)
return; return;

View File

@ -1274,9 +1274,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
break; break;
case Expr::ConstantExprClass: case Expr::ConstantExprClass:
// Handled due to it being a wrapper class.
break;
case Stmt::ExprWithCleanupsClass: case Stmt::ExprWithCleanupsClass:
// Handled due to fully linearised CFG. // Handled due to fully linearised CFG.
break; break;

View File

@ -810,8 +810,9 @@ void ExprEngine::
VisitOffsetOfExpr(const OffsetOfExpr *OOE, VisitOffsetOfExpr(const OffsetOfExpr *OOE,
ExplodedNode *Pred, ExplodedNodeSet &Dst) { ExplodedNode *Pred, ExplodedNodeSet &Dst) {
StmtNodeBuilder B(Pred, Dst, *currBldrCtx); StmtNodeBuilder B(Pred, Dst, *currBldrCtx);
APSInt IV; Expr::EvalResult Result;
if (OOE->EvaluateAsInt(IV, getContext())) { if (OOE->EvaluateAsInt(Result, getContext())) {
APSInt IV = Result.Val.getInt();
assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
assert(OOE->getType()->isBuiltinType()); assert(OOE->getType()->isBuiltinType());
assert(OOE->getType()->getAs<BuiltinType>()->isInteger()); assert(OOE->getType()->getAs<BuiltinType>()->isInteger());

View File

@ -362,9 +362,9 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
return None; return None;
ASTContext &Ctx = getContext(); ASTContext &Ctx = getContext();
llvm::APSInt Result; Expr::EvalResult Result;
if (E->EvaluateAsInt(Result, Ctx)) if (E->EvaluateAsInt(Result, Ctx))
return makeIntVal(Result); return makeIntVal(Result.Val.getInt());
if (Loc::isLocType(E->getType())) if (Loc::isLocType(E->getType()))
if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))

View File

@ -0,0 +1,24 @@
// RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - %s
// Don't crash if the argument to __builtin_constant_p isn't scalar.
template <typename T>
constexpr bool is_constant(const T v) {
return __builtin_constant_p(v);
}
template <typename T>
class numeric {
public:
using type = T;
template <typename S>
constexpr numeric(S value)
: value_(static_cast<T>(value)) {}
private:
const T value_;
};
bool bcp() {
return is_constant(numeric<int>(1));
}

View File

@ -122,6 +122,14 @@ int test16() {
__builtin_constant_p(1, 2); // expected-error {{too many arguments}} __builtin_constant_p(1, 2); // expected-error {{too many arguments}}
} }
// __builtin_constant_p cannot resolve non-constants as a file scoped array.
int expr;
char y[__builtin_constant_p(expr) ? -1 : 1]; // no warning, the builtin is false.
// no warning, the builtin is false.
struct foo { int a; };
struct foo x = (struct foo) { __builtin_constant_p(42) ? 37 : 927 };
const int test17_n = 0; const int test17_n = 0;
const char test17_c[] = {1, 2, 3, 0}; const char test17_c[] = {1, 2, 3, 0};
const char test17_d[] = {1, 2, 3, 4}; const char test17_d[] = {1, 2, 3, 4};
@ -161,6 +169,7 @@ void test17() {
F(&test17_d); F(&test17_d);
F((struct Aggregate){0, 1}); F((struct Aggregate){0, 1});
F((IntVector){0, 1, 2, 3}); F((IntVector){0, 1, 2, 3});
F(test17);
// Ensure that a technique used in glibc is handled correctly. // Ensure that a technique used in glibc is handled correctly.
#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4) #define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4)

View File

@ -36,10 +36,11 @@ namespace brace_initializers {
POD p = (POD){1, 2}; POD p = (POD){1, 2};
// CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD' // CHECK-NOT: CXXBindTemporaryExpr {{.*}} 'brace_initializers::POD'
// CHECK: ConstantExpr {{.*}} 'brace_initializers::POD' // CHECK: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: CompoundLiteralExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD' // CHECK-NEXT: InitListExpr {{.*}} 'brace_initializers::POD'
// CHECK-NEXT: ConstantExpr {{.*}}
// CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}} // CHECK-NEXT: IntegerLiteral {{.*}} 1{{$}}
// CHECK-NEXT: ConstantExpr {{.*}}
// CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}} // CHECK-NEXT: IntegerLiteral {{.*}} 2{{$}}
void test() { void test() {