aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp472
1 files changed, 303 insertions, 169 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 4cac4fab8476..7d7ca9924c85 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -320,7 +320,7 @@ namespace {
APValue *getTemporary(const void *Key) {
MapTy::iterator I = Temporaries.find(Key);
- return I == Temporaries.end() ? 0 : &I->second;
+ return I == Temporaries.end() ? nullptr : &I->second;
}
APValue &createTemporary(const void *Key, bool IsLifetimeExtended);
};
@@ -347,7 +347,8 @@ namespace {
PartialDiagnostic *Diag;
public:
- explicit OptionalDiagnostic(PartialDiagnostic *Diag = 0) : Diag(Diag) {}
+ explicit OptionalDiagnostic(PartialDiagnostic *Diag = nullptr)
+ : Diag(Diag) {}
template<typename T>
OptionalDiagnostic &operator<<(const T &v) {
@@ -474,13 +475,30 @@ namespace {
/// Evaluate in any way we know how. Don't worry about side-effects that
/// can't be modeled.
- EM_IgnoreSideEffects
+ EM_IgnoreSideEffects,
+
+ /// Evaluate as a constant expression. Stop if we find that the expression
+ /// is not a constant expression. Some expressions can be retried in the
+ /// optimizer if we don't constant fold them here, but in an unevaluated
+ /// context we try to fold them immediately since the optimizer never
+ /// gets a chance to look at it.
+ EM_ConstantExpressionUnevaluated,
+
+ /// Evaluate as a potential constant expression. Keep going if we hit a
+ /// construct that we can't evaluate yet (because we don't yet know the
+ /// value of something) but stop if we hit something that could never be
+ /// a constant expression. Some expressions can be retried in the
+ /// optimizer if we don't constant fold them here, but in an unevaluated
+ /// context we try to fold them immediately since the optimizer never
+ /// gets a chance to look at it.
+ EM_PotentialConstantExpressionUnevaluated
} EvalMode;
/// Are we checking whether the expression is a potential constant
/// expression?
bool checkingPotentialConstantExpression() const {
- return EvalMode == EM_PotentialConstantExpression;
+ return EvalMode == EM_PotentialConstantExpression ||
+ EvalMode == EM_PotentialConstantExpressionUnevaluated;
}
/// Are we checking an expression for overflow?
@@ -489,12 +507,13 @@ namespace {
bool checkingForOverflow() { return EvalMode == EM_EvaluateForOverflow; }
EvalInfo(const ASTContext &C, Expr::EvalStatus &S, EvaluationMode Mode)
- : Ctx(const_cast<ASTContext&>(C)), EvalStatus(S), CurrentCall(0),
+ : Ctx(const_cast<ASTContext &>(C)), EvalStatus(S), CurrentCall(nullptr),
CallStackDepth(0), NextCallIndex(1),
StepsLeft(getLangOpts().ConstexprStepLimit),
- BottomFrame(*this, SourceLocation(), 0, 0, 0),
- EvaluatingDecl((const ValueDecl*)0), EvaluatingDeclValue(0),
- HasActiveDiagnostic(false), EvalMode(Mode) {}
+ BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
+ EvaluatingDecl((const ValueDecl *)nullptr),
+ EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
+ EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -527,7 +546,7 @@ namespace {
CallStackFrame *Frame = CurrentCall;
while (Frame->Index > CallIndex)
Frame = Frame->Caller;
- return (Frame->Index == CallIndex) ? Frame : 0;
+ return (Frame->Index == CallIndex) ? Frame : nullptr;
}
bool nextStep(const Stmt *S) {
@@ -573,6 +592,8 @@ namespace {
// some later problem.
case EM_ConstantExpression:
case EM_PotentialConstantExpression:
+ case EM_ConstantExpressionUnevaluated:
+ case EM_PotentialConstantExpressionUnevaluated:
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -644,11 +665,13 @@ namespace {
bool keepEvaluatingAfterSideEffect() {
switch (EvalMode) {
case EM_PotentialConstantExpression:
+ case EM_PotentialConstantExpressionUnevaluated:
case EM_EvaluateForOverflow:
case EM_IgnoreSideEffects:
return true;
case EM_ConstantExpression:
+ case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
return false;
}
@@ -670,10 +693,12 @@ namespace {
switch (EvalMode) {
case EM_PotentialConstantExpression:
+ case EM_PotentialConstantExpressionUnevaluated:
case EM_EvaluateForOverflow:
return true;
case EM_ConstantExpression:
+ case EM_ConstantExpressionUnevaluated:
case EM_ConstantFold:
case EM_IgnoreSideEffects:
return false;
@@ -696,7 +721,9 @@ namespace {
Info.EvalStatus.Diag->empty() &&
!Info.EvalStatus.HasSideEffects),
OldMode(Info.EvalMode) {
- if (Enabled && Info.EvalMode == EvalInfo::EM_ConstantExpression)
+ if (Enabled &&
+ (Info.EvalMode == EvalInfo::EM_ConstantExpression ||
+ Info.EvalMode == EvalInfo::EM_ConstantExpressionUnevaluated))
Info.EvalMode = EvalInfo::EM_ConstantFold;
}
void keepDiagnostics() { Enabled = false; }
@@ -716,7 +743,7 @@ namespace {
public:
SpeculativeEvaluationRAII(EvalInfo &Info,
- SmallVectorImpl<PartialDiagnosticAt> *NewDiag = 0)
+ SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
: Info(Info), Old(Info.EvalStatus) {
Info.EvalStatus.Diag = NewDiag;
// If we're speculatively evaluating, we may have skipped over some
@@ -943,7 +970,7 @@ namespace {
// any object: we won't use such a designator for anything.
if (!Info.getLangOpts().CPlusPlus11)
Designator.setInvalid();
- return checkNullPointer(Info, E, CSK) &&
+ return (CSK == CSK_ArrayToPointer || checkNullPointer(Info, E, CSK)) &&
Designator.checkSubobject(Info, E, CSK);
}
@@ -961,7 +988,7 @@ namespace {
Designator.addComplexUnchecked(EltTy, Imag);
}
void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) {
- if (checkNullPointer(Info, E, CSK_ArrayIndex))
+ if (N && checkNullPointer(Info, E, CSK_ArrayIndex))
Designator.adjustIndex(Info, E, N);
}
};
@@ -1141,7 +1168,7 @@ static int64_t getExtValue(const APSInt &Value) {
/// Should this call expression be treated as a string literal?
static bool IsStringLiteralCall(const CallExpr *E) {
- unsigned Builtin = E->isBuiltinCall();
+ unsigned Builtin = E->getBuiltinCallee();
return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
Builtin == Builtin::BI__builtin___NSStringMakeConstantString);
}
@@ -1242,11 +1269,29 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
LVal.getLValueCallIndex() == 0) &&
"have call index for global lvalue");
- // Check if this is a thread-local variable.
if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) {
if (const VarDecl *Var = dyn_cast<const VarDecl>(VD)) {
+ // Check if this is a thread-local variable.
if (Var->getTLSKind())
return false;
+
+ // A dllimport variable never acts like a constant.
+ if (Var->hasAttr<DLLImportAttr>())
+ return false;
+ }
+ if (const auto *FD = dyn_cast<const FunctionDecl>(VD)) {
+ // __declspec(dllimport) must be handled very carefully:
+ // We must never initialize an expression with the thunk in C++.
+ // Doing otherwise would allow the same id-expression to yield
+ // different addresses for the same function in different translation
+ // units. However, this means that we must dynamically initialize the
+ // expression with the contents of the import address table at runtime.
+ //
+ // The C language has no notion of ODR; furthermore, it has no notion of
+ // dynamic initialization. This means that we are permitted to
+ // perform initialization with the address of the thunk.
+ if (Info.getLangOpts().CPlusPlus && FD->hasAttr<DLLImportAttr>())
+ return false;
}
}
@@ -1276,7 +1321,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
/// Check that this core constant expression is of literal type, and if not,
/// produce an appropriate diagnostic.
static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
- const LValue *This = 0) {
+ const LValue *This = nullptr) {
if (!E->isRValue() || E->getType()->isLiteralType(Info.Ctx))
return true;
@@ -1307,6 +1352,11 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
return false;
}
+ // We allow _Atomic(T) to be initialized from anything that T can be
+ // initialized from.
+ if (const AtomicType *AT = Type->getAs<AtomicType>())
+ Type = AT->getValueType();
+
// Core issue 1454: For a literal constant expression of array or class type,
// each subobject of its value shall have been initialized by a constant
// expression.
@@ -1338,8 +1388,7 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
return false;
}
}
- for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
- I != E; ++I) {
+ for (const auto *I : RD->fields()) {
if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
Value.getStructField(I->getFieldIndex())))
return false;
@@ -1738,7 +1787,7 @@ static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result,
static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
- const ASTRecordLayout *RL = 0) {
+ const ASTRecordLayout *RL = nullptr) {
if (!RL) {
if (Derived->isInvalidDecl()) return false;
RL = &Info.Ctx.getASTRecordLayout(Derived);
@@ -1791,7 +1840,7 @@ static bool HandleLValueBasePath(EvalInfo &Info, const CastExpr *E,
/// currently described by LVal.
static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
const FieldDecl *FD,
- const ASTRecordLayout *RL = 0) {
+ const ASTRecordLayout *RL = nullptr) {
if (!RL) {
if (FD->getParent()->isInvalidDecl()) return false;
RL = &Info.Ctx.getASTRecordLayout(FD->getParent());
@@ -1807,9 +1856,8 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
static bool HandleLValueIndirectMember(EvalInfo &Info, const Expr *E,
LValue &LVal,
const IndirectFieldDecl *IFD) {
- for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(),
- CE = IFD->chain_end(); C != CE; ++C)
- if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(*C)))
+ for (const auto *C : IFD->chain())
+ if (!HandleLValueMember(Info, E, LVal, cast<FieldDecl>(C)))
return false;
return true;
}
@@ -2047,7 +2095,7 @@ struct CompleteObject {
/// The type of the complete object.
QualType Type;
- CompleteObject() : Value(0) {}
+ CompleteObject() : Value(nullptr) {}
CompleteObject(APValue *Value, QualType Type)
: Value(Value), Type(Type) {
assert(Value && "missing value for complete object");
@@ -2075,7 +2123,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
APValue *O = Obj.Value;
QualType ObjType = Obj.Type;
- const FieldDecl *LastField = 0;
+ const FieldDecl *LastField = nullptr;
// Walk the designator's path to find the subobject.
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
@@ -2098,7 +2146,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
return true;
}
- LastField = 0;
+ LastField = nullptr;
if (ObjType->isArrayType()) {
// Next subobject is an array element.
const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType);
@@ -2381,7 +2429,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
return CompleteObject();
}
- CallStackFrame *Frame = 0;
+ CallStackFrame *Frame = nullptr;
if (LVal.CallIndex) {
Frame = Info.getCallFrame(LVal.CallIndex);
if (!Frame) {
@@ -2406,7 +2454,7 @@ CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, AccessKinds AK,
}
// Compute value storage location and type of base object.
- APValue *BaseVal = 0;
+ APValue *BaseVal = nullptr;
QualType BaseType = getType(LVal.Base);
if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
@@ -2776,7 +2824,7 @@ struct IncDecSubobjectHandler {
// if we're post-incrementing a complex.
if (Old) {
*Old = Subobj;
- Old = 0;
+ Old = nullptr;
}
switch (Subobj.getKind()) {
@@ -2913,6 +2961,7 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object,
if (Object->getType()->isLiteralType(Info.Ctx))
return EvaluateTemporary(Object, This, Info);
+ Info.Diag(Object, diag::note_constexpr_nonliteral) << Object->getType();
return false;
}
@@ -2934,14 +2983,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
bool IncludeMember = true) {
MemberPtr MemPtr;
if (!EvaluateMemberPointer(RHS, MemPtr, Info))
- return 0;
+ return nullptr;
// C++11 [expr.mptr.oper]p6: If the second operand is the null pointer to
// member value, the behavior is undefined.
if (!MemPtr.getDecl()) {
// FIXME: Specific diagnostic.
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
if (MemPtr.isDerivedMember()) {
@@ -2951,7 +3000,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() >
LV.Designator.Entries.size()) {
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
unsigned PathLengthToMember =
LV.Designator.Entries.size() - MemPtr.Path.size();
@@ -2961,14 +3010,14 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
const CXXRecordDecl *MPDecl = MemPtr.Path[I];
if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) {
Info.Diag(RHS);
- return 0;
+ return nullptr;
}
}
// Truncate the lvalue to the appropriate derived class.
if (!CastToDerivedClass(Info, RHS, LV, MemPtr.getContainingRecord(),
PathLengthToMember))
- return 0;
+ return nullptr;
} else if (!MemPtr.Path.empty()) {
// Extend the LValue path with the member pointer's path.
LV.Designator.Entries.reserve(LV.Designator.Entries.size() +
@@ -2983,24 +3032,24 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
for (unsigned I = 1, N = MemPtr.Path.size(); I != N; ++I) {
const CXXRecordDecl *Base = MemPtr.Path[N - I - 1];
if (!HandleLValueDirectBase(Info, RHS, LV, RD, Base))
- return 0;
+ return nullptr;
RD = Base;
}
// Finally cast to the class containing the member.
if (!HandleLValueDirectBase(Info, RHS, LV, RD,
MemPtr.getContainingRecord()))
- return 0;
+ return nullptr;
}
// Add the member. Note that we cannot build bound member functions here.
if (IncludeMember) {
if (const FieldDecl *FD = dyn_cast<FieldDecl>(MemPtr.getDecl())) {
if (!HandleLValueMember(Info, RHS, LV, FD))
- return 0;
+ return nullptr;
} else if (const IndirectFieldDecl *IFD =
dyn_cast<IndirectFieldDecl>(MemPtr.getDecl())) {
if (!HandleLValueIndirectMember(Info, RHS, LV, IFD))
- return 0;
+ return nullptr;
} else {
llvm_unreachable("can't construct reference to bound member function");
}
@@ -3020,7 +3069,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
MemberPtr MemPtr;
EvaluateMemberPointer(BO->getRHS(), MemPtr, Info);
}
- return 0;
+ return nullptr;
}
return HandleMemberPointerAccess(Info, BO->getLHS()->getType(), LV,
@@ -3092,14 +3141,18 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
Result.set(VD, Info.CurrentCall->Index);
APValue &Val = Info.CurrentCall->createTemporary(VD, true);
- if (!VD->getInit()) {
+ const Expr *InitE = VD->getInit();
+ if (!InitE) {
Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized)
<< false << VD->getType();
Val = APValue();
return false;
}
- if (!EvaluateInPlace(Val, Info, Result, VD->getInit())) {
+ if (InitE->isValueDependent())
+ return false;
+
+ if (!EvaluateInPlace(Val, Info, Result, InitE)) {
// Wipe out any partially-computed value, to allow tracking that this
// evaluation failed.
Val = APValue();
@@ -3120,12 +3173,13 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
}
static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
- const Stmt *S, const SwitchCase *SC = 0);
+ const Stmt *S,
+ const SwitchCase *SC = nullptr);
/// Evaluate the body of a loop, and translate the result as appropriate.
static EvalStmtResult EvaluateLoopBody(APValue &Result, EvalInfo &Info,
const Stmt *Body,
- const SwitchCase *Case = 0) {
+ const SwitchCase *Case = nullptr) {
BlockScopeRAII Scope(Info);
switch (EvalStmtResult ESR = EvaluateStmt(Result, Info, Body, Case)) {
case ESR_Break:
@@ -3159,7 +3213,7 @@ static EvalStmtResult EvaluateSwitch(APValue &Result, EvalInfo &Info,
// Find the switch case corresponding to the value of the condition.
// FIXME: Cache this lookup.
- const SwitchCase *Found = 0;
+ const SwitchCase *Found = nullptr;
for (const SwitchCase *SC = SS->getSwitchCaseList(); SC;
SC = SC->getNextSwitchCase()) {
if (isa<DefaultStmt>(SC)) {
@@ -3224,7 +3278,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
if (Case == S)
- Case = 0;
+ Case = nullptr;
break;
case Stmt::IfStmtClass: {
@@ -3291,13 +3345,12 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
case Stmt::DeclStmtClass: {
const DeclStmt *DS = cast<DeclStmt>(S);
- for (DeclStmt::const_decl_iterator DclIt = DS->decl_begin(),
- DclEnd = DS->decl_end(); DclIt != DclEnd; ++DclIt) {
+ for (const auto *DclIt : DS->decls()) {
// Each declaration initialization is its own full-expression.
// FIXME: This isn't quite right; if we're performing aggregate
// initialization, each braced subexpression is its own full-expression.
FullExpressionRAII Scope(Info);
- if (!EvaluateDecl(Info, *DclIt) && !Info.keepEvaluatingAfterFailure())
+ if (!EvaluateDecl(Info, DclIt) && !Info.keepEvaluatingAfterFailure())
return ESR_Failed;
}
return ESR_Succeeded;
@@ -3315,11 +3368,10 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
BlockScopeRAII Scope(Info);
const CompoundStmt *CS = cast<CompoundStmt>(S);
- for (CompoundStmt::const_body_iterator BI = CS->body_begin(),
- BE = CS->body_end(); BI != BE; ++BI) {
- EvalStmtResult ESR = EvaluateStmt(Result, Info, *BI, Case);
+ for (const auto *BI : CS->body()) {
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, BI, Case);
if (ESR == ESR_Succeeded)
- Case = 0;
+ Case = nullptr;
else if (ESR != ESR_CaseNotFound)
return ESR;
}
@@ -3368,7 +3420,7 @@ static EvalStmtResult EvaluateStmt(APValue &Result, EvalInfo &Info,
EvalStmtResult ESR = EvaluateLoopBody(Result, Info, DS->getBody(), Case);
if (ESR != ESR_Continue)
return ESR;
- Case = 0;
+ Case = nullptr;
FullExpressionRAII CondScope(Info);
if (!EvaluateAsBooleanCondition(DS->getCond(), Continue, Info))
@@ -3593,7 +3645,7 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
EvalStmtResult ESR = EvaluateStmt(Result, Info, Body);
if (ESR == ESR_Succeeded) {
- if (Callee->getResultType()->isVoidType())
+ if (Callee->getReturnType()->isVoidType())
return true;
Info.Diag(Callee->getLocEnd(), diag::note_constexpr_no_return);
}
@@ -3659,15 +3711,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
#ifndef NDEBUG
CXXRecordDecl::base_class_const_iterator BaseIt = RD->bases_begin();
#endif
- for (CXXConstructorDecl::init_const_iterator I = Definition->init_begin(),
- E = Definition->init_end(); I != E; ++I) {
+ for (const auto *I : Definition->inits()) {
LValue Subobject = This;
APValue *Value = &Result;
// Determine the subobject to initialize.
- FieldDecl *FD = 0;
- if ((*I)->isBaseInitializer()) {
- QualType BaseType((*I)->getBaseClass(), 0);
+ FieldDecl *FD = nullptr;
+ if (I->isBaseInitializer()) {
+ QualType BaseType(I->getBaseClass(), 0);
#ifndef NDEBUG
// Non-virtual base classes are initialized in the order in the class
// definition. We have already checked for virtual base classes.
@@ -3676,12 +3727,12 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
"base class initializers not in expected order");
++BaseIt;
#endif
- if (!HandleLValueDirectBase(Info, (*I)->getInit(), Subobject, RD,
+ if (!HandleLValueDirectBase(Info, I->getInit(), Subobject, RD,
BaseType->getAsCXXRecordDecl(), &Layout))
return false;
Value = &Result.getStructBase(BasesSeen++);
- } else if ((FD = (*I)->getMember())) {
- if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD, &Layout))
+ } else if ((FD = I->getMember())) {
+ if (!HandleLValueMember(Info, I->getInit(), Subobject, FD, &Layout))
return false;
if (RD->isUnion()) {
Result = APValue(FD);
@@ -3689,13 +3740,11 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
} else {
Value = &Result.getStructField(FD->getFieldIndex());
}
- } else if (IndirectFieldDecl *IFD = (*I)->getIndirectMember()) {
+ } else if (IndirectFieldDecl *IFD = I->getIndirectMember()) {
// Walk the indirect field decl's chain to find the object to initialize,
// and make sure we've initialized every step along it.
- for (IndirectFieldDecl::chain_iterator C = IFD->chain_begin(),
- CE = IFD->chain_end();
- C != CE; ++C) {
- FD = cast<FieldDecl>(*C);
+ for (auto *C : IFD->chain()) {
+ FD = cast<FieldDecl>(C);
CXXRecordDecl *CD = cast<CXXRecordDecl>(FD->getParent());
// Switch the union field if it differs. This happens if we had
// preceding zero-initialization, and we're now initializing a union
@@ -3710,7 +3759,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
*Value = APValue(APValue::UninitStruct(), CD->getNumBases(),
std::distance(CD->field_begin(), CD->field_end()));
}
- if (!HandleLValueMember(Info, (*I)->getInit(), Subobject, FD))
+ if (!HandleLValueMember(Info, I->getInit(), Subobject, FD))
return false;
if (CD->isUnion())
Value = &Value->getUnionValue();
@@ -3722,8 +3771,8 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
}
FullExpressionRAII InitScope(Info);
- if (!EvaluateInPlace(*Value, Info, Subobject, (*I)->getInit()) ||
- (FD && FD->isBitField() && !truncateBitfieldValue(Info, (*I)->getInit(),
+ if (!EvaluateInPlace(*Value, Info, Subobject, I->getInit()) ||
+ (FD && FD->isBitField() && !truncateBitfieldValue(Info, I->getInit(),
*Value, FD))) {
// If we're checking for a potential constant expression, evaluate all
// initializers even if some of them fail.
@@ -3742,15 +3791,14 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
//===----------------------------------------------------------------------===//
namespace {
-// FIXME: RetTy is always bool. Remove it.
-template <class Derived, typename RetTy=bool>
+template <class Derived>
class ExprEvaluatorBase
- : public ConstStmtVisitor<Derived, RetTy> {
+ : public ConstStmtVisitor<Derived, bool> {
private:
- RetTy DerivedSuccess(const APValue &V, const Expr *E) {
+ bool DerivedSuccess(const APValue &V, const Expr *E) {
return static_cast<Derived*>(this)->Success(V, E);
}
- RetTy DerivedZeroInitialization(const Expr *E) {
+ bool DerivedZeroInitialization(const Expr *E) {
return static_cast<Derived*>(this)->ZeroInitialization(E);
}
@@ -3795,14 +3843,14 @@ private:
protected:
EvalInfo &Info;
- typedef ConstStmtVisitor<Derived, RetTy> StmtVisitorTy;
+ typedef ConstStmtVisitor<Derived, bool> StmtVisitorTy;
typedef ExprEvaluatorBase ExprEvaluatorBaseTy;
OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) {
return Info.CCEDiag(E, D);
}
- RetTy ZeroInitialization(const Expr *E) { return Error(E); }
+ bool ZeroInitialization(const Expr *E) { return Error(E); }
public:
ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
@@ -3819,28 +3867,28 @@ public:
return Error(E, diag::note_invalid_subexpr_in_const_expr);
}
- RetTy VisitStmt(const Stmt *) {
+ bool VisitStmt(const Stmt *) {
llvm_unreachable("Expression evaluator should not be called on stmts");
}
- RetTy VisitExpr(const Expr *E) {
+ bool VisitExpr(const Expr *E) {
return Error(E);
}
- RetTy VisitParenExpr(const ParenExpr *E)
+ bool VisitParenExpr(const ParenExpr *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
- RetTy VisitUnaryExtension(const UnaryOperator *E)
+ bool VisitUnaryExtension(const UnaryOperator *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
- RetTy VisitUnaryPlus(const UnaryOperator *E)
+ bool VisitUnaryPlus(const UnaryOperator *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
- RetTy VisitChooseExpr(const ChooseExpr *E)
+ bool VisitChooseExpr(const ChooseExpr *E)
{ return StmtVisitorTy::Visit(E->getChosenSubExpr()); }
- RetTy VisitGenericSelectionExpr(const GenericSelectionExpr *E)
+ bool VisitGenericSelectionExpr(const GenericSelectionExpr *E)
{ return StmtVisitorTy::Visit(E->getResultExpr()); }
- RetTy VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
+ bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
{ return StmtVisitorTy::Visit(E->getReplacement()); }
- RetTy VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
+ bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
{ return StmtVisitorTy::Visit(E->getExpr()); }
- RetTy VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
+ bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
// The initializer may not have been parsed yet, or might be erroneous.
if (!E->getExpr())
return Error(E);
@@ -3848,19 +3896,19 @@ public:
}
// We cannot create any objects for which cleanups are required, so there is
// nothing to do here; all cleanups must come from unevaluated subexpressions.
- RetTy VisitExprWithCleanups(const ExprWithCleanups *E)
+ bool VisitExprWithCleanups(const ExprWithCleanups *E)
{ return StmtVisitorTy::Visit(E->getSubExpr()); }
- RetTy VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) {
+ bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E) {
CCEDiag(E, diag::note_constexpr_invalid_cast) << 0;
return static_cast<Derived*>(this)->VisitCastExpr(E);
}
- RetTy VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
+ bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
CCEDiag(E, diag::note_constexpr_invalid_cast) << 1;
return static_cast<Derived*>(this)->VisitCastExpr(E);
}
- RetTy VisitBinaryOperator(const BinaryOperator *E) {
+ bool VisitBinaryOperator(const BinaryOperator *E) {
switch (E->getOpcode()) {
default:
return Error(E);
@@ -3882,7 +3930,7 @@ public:
}
}
- RetTy VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) {
+ bool VisitBinaryConditionalOperator(const BinaryConditionalOperator *E) {
// Evaluate and cache the common expression. We treat it as a temporary,
// even though it's not quite the same thing.
if (!Evaluate(Info.CurrentCall->createTemporary(E->getOpaqueValue(), false),
@@ -3892,7 +3940,7 @@ public:
return HandleConditionalOperator(E);
}
- RetTy VisitConditionalOperator(const ConditionalOperator *E) {
+ bool VisitConditionalOperator(const ConditionalOperator *E) {
bool IsBcpCall = false;
// If the condition (ignoring parens) is a __builtin_constant_p call,
// the result is a constant expression if it can be folded without
@@ -3900,7 +3948,7 @@ public:
// for discussion.
if (const CallExpr *CallCE =
dyn_cast<CallExpr>(E->getCond()->IgnoreParenCasts()))
- if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p)
+ if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p)
IsBcpCall = true;
// Always assume __builtin_constant_p(...) ? ... : ... is a potential
@@ -3917,7 +3965,7 @@ public:
return true;
}
- RetTy VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
+ bool VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
if (APValue *Value = Info.CurrentCall->getTemporary(E))
return DerivedSuccess(*Value, E);
@@ -3931,18 +3979,18 @@ public:
return StmtVisitorTy::Visit(Source);
}
- RetTy VisitCallExpr(const CallExpr *E) {
+ bool VisitCallExpr(const CallExpr *E) {
const Expr *Callee = E->getCallee()->IgnoreParens();
QualType CalleeType = Callee->getType();
- const FunctionDecl *FD = 0;
- LValue *This = 0, ThisVal;
+ const FunctionDecl *FD = nullptr;
+ LValue *This = nullptr, ThisVal;
ArrayRef<const Expr *> Args(E->getArgs(), E->getNumArgs());
bool HasQualifier = false;
// Extract function decl and 'this' pointer from the callee.
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
- const ValueDecl *Member = 0;
+ const ValueDecl *Member = nullptr;
if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) {
// Explicit bound member calls, such as x.f() or p->g();
if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal))
@@ -4004,7 +4052,7 @@ public:
isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual())
return Error(E, diag::note_constexpr_virtual_call);
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
APValue Result;
@@ -4016,28 +4064,28 @@ public:
return DerivedSuccess(Result, E);
}
- RetTy VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
+ bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
return StmtVisitorTy::Visit(E->getInitializer());
}
- RetTy VisitInitListExpr(const InitListExpr *E) {
+ bool VisitInitListExpr(const InitListExpr *E) {
if (E->getNumInits() == 0)
return DerivedZeroInitialization(E);
if (E->getNumInits() == 1)
return StmtVisitorTy::Visit(E->getInit(0));
return Error(E);
}
- RetTy VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
+ bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
return DerivedZeroInitialization(E);
}
- RetTy VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
+ bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
return DerivedZeroInitialization(E);
}
- RetTy VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
+ bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E) {
return DerivedZeroInitialization(E);
}
/// A member expression where the object is a prvalue is itself a prvalue.
- RetTy VisitMemberExpr(const MemberExpr *E) {
+ bool VisitMemberExpr(const MemberExpr *E) {
assert(!E->isArrow() && "missing call to bound member function?");
APValue Val;
@@ -4061,7 +4109,7 @@ public:
DerivedSuccess(Result, E);
}
- RetTy VisitCastExpr(const CastExpr *E) {
+ bool VisitCastExpr(const CastExpr *E) {
switch (E->getCastKind()) {
default:
break;
@@ -4093,13 +4141,13 @@ public:
return Error(E);
}
- RetTy VisitUnaryPostInc(const UnaryOperator *UO) {
+ bool VisitUnaryPostInc(const UnaryOperator *UO) {
return VisitUnaryPostIncDec(UO);
}
- RetTy VisitUnaryPostDec(const UnaryOperator *UO) {
+ bool VisitUnaryPostDec(const UnaryOperator *UO) {
return VisitUnaryPostIncDec(UO);
}
- RetTy VisitUnaryPostIncDec(const UnaryOperator *UO) {
+ bool VisitUnaryPostIncDec(const UnaryOperator *UO) {
if (!Info.getLangOpts().CPlusPlus1y && !Info.keepEvaluatingAfterFailure())
return Error(UO);
@@ -4113,7 +4161,7 @@ public:
return DerivedSuccess(RVal, UO);
}
- RetTy VisitStmtExpr(const StmtExpr *E) {
+ bool VisitStmtExpr(const StmtExpr *E) {
// We will have checked the full-expressions inside the statement expression
// when they were completed, and don't need to check them again now.
if (Info.checkingForOverflow())
@@ -4162,11 +4210,11 @@ public:
namespace {
template<class Derived>
class LValueExprEvaluatorBase
- : public ExprEvaluatorBase<Derived, bool> {
+ : public ExprEvaluatorBase<Derived> {
protected:
LValue &Result;
typedef LValueExprEvaluatorBase LValueExprEvaluatorBaseTy;
- typedef ExprEvaluatorBase<Derived, bool> ExprEvaluatorBaseTy;
+ typedef ExprEvaluatorBase<Derived> ExprEvaluatorBaseTy;
bool Success(APValue::LValueBase B) {
Result.set(B);
@@ -4356,7 +4404,7 @@ bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
}
bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
- CallStackFrame *Frame = 0;
+ CallStackFrame *Frame = nullptr;
if (VD->hasLocalStorage() && Info.CurrentCall->Index > 1)
Frame = Info.CurrentCall;
@@ -4533,7 +4581,7 @@ bool LValueExprEvaluator::VisitUnaryPreIncDec(const UnaryOperator *UO) {
return handleIncDec(
this->Info, UO, Result, UO->getSubExpr()->getType(),
- UO->isIncrementOp(), 0);
+ UO->isIncrementOp(), nullptr);
}
bool LValueExprEvaluator::VisitCompoundAssignOperator(
@@ -4584,7 +4632,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
namespace {
class PointerExprEvaluator
- : public ExprEvaluatorBase<PointerExprEvaluator, bool> {
+ : public ExprEvaluatorBase<PointerExprEvaluator> {
LValue &Result;
bool Success(const Expr *E) {
@@ -4601,7 +4649,7 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((Expr*)0);
+ return Success((Expr*)nullptr);
}
bool VisitBinaryOperator(const BinaryOperator *E);
@@ -4623,8 +4671,13 @@ public:
// Can't look at 'this' when checking a potential constant expression.
if (Info.checkingPotentialConstantExpression())
return false;
- if (!Info.CurrentCall->This)
- return Error(E);
+ if (!Info.CurrentCall->This) {
+ if (Info.getLangOpts().CPlusPlus11)
+ Info.Diag(E, diag::note_constexpr_this) << E->isImplicit();
+ else
+ Info.Diag(E);
+ return false;
+ }
Result = *Info.CurrentCall->This;
return true;
}
@@ -4729,7 +4782,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
if (Value.isInt()) {
unsigned Size = Info.Ctx.getTypeSize(E->getType());
uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
- Result.Base = (Expr*)0;
+ Result.Base = (Expr*)nullptr;
Result.Offset = CharUnits::fromQuantity(N);
Result.CallIndex = 0;
Result.Designator.setInvalid();
@@ -4769,7 +4822,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (IsStringLiteralCall(E))
return Success(E);
- switch (E->isBuiltinCall()) {
+ switch (E->getBuiltinCallee()) {
case Builtin::BI__builtin_addressof:
return EvaluateLValue(E->getArg(0), Result, Info);
@@ -4784,7 +4837,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
namespace {
class MemberPointerExprEvaluator
- : public ExprEvaluatorBase<MemberPointerExprEvaluator, bool> {
+ : public ExprEvaluatorBase<MemberPointerExprEvaluator> {
MemberPtr &Result;
bool Success(const ValueDecl *D) {
@@ -4801,7 +4854,7 @@ public:
return true;
}
bool ZeroInitialization(const Expr *E) {
- return Success((const ValueDecl*)0);
+ return Success((const ValueDecl*)nullptr);
}
bool VisitCastExpr(const CastExpr *E);
@@ -4872,7 +4925,7 @@ bool MemberPointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
namespace {
class RecordExprEvaluator
- : public ExprEvaluatorBase<RecordExprEvaluator, bool> {
+ : public ExprEvaluatorBase<RecordExprEvaluator> {
const LValue &This;
APValue &Result;
public:
@@ -4925,14 +4978,13 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E,
}
}
- for (RecordDecl::field_iterator I = RD->field_begin(), End = RD->field_end();
- I != End; ++I) {
+ for (const auto *I : RD->fields()) {
// -- if T is a reference type, no initialization is performed.
if (I->getType()->isReferenceType())
continue;
LValue Subobject = This;
- if (!HandleLValueMember(Info, E, Subobject, *I, &Layout))
+ if (!HandleLValueMember(Info, E, Subobject, I, &Layout))
return false;
ImplicitValueInitExpr VIE(I->getType());
@@ -4952,7 +5004,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) {
// object's first non-static named data member is zero-initialized
RecordDecl::field_iterator I = RD->field_begin();
if (I == RD->field_end()) {
- Result = APValue((const FieldDecl*)0);
+ Result = APValue((const FieldDecl*)nullptr);
return true;
}
@@ -5040,8 +5092,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
std::distance(RD->field_begin(), RD->field_end()));
unsigned ElementNo = 0;
bool Success = true;
- for (RecordDecl::field_iterator Field = RD->field_begin(),
- FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) {
+ for (const auto *Field : RD->fields()) {
// Anonymous bit-fields are not considered members of the class for
// purposes of aggregate initialization.
if (Field->isUnnamedBitfield())
@@ -5054,7 +5105,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// FIXME: Diagnostics here should point to the end of the initializer
// list, not the start.
if (!HandleLValueMember(Info, HaveInit ? E->getInit(ElementNo) : E,
- Subobject, *Field, &Layout))
+ Subobject, Field, &Layout))
return false;
// Perform an implicit value-initialization for members beyond the end of
@@ -5069,7 +5120,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
APValue &FieldVal = Result.getStructField(Field->getFieldIndex());
if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
(Field->isBitField() && !truncateBitfieldValue(Info, Init,
- FieldVal, *Field))) {
+ FieldVal, Field))) {
if (!Info.keepEvaluatingAfterFailure())
return false;
Success = false;
@@ -5100,7 +5151,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return ZeroInitialization(E);
}
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
@@ -5234,7 +5285,7 @@ static bool EvaluateTemporary(const Expr *E, LValue &Result, EvalInfo &Info) {
namespace {
class VectorExprEvaluator
- : public ExprEvaluatorBase<VectorExprEvaluator, bool> {
+ : public ExprEvaluatorBase<VectorExprEvaluator> {
APValue &Result;
public:
@@ -5415,7 +5466,7 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
namespace {
class ArrayExprEvaluator
- : public ExprEvaluatorBase<ArrayExprEvaluator, bool> {
+ : public ExprEvaluatorBase<ArrayExprEvaluator> {
const LValue &This;
APValue &Result;
public:
@@ -5487,7 +5538,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
unsigned NumEltsToInit = E->getNumInits();
unsigned NumElts = CAT->getSize().getZExtValue();
- const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : 0;
+ const Expr *FillerExpr = E->hasArrayFiller() ? E->getArrayFiller() : nullptr;
// If the initializer might depend on the array index, run it for each
// array element. For now, just whitelist non-class value-initialization.
@@ -5582,7 +5633,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
return EvaluateInPlace(*Value, Info, Subobject, &VIE);
}
- const FunctionDecl *Definition = 0;
+ const FunctionDecl *Definition = nullptr;
FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
@@ -5610,7 +5661,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
namespace {
class IntExprEvaluator
- : public ExprEvaluatorBase<IntExprEvaluator, bool> {
+ : public ExprEvaluatorBase<IntExprEvaluator> {
APValue &Result;
public:
IntExprEvaluator(EvalInfo &info, APValue &result)
@@ -5716,14 +5767,6 @@ public:
return ZeroInitialization(E);
}
- bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
- return Success(E->getValue(), E);
- }
-
- bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
- return Success(E->getValue(), E);
- }
-
bool VisitTypeTraitExpr(const TypeTraitExpr *E) {
return Success(E->getValue(), E);
}
@@ -5964,7 +6007,7 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) {
}
bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
- switch (unsigned BuiltinOp = E->isBuiltinCall()) {
+ switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -5983,7 +6026,17 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
// Expression had no side effects, but we couldn't statically determine the
// size of the referenced object.
- return Error(E);
+ switch (Info.EvalMode) {
+ case EvalInfo::EM_ConstantExpression:
+ case EvalInfo::EM_PotentialConstantExpression:
+ case EvalInfo::EM_ConstantFold:
+ case EvalInfo::EM_EvaluateForOverflow:
+ case EvalInfo::EM_IgnoreSideEffects:
+ return Error(E);
+ case EvalInfo::EM_ConstantExpressionUnevaluated:
+ case EvalInfo::EM_PotentialConstantExpressionUnevaluated:
+ return Success(-1ULL, E);
+ }
}
case Builtin::BI__builtin_bswap16:
@@ -6005,7 +6058,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_clz:
case Builtin::BI__builtin_clzl:
- case Builtin::BI__builtin_clzll: {
+ case Builtin::BI__builtin_clzll:
+ case Builtin::BI__builtin_clzs: {
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
@@ -6020,7 +6074,8 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
- case Builtin::BI__builtin_ctzll: {
+ case Builtin::BI__builtin_ctzll:
+ case Builtin::BI__builtin_ctzs: {
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
@@ -6256,11 +6311,11 @@ class DataRecursiveIntBinOpEvaluator {
const Expr *E;
EvalResult LHSResult; // meaningful only for binary operator expression.
enum { AnyExprKind, BinOpKind, BinOpVisitedLHSKind } Kind;
-
- Job() : StoredInfo(0) { }
+
+ Job() : StoredInfo(nullptr) {}
void startSpeculativeEval(EvalInfo &Info) {
OldEvalStatus = Info.EvalStatus;
- Info.EvalStatus.Diag = 0;
+ Info.EvalStatus.Diag = nullptr;
StoredInfo = &Info;
}
~Job() {
@@ -6886,8 +6941,9 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
}
CharUnits IntExprEvaluator::GetAlignOfType(QualType T) {
- // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the
- // result shall be the alignment of the referenced type."
+ // C++ [expr.alignof]p3:
+ // When alignof is applied to a reference type, the result is the
+ // alignment of the referenced type.
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
@@ -6906,7 +6962,7 @@ CharUnits IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
// alignof decl is always accepted, even if it doesn't make sense: we default
// to 1 in those cases.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return Info.Ctx.getDeclAlign(DRE->getDecl(),
+ return Info.Ctx.getDeclAlign(DRE->getDecl(),
/*RefAsPointee*/true);
if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
@@ -7109,6 +7165,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
case CK_NonAtomicToAtomic:
+ case CK_AddressSpaceConversion:
llvm_unreachable("invalid cast kind for integral value");
case CK_BitCast:
@@ -7247,7 +7304,7 @@ bool IntExprEvaluator::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
namespace {
class FloatExprEvaluator
- : public ExprEvaluatorBase<FloatExprEvaluator, bool> {
+ : public ExprEvaluatorBase<FloatExprEvaluator> {
APFloat &Result;
public:
FloatExprEvaluator(EvalInfo &info, APFloat &result)
@@ -7308,7 +7365,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context,
}
bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
- switch (E->isBuiltinCall()) {
+ switch (E->getBuiltinCallee()) {
default:
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -7463,7 +7520,7 @@ bool FloatExprEvaluator::VisitCastExpr(const CastExpr *E) {
namespace {
class ComplexExprEvaluator
- : public ExprEvaluatorBase<ComplexExprEvaluator, bool> {
+ : public ExprEvaluatorBase<ComplexExprEvaluator> {
ComplexValue &Result;
public:
@@ -7581,6 +7638,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
case CK_BuiltinFnToFnPtr:
case CK_ZeroToOCLEvent:
case CK_NonAtomicToAtomic:
+ case CK_AddressSpaceConversion:
llvm_unreachable("invalid cast kind for complex value");
case CK_LValueToRValue:
@@ -7847,7 +7905,7 @@ bool ComplexExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
namespace {
class AtomicExprEvaluator :
- public ExprEvaluatorBase<AtomicExprEvaluator, bool> {
+ public ExprEvaluatorBase<AtomicExprEvaluator> {
APValue &Result;
public:
AtomicExprEvaluator(EvalInfo &Info, APValue &Result)
@@ -7887,7 +7945,7 @@ static bool EvaluateAtomic(const Expr *E, APValue &Result, EvalInfo &Info) {
namespace {
class VoidExprEvaluator
- : public ExprEvaluatorBase<VoidExprEvaluator, bool> {
+ : public ExprEvaluatorBase<VoidExprEvaluator> {
public:
VoidExprEvaluator(EvalInfo &Info) : ExprEvaluatorBaseTy(Info) {}
@@ -7902,6 +7960,16 @@ public:
return true;
}
}
+
+ bool VisitCallExpr(const CallExpr *E) {
+ switch (E->getBuiltinCallee()) {
+ default:
+ return ExprEvaluatorBaseTy::VisitCallExpr(E);
+ case Builtin::BI__assume:
+ // The argument is not evaluated!
+ return true;
+ }
+ }
};
} // end anonymous namespace
@@ -7989,6 +8057,8 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
/// an object can indirectly refer to subobjects which were initialized earlier.
static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This,
const Expr *E, bool AllowNonLiteralTypes) {
+ assert(!E->isValueDependent());
+
if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This))
return false;
@@ -8008,6 +8078,9 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This,
/// EvaluateAsRValue - Try to evaluate this expression, performing an implicit
/// lvalue-to-rvalue cast if it is an lvalue.
static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
+ if (E->getType().isNull())
+ return false;
+
if (!CheckLiteralType(Info, E))
return false;
@@ -8035,6 +8108,13 @@ static bool FastEvaluateAsRValue(const Expr *Exp, Expr::EvalResult &Result,
IsConst = true;
return true;
}
+
+ // This case should be rare, but we need to check it before we check on
+ // the type below.
+ if (Exp->getType().isNull()) {
+ IsConst = false;
+ return true;
+ }
// FIXME: Evaluating values of large array and record types can cause
// performance problems. Only do so in C++11 for now.
@@ -8292,10 +8372,20 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::MaterializeTemporaryExprClass:
case Expr::PseudoObjectExprClass:
case Expr::AtomicExprClass:
- case Expr::InitListExprClass:
case Expr::LambdaExprClass:
return ICEDiag(IK_NotICE, E->getLocStart());
+ case Expr::InitListExprClass: {
+ // C++03 [dcl.init]p13: If T is a scalar type, then a declaration of the
+ // form "T x = { a };" is equivalent to "T x = a;".
+ // Unless we're initializing a reference, T is a scalar as it is known to be
+ // of integral or enumeration type.
+ if (E->isRValue())
+ if (cast<InitListExpr>(E)->getNumInits() == 1)
+ return CheckICE(cast<InitListExpr>(E)->getInit(0), Ctx);
+ return ICEDiag(IK_NotICE, E->getLocStart());
+ }
+
case Expr::SizeOfPackExprClass:
case Expr::GNUNullExprClass:
// GCC considers the GNU __null value to be an integral constant expression.
@@ -8314,8 +8404,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ObjCBoolLiteralExprClass:
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXScalarValueInitExprClass:
- case Expr::UnaryTypeTraitExprClass:
- case Expr::BinaryTypeTraitExprClass:
case Expr::TypeTraitExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
@@ -8327,7 +8415,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// constant expressions, but they can never be ICEs because an ICE cannot
// contain an operand of (pointer to) function type.
const CallExpr *CE = cast<CallExpr>(E);
- if (CE->isBuiltinCall())
+ if (CE->getBuiltinCallee())
return CheckEvalInICE(E, Ctx);
return ICEDiag(IK_NotICE, E->getLocStart());
}
@@ -8544,7 +8632,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
// extension. See GCC PR38377 for discussion.
if (const CallExpr *CallCE
= dyn_cast<CallExpr>(Exp->getCond()->IgnoreParenCasts()))
- if (CallCE->isBuiltinCall() == Builtin::BI__builtin_constant_p)
+ if (CallCE->getBuiltinCallee() == Builtin::BI__builtin_constant_p)
return CheckEvalInICE(E, Ctx);
ICEDiag CondResult = CheckICE(Exp->getCond(), Ctx);
if (CondResult.Kind == IK_NotICE)
@@ -8602,7 +8690,7 @@ static bool EvaluateCPlusPlus11IntegralConstantExpr(const ASTContext &Ctx,
bool Expr::isIntegerConstantExpr(const ASTContext &Ctx,
SourceLocation *Loc) const {
if (Ctx.getLangOpts().CPlusPlus11)
- return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, 0, Loc);
+ return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);
ICEDiag D = CheckICE(this, Ctx);
if (D.Kind != IK_ICE) {
@@ -8654,6 +8742,28 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result,
return IsConstExpr;
}
+bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
+ const FunctionDecl *Callee,
+ ArrayRef<const Expr*> Args) const {
+ Expr::EvalStatus Status;
+ EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpressionUnevaluated);
+
+ ArgVector ArgValues(Args.size());
+ for (ArrayRef<const Expr*>::iterator I = Args.begin(), E = Args.end();
+ I != E; ++I) {
+ if (!Evaluate(ArgValues[I - Args.begin()], Info, *I))
+ // If evaluation fails, throw away the argument entirely.
+ ArgValues[I - Args.begin()] = APValue();
+ if (Info.EvalStatus.HasSideEffects)
+ return false;
+ }
+
+ // Build fake call to Callee.
+ CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr,
+ ArgValues.data());
+ return Evaluate(Value, Info, this) && !Info.EvalStatus.HasSideEffects;
+}
+
bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
SmallVectorImpl<
PartialDiagnosticAt> &Diags) {
@@ -8670,7 +8780,7 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
EvalInfo::EM_PotentialConstantExpression);
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
- const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : 0;
+ const CXXRecordDecl *RD = MD ? MD->getParent()->getCanonicalDecl() : nullptr;
// Fabricate an arbitrary expression on the stack and pretend that it
// is a temporary being used as the 'this' pointer.
@@ -8689,8 +8799,32 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
Info.setEvaluatingDecl(This.getLValueBase(), Scratch);
HandleConstructorCall(Loc, This, Args, CD, Info, Scratch);
} else
- HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : 0,
+ HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
Args, FD->getBody(), Info, Scratch);
return Diags.empty();
}
+
+bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
+ const FunctionDecl *FD,
+ SmallVectorImpl<
+ PartialDiagnosticAt> &Diags) {
+ Expr::EvalStatus Status;
+ Status.Diag = &Diags;
+
+ EvalInfo Info(FD->getASTContext(), Status,
+ EvalInfo::EM_PotentialConstantExpressionUnevaluated);
+
+ // Fabricate a call stack frame to give the arguments a plausible cover story.
+ ArrayRef<const Expr*> Args;
+ ArgVector ArgValues(0);
+ bool Success = EvaluateArgs(Args, ArgValues, Info);
+ (void)Success;
+ assert(Success &&
+ "Failed to set up arguments for potential constant evaluation");
+ CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data());
+
+ APValue ResultScratch;
+ Evaluate(ResultScratch, Info, E);
+ return Diags.empty();
+}