summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
committerdim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
commit06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch)
treeab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
parent2dd166267f53df1c3748b4325d294b9b839de74b (diff)
downloadFreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip
FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0 release, and add lld 3.9.0. Also completely revamp the build system for clang, llvm, lldb and their related tools. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld are available here: <http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html> <http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html> <http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html> Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan Beich for their help. Relnotes: yes MFC r309147: Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek): [PPC] Set SP after loading data from stack frame, if no red zone is present Follow-up to r280705: Make sure that the SP is only restored after all data is loaded from the stack frame, if there is no red zone. This completes the fix for https://llvm.org/bugs/show_bug.cgi?id=26519. Differential Revision: https://reviews.llvm.org/D24466 Reported by: Mark Millard PR: 214433 MFC r309149: Pull in r283060 from upstream llvm trunk (by Hal Finkel): [PowerPC] Refactor soft-float support, and enable PPC64 soft float This change enables soft-float for PowerPC64, and also makes soft-float disable all vector instruction sets for both 32-bit and 64-bit modes. This latter part is necessary because the PPC backend canonicalizes many Altivec vector types to floating-point types, and so soft-float breaks scalarization support for many operations. Both for embedded targets and for operating-system kernels desiring soft-float support, it seems reasonable that disabling hardware floating-point also disables vector instructions (embedded targets without hardware floating point support are unlikely to have Altivec, etc. and operating system kernels desiring not to use floating-point registers to lower syscall cost are unlikely to want to use vector registers either). If someone needs this to work, we'll need to change the fact that we promote many Altivec operations to act on v4f32. To make it possible to disable Altivec when soft-float is enabled, hardware floating-point support needs to be expressed as a positive feature, like the others, and not a negative feature, because target features cannot have dependencies on the disabling of some other feature. So +soft-float has now become -hard-float. Fixes PR26970. Pull in r283061 from upstream clang trunk (by Hal Finkel): [PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float Enable soft-float support on PPC64, as the backend now supports it. Also, the backend now uses -hard-float instead of +soft-float, so set the target features accordingly. Fixes PR26970. Reported by: Mark Millard PR: 214433 MFC r309212: Add a few missed clang 3.9.0 files to OptionalObsoleteFiles. MFC r309262: Fix packaging for clang, lldb and lld 3.9.0 During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE directive in the usr.bin/clang/*.mk files got dropped accidentally. Restore it, with a few minor changes and additions: * Correct license in clang.ucl to NCSA * Add PACKAGE=clang for clang and most of the "ll" tools * Put lldb in its own package * Put lld in its own package Reviewed by: gjb, jmallett Differential Revision: https://reviews.freebsd.org/D8666 MFC r309656: During the bootstrap phase, when building the minimal llvm library on PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream llvm revision r271821 disabled the use of std::call_once, which causes some fallback functions from Atomic.cpp to be used instead. Reported by: Mark Millard PR: 214902 MFC r309835: Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR 70528 (bogus error: constructor required before non-static data member). This should fix buildworld with the external gcc package. Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/ MFC r310194: Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to 3.9.1 release. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld will be available here: <http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html> <http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html> <http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html> Relnotes: yes
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp828
1 files changed, 563 insertions, 265 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
index fa652ba..df944e8 100644
--- a/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
+++ b/contrib/llvm/tools/clang/lib/AST/ExprConstant.cpp
@@ -157,13 +157,13 @@ namespace {
/// True if the subobject was named in a manner not supported by C++11. Such
/// lvalues can still be folded, but they are not core constant expressions
/// and we cannot perform lvalue-to-rvalue conversions on them.
- bool Invalid : 1;
+ unsigned Invalid : 1;
/// Is this a pointer one past the end of an object?
- bool IsOnePastTheEnd : 1;
+ unsigned IsOnePastTheEnd : 1;
/// Indicator of whether the most-derived object is an array element.
- bool MostDerivedIsArrayElement : 1;
+ unsigned MostDerivedIsArrayElement : 1;
/// The length of the path to the most-derived object of which this is a
/// subobject.
@@ -477,6 +477,9 @@ namespace {
/// fold (not just why it's not strictly a constant expression)?
bool HasFoldFailureDiagnostic;
+ /// \brief Whether or not we're currently speculatively evaluating.
+ bool IsSpeculativelyEvaluating;
+
enum EvaluationMode {
/// Evaluate as a constant expression. Stop if we find that the expression
/// is not a constant expression.
@@ -541,7 +544,8 @@ namespace {
BottomFrame(*this, SourceLocation(), nullptr, nullptr, nullptr),
EvaluatingDecl((const ValueDecl *)nullptr),
EvaluatingDeclValue(nullptr), HasActiveDiagnostic(false),
- HasFoldFailureDiagnostic(false), EvalMode(Mode) {}
+ HasFoldFailureDiagnostic(false), IsSpeculativelyEvaluating(false),
+ EvalMode(Mode) {}
void setEvaluatingDecl(APValue::LValueBase Base, APValue &Value) {
EvaluatingDecl = Base;
@@ -557,12 +561,12 @@ namespace {
return false;
if (NextCallIndex == 0) {
// NextCallIndex has wrapped around.
- Diag(Loc, diag::note_constexpr_call_limit_exceeded);
+ FFDiag(Loc, diag::note_constexpr_call_limit_exceeded);
return false;
}
if (CallStackDepth <= getLangOpts().ConstexprCallDepth)
return true;
- Diag(Loc, diag::note_constexpr_depth_limit_exceeded)
+ FFDiag(Loc, diag::note_constexpr_depth_limit_exceeded)
<< getLangOpts().ConstexprCallDepth;
return false;
}
@@ -579,7 +583,7 @@ namespace {
bool nextStep(const Stmt *S) {
if (!StepsLeft) {
- Diag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded);
+ FFDiag(S->getLocStart(), diag::note_constexpr_step_limit_exceeded);
return false;
}
--StepsLeft;
@@ -597,11 +601,10 @@ namespace {
/// Add notes containing a call stack to the current point of evaluation.
void addCallStack(unsigned Limit);
- public:
- /// Diagnose that the evaluation cannot be folded.
- OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId
- = diag::note_invalid_subexpr_in_const_expr,
- unsigned ExtraNotes = 0, bool IsCCEDiag = false) {
+ private:
+ OptionalDiagnostic Diag(SourceLocation Loc, diag::kind DiagId,
+ unsigned ExtraNotes, bool IsCCEDiag) {
+
if (EvalStatus.Diag) {
// If we have a prior diagnostic, it will be noting that the expression
// isn't a constant expression. This diagnostic is more important,
@@ -646,12 +649,20 @@ namespace {
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
-
- OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId
+ public:
+ // Diagnose that the evaluation could not be folded (FF => FoldFailure)
+ OptionalDiagnostic
+ FFDiag(SourceLocation Loc,
+ diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr,
+ unsigned ExtraNotes = 0) {
+ return Diag(Loc, DiagId, ExtraNotes, false);
+ }
+
+ OptionalDiagnostic FFDiag(const Expr *E, diag::kind DiagId
= diag::note_invalid_subexpr_in_const_expr,
- unsigned ExtraNotes = 0, bool IsCCEDiag = false) {
+ unsigned ExtraNotes = 0) {
if (EvalStatus.Diag)
- return Diag(E->getExprLoc(), DiagId, ExtraNotes, IsCCEDiag);
+ return Diag(E->getExprLoc(), DiagId, ExtraNotes, /*IsCCEDiag*/false);
HasActiveDiagnostic = false;
return OptionalDiagnostic();
}
@@ -661,8 +672,7 @@ namespace {
///
/// FIXME: Stop evaluating if we're in EM_ConstantExpression or
/// EM_PotentialConstantExpression mode and we produce one of these.
- template<typename LocArg>
- OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId
+ OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId
= diag::note_invalid_subexpr_in_const_expr,
unsigned ExtraNotes = 0) {
// Don't override a previous diagnostic. Don't bother collecting
@@ -673,7 +683,11 @@ namespace {
}
return Diag(Loc, DiagId, ExtraNotes, true);
}
-
+ OptionalDiagnostic CCEDiag(const Expr *E, diag::kind DiagId
+ = diag::note_invalid_subexpr_in_const_expr,
+ unsigned ExtraNotes = 0) {
+ return CCEDiag(E->getExprLoc(), DiagId, ExtraNotes);
+ }
/// Add a note to a prior diagnostic.
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId) {
if (!HasActiveDiagnostic)
@@ -763,6 +777,29 @@ namespace {
llvm_unreachable("Missed EvalMode case");
}
+ /// Notes that we failed to evaluate an expression that other expressions
+ /// directly depend on, and determine if we should keep evaluating. This
+ /// should only be called if we actually intend to keep evaluating.
+ ///
+ /// Call noteSideEffect() instead if we may be able to ignore the value that
+ /// we failed to evaluate, e.g. if we failed to evaluate Foo() in:
+ ///
+ /// (Foo(), 1) // use noteSideEffect
+ /// (Foo() || true) // use noteSideEffect
+ /// Foo() + 1 // use noteFailure
+ LLVM_ATTRIBUTE_UNUSED_RESULT bool noteFailure() {
+ // Failure when evaluating some expression often means there is some
+ // subexpression whose evaluation was skipped. Therefore, (because we
+ // don't track whether we skipped an expression when unwinding after an
+ // evaluation failure) every evaluation failure that bubbles up from a
+ // subexpression implies that a side-effect has potentially happened. We
+ // skip setting the HasSideEffects flag to true until we decide to
+ // continue evaluating after that point, which happens here.
+ bool KeepGoing = keepEvaluatingAfterFailure();
+ EvalStatus.HasSideEffects |= KeepGoing;
+ return KeepGoing;
+ }
+
bool allowInvalidBaseExpr() const {
return EvalMode == EM_DesignatorFold;
}
@@ -811,24 +848,52 @@ namespace {
~FoldOffsetRAII() { Info.EvalMode = OldMode; }
};
- /// RAII object used to suppress diagnostics and side-effects from a
- /// speculative evaluation.
+ /// RAII object used to optionally suppress diagnostics and side-effects from
+ /// a speculative evaluation.
class SpeculativeEvaluationRAII {
- EvalInfo &Info;
+ /// Pair of EvalInfo, and a bit that stores whether or not we were
+ /// speculatively evaluating when we created this RAII.
+ llvm::PointerIntPair<EvalInfo *, 1, bool> InfoAndOldSpecEval;
Expr::EvalStatus Old;
+ void moveFromAndCancel(SpeculativeEvaluationRAII &&Other) {
+ InfoAndOldSpecEval = Other.InfoAndOldSpecEval;
+ Old = Other.Old;
+ Other.InfoAndOldSpecEval.setPointer(nullptr);
+ }
+
+ void maybeRestoreState() {
+ EvalInfo *Info = InfoAndOldSpecEval.getPointer();
+ if (!Info)
+ return;
+
+ Info->EvalStatus = Old;
+ Info->IsSpeculativelyEvaluating = InfoAndOldSpecEval.getInt();
+ }
+
public:
- SpeculativeEvaluationRAII(EvalInfo &Info,
- SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
- : Info(Info), Old(Info.EvalStatus) {
+ SpeculativeEvaluationRAII() = default;
+
+ SpeculativeEvaluationRAII(
+ EvalInfo &Info, SmallVectorImpl<PartialDiagnosticAt> *NewDiag = nullptr)
+ : InfoAndOldSpecEval(&Info, Info.IsSpeculativelyEvaluating),
+ Old(Info.EvalStatus) {
Info.EvalStatus.Diag = NewDiag;
- // If we're speculatively evaluating, we may have skipped over some
- // evaluations and missed out a side effect.
- Info.EvalStatus.HasSideEffects = true;
+ Info.IsSpeculativelyEvaluating = true;
}
- ~SpeculativeEvaluationRAII() {
- Info.EvalStatus = Old;
+
+ SpeculativeEvaluationRAII(const SpeculativeEvaluationRAII &Other) = delete;
+ SpeculativeEvaluationRAII(SpeculativeEvaluationRAII &&Other) {
+ moveFromAndCancel(std::move(Other));
}
+
+ SpeculativeEvaluationRAII &operator=(SpeculativeEvaluationRAII &&Other) {
+ maybeRestoreState();
+ moveFromAndCancel(std::move(Other));
+ return *this;
+ }
+
+ ~SpeculativeEvaluationRAII() { maybeRestoreState(); }
};
/// RAII object wrapping a full-expression or block scope, and handling
@@ -941,6 +1006,16 @@ void EvalInfo::addCallStack(unsigned Limit) {
continue;
}
+ // Use a different note for an inheriting constructor, because from the
+ // user's perspective it's not really a function at all.
+ if (auto *CD = dyn_cast_or_null<CXXConstructorDecl>(Frame->Callee)) {
+ if (CD->isInheritingConstructor()) {
+ addDiag(Frame->CallLoc, diag::note_constexpr_inherited_ctor_call_here)
+ << CD->getParent();
+ continue;
+ }
+ }
+
SmallVector<char, 128> Buffer;
llvm::raw_svector_ostream Out(Buffer);
describeCall(Frame, Out);
@@ -992,7 +1067,7 @@ namespace {
struct LValue {
APValue::LValueBase Base;
CharUnits Offset;
- bool InvalidBase : 1;
+ unsigned InvalidBase : 1;
unsigned CallIndex : 31;
SubobjectDesignator Designator;
@@ -1335,12 +1410,12 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
if (!IsGlobalLValue(Base)) {
if (Info.getLangOpts().CPlusPlus11) {
const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();
- Info.Diag(Loc, diag::note_constexpr_non_global, 1)
+ Info.FFDiag(Loc, diag::note_constexpr_non_global, 1)
<< IsReferenceType << !Designator.Entries.empty()
<< !!VD << VD;
NoteLValueLocation(Info, Base);
} else {
- Info.Diag(Loc);
+ Info.FFDiag(Loc);
}
// Don't allow references to temporaries to escape.
return false;
@@ -1390,7 +1465,7 @@ static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
// Does this refer one past the end of some object?
if (!Designator.Invalid && Designator.isOnePastTheEnd()) {
const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>();
- Info.Diag(Loc, diag::note_constexpr_past_end, 1)
+ Info.FFDiag(Loc, diag::note_constexpr_past_end, 1)
<< !Designator.Entries.empty() << !!VD << VD;
NoteLValueLocation(Info, Base);
}
@@ -1414,10 +1489,10 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
// Prvalue constant expressions must be of literal types.
if (Info.getLangOpts().CPlusPlus11)
- Info.Diag(E, diag::note_constexpr_nonliteral)
+ Info.FFDiag(E, diag::note_constexpr_nonliteral)
<< E->getType();
else
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
@@ -1427,7 +1502,7 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E,
static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
QualType Type, const APValue &Value) {
if (Value.isUninit()) {
- Info.Diag(DiagLoc, diag::note_constexpr_uninitialized)
+ Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
<< true << Type;
return false;
}
@@ -1637,7 +1712,7 @@ static bool truncateBitfieldValue(EvalInfo &Info, const Expr *E,
// FIXME: In this case, we should provide the diagnostic for casting
// a pointer to an integer.
assert(Value.isLValue() && "integral value neither int nor lvalue?");
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -1679,7 +1754,7 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E,
} else {
// Don't try to handle vectors of anything other than int or float
// (not sure if it's possible to hit this case).
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
unsigned BaseEltSize = EltAsInt.getBitWidth();
@@ -1692,7 +1767,7 @@ static bool EvalAndBitcastToAPInt(EvalInfo &Info, const Expr *E,
}
// Give up if the input isn't an int, float, or vector. For example, we
// reject "(v4i16)(intptr_t)&a".
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
@@ -1728,7 +1803,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
APSInt &Result) {
switch (Opcode) {
default:
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
case BO_Mul:
return CheckedIntArithmetic(Info, E, LHS, RHS, LHS.getBitWidth() * 2,
@@ -1745,7 +1820,7 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
case BO_Div:
case BO_Rem:
if (RHS == 0) {
- Info.Diag(E, diag::note_expr_divide_by_zero);
+ Info.FFDiag(E, diag::note_expr_divide_by_zero);
return false;
}
Result = (Opcode == BO_Rem ? LHS % RHS : LHS / RHS);
@@ -1826,7 +1901,7 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E,
const APFloat &RHS) {
switch (Opcode) {
default:
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
case BO_Mul:
LHS.multiply(RHS, APFloat::rmNearestTiesToEven);
@@ -1968,10 +2043,15 @@ static bool HandleSizeof(EvalInfo &Info, SourceLocation Loc,
return true;
}
+ if (Type->isDependentType()) {
+ Info.FFDiag(Loc);
+ return false;
+ }
+
if (!Type->isConstantSizeType()) {
// sizeof(vla) is not a constantexpr: C99 6.5.3.4p2.
// FIXME: Better diagnostic.
- Info.Diag(Loc);
+ Info.FFDiag(Loc);
return false;
}
@@ -2035,7 +2115,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
if (Info.checkingPotentialConstantExpression())
return false;
if (!Frame || !Frame->Arguments) {
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
Result = &Frame->Arguments[PVD->getFunctionScopeIndex()];
@@ -2055,7 +2135,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// If we're checking a potential constant expression, the variable could be
// initialized later.
if (!Info.checkingPotentialConstantExpression())
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
@@ -2069,7 +2149,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// Never evaluate the initializer of a weak variable. We can't be sure that
// this is the definition which will be used.
if (VD->isWeak()) {
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
@@ -2077,7 +2157,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
// this in the cases where it matters for conformance.
SmallVector<PartialDiagnosticAt, 8> Notes;
if (!VD->evaluateValue(Notes)) {
- Info.Diag(E, diag::note_constexpr_var_init_non_constant,
+ Info.FFDiag(E, diag::note_constexpr_var_init_non_constant,
Notes.size() + 1) << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
Info.addNotes(Notes);
@@ -2218,7 +2298,7 @@ static bool diagnoseUnreadableFields(EvalInfo &Info, const Expr *E,
// FIXME: Add core issue number for the union case.
if (Field->isMutable() &&
(RD->isUnion() || isReadByLvalueToRvalueConversion(Field->getType()))) {
- Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field;
+ Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1) << Field;
Info.Note(Field->getLocation(), diag::note_declared_at);
return true;
}
@@ -2272,10 +2352,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
return handler.failed();
if (Sub.isOnePastTheEnd()) {
if (Info.getLangOpts().CPlusPlus11)
- Info.Diag(E, diag::note_constexpr_access_past_end)
+ Info.FFDiag(E, diag::note_constexpr_access_past_end)
<< handler.AccessKind;
else
- Info.Diag(E);
+ Info.FFDiag(E);
return handler.failed();
}
@@ -2287,7 +2367,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) {
if (O->isUninit()) {
if (!Info.checkingPotentialConstantExpression())
- Info.Diag(E, diag::note_constexpr_access_uninit) << handler.AccessKind;
+ Info.FFDiag(E, diag::note_constexpr_access_uninit) << handler.AccessKind;
return handler.failed();
}
@@ -2322,10 +2402,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
// Note, it should not be possible to form a pointer with a valid
// designator which points more than one past the end of the array.
if (Info.getLangOpts().CPlusPlus11)
- Info.Diag(E, diag::note_constexpr_access_past_end)
+ Info.FFDiag(E, diag::note_constexpr_access_past_end)
<< handler.AccessKind;
else
- Info.Diag(E);
+ Info.FFDiag(E);
return handler.failed();
}
@@ -2355,10 +2435,10 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
uint64_t Index = Sub.Entries[I].ArrayIndex;
if (Index > 1) {
if (Info.getLangOpts().CPlusPlus11)
- Info.Diag(E, diag::note_constexpr_access_past_end)
+ Info.FFDiag(E, diag::note_constexpr_access_past_end)
<< handler.AccessKind;
else
- Info.Diag(E);
+ Info.FFDiag(E);
return handler.failed();
}
@@ -2378,7 +2458,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
}
} else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) {
if (Field->isMutable() && handler.AccessKind == AK_Read) {
- Info.Diag(E, diag::note_constexpr_ltor_mutable, 1)
+ Info.FFDiag(E, diag::note_constexpr_ltor_mutable, 1)
<< Field;
Info.Note(Field->getLocation(), diag::note_declared_at);
return handler.failed();
@@ -2390,7 +2470,7 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
const FieldDecl *UnionField = O->getUnionField();
if (!UnionField ||
UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) {
- Info.Diag(E, diag::note_constexpr_access_inactive_union_member)
+ Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member)
<< handler.AccessKind << Field << !UnionField << UnionField;
return handler.failed();
}
@@ -2406,11 +2486,11 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj,
if (ObjType.isVolatileQualified()) {
if (Info.getLangOpts().CPlusPlus) {
// FIXME: Include a description of the path to the volatile subobject.
- Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1)
+ Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1)
<< handler.AccessKind << 2 << Field;
Info.Note(Field->getLocation(), diag::note_declared_at);
} else {
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
}
return handler.failed();
}
@@ -2482,7 +2562,7 @@ struct ModifySubobjectHandler {
bool checkConst(QualType QT) {
// Assigning to a const object has undefined behavior.
if (QT.isConstQualified()) {
- Info.Diag(E, diag::note_constexpr_modify_const_type) << QT;
+ Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
return false;
}
return true;
@@ -2501,7 +2581,7 @@ struct ModifySubobjectHandler {
return false;
if (!NewVal.isInt()) {
// Maybe trying to write a cast pointer value into a complex?
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
Value = NewVal.getInt();
@@ -2592,7 +2672,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
AccessKinds AK, const LValue &LVal,
QualType LValType) {
if (!LVal.Base) {
- Info.Diag(E, diag::note_constexpr_access_null) << AK;
+ Info.FFDiag(E, diag::note_constexpr_access_null) << AK;
return CompleteObject();
}
@@ -2600,7 +2680,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
if (LVal.CallIndex) {
Frame = Info.getCallFrame(LVal.CallIndex);
if (!Frame) {
- Info.Diag(E, diag::note_constexpr_lifetime_ended, 1)
+ Info.FFDiag(E, diag::note_constexpr_lifetime_ended, 1)
<< AK << LVal.Base.is<const ValueDecl*>();
NoteLValueLocation(Info, LVal.Base);
return CompleteObject();
@@ -2613,10 +2693,10 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// semantics.
if (LValType.isVolatileQualified()) {
if (Info.getLangOpts().CPlusPlus)
- Info.Diag(E, diag::note_constexpr_access_volatile_type)
+ Info.FFDiag(E, diag::note_constexpr_access_volatile_type)
<< AK << LValType;
else
- Info.Diag(E);
+ Info.FFDiag(E);
return CompleteObject();
}
@@ -2638,18 +2718,18 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
VD = VDef;
}
if (!VD || VD->isInvalidDecl()) {
- Info.Diag(E);
+ Info.FFDiag(E);
return CompleteObject();
}
// Accesses of volatile-qualified objects are not allowed.
if (BaseType.isVolatileQualified()) {
if (Info.getLangOpts().CPlusPlus) {
- Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1)
+ Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1)
<< AK << 1 << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
- Info.Diag(E);
+ Info.FFDiag(E);
}
return CompleteObject();
}
@@ -2664,17 +2744,20 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// evaluation.
} else if (AK != AK_Read) {
// All the remaining cases only permit reading.
- Info.Diag(E, diag::note_constexpr_modify_global);
+ Info.FFDiag(E, diag::note_constexpr_modify_global);
return CompleteObject();
} else if (VD->isConstexpr()) {
// OK, we can read this variable.
} else if (BaseType->isIntegralOrEnumerationType()) {
- if (!BaseType.isConstQualified()) {
+ // In OpenCL if a variable is in constant address space it is a const value.
+ if (!(BaseType.isConstQualified() ||
+ (Info.getLangOpts().OpenCL &&
+ BaseType.getAddressSpace() == LangAS::opencl_constant))) {
if (Info.getLangOpts().CPlusPlus) {
- Info.Diag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD;
+ Info.FFDiag(E, diag::note_constexpr_ltor_non_const_int, 1) << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
- Info.Diag(E);
+ Info.FFDiag(E);
}
return CompleteObject();
}
@@ -2690,11 +2773,15 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
} else {
// FIXME: Allow folding of values of any literal type in all languages.
- if (Info.getLangOpts().CPlusPlus11) {
- Info.Diag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
+ if (Info.checkingPotentialConstantExpression() &&
+ VD->getType().isConstQualified() && !VD->hasDefinition(Info.Ctx)) {
+ // The definition of this variable could be constexpr. We can't
+ // access it right now, but may be able to in future.
+ } else if (Info.getLangOpts().CPlusPlus11) {
+ Info.FFDiag(E, diag::note_constexpr_ltor_non_constexpr, 1) << VD;
Info.Note(VD->getLocation(), diag::note_declared_at);
} else {
- Info.Diag(E);
+ Info.FFDiag(E);
}
return CompleteObject();
}
@@ -2730,7 +2817,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
if (!(BaseType.isConstQualified() &&
BaseType->isIntegralOrEnumerationType()) &&
!(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) {
- Info.Diag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
+ Info.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
Info.Note(MTE->getExprLoc(), diag::note_constexpr_temporary_here);
return CompleteObject();
}
@@ -2738,7 +2825,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
BaseVal = Info.Ctx.getMaterializedTemporaryValue(MTE, false);
assert(BaseVal && "got reference to unevaluated temporary");
} else {
- Info.Diag(E);
+ Info.FFDiag(E);
return CompleteObject();
}
} else {
@@ -2749,11 +2836,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
// Volatile temporary objects cannot be accessed in constant expressions.
if (BaseType.isVolatileQualified()) {
if (Info.getLangOpts().CPlusPlus) {
- Info.Diag(E, diag::note_constexpr_access_volatile_obj, 1)
+ Info.FFDiag(E, diag::note_constexpr_access_volatile_obj, 1)
<< AK << 0;
Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here);
} else {
- Info.Diag(E);
+ Info.FFDiag(E);
}
return CompleteObject();
}
@@ -2769,12 +2856,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E,
}
// In C++1y, we can't safely access any mutable state when we might be
- // evaluating after an unmodeled side effect or an evaluation failure.
+ // evaluating after an unmodeled side effect.
//
// FIXME: Not all local state is mutable. Allow local constant subobjects
// to be read here (but take care with 'mutable' fields).
- if (Frame && Info.getLangOpts().CPlusPlus14 &&
- (Info.EvalStatus.HasSideEffects || Info.keepEvaluatingAfterFailure()))
+ if ((Frame && Info.getLangOpts().CPlusPlus14 &&
+ Info.EvalStatus.HasSideEffects) ||
+ (AK != AK_Read && Info.IsSpeculativelyEvaluating))
return CompleteObject();
return CompleteObject(BaseVal, BaseType);
@@ -2806,7 +2894,7 @@ static bool handleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
// an ICE in C, so this only matters for fold.
assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
if (Type.isVolatileQualified()) {
- Info.Diag(Conv);
+ Info.FFDiag(Conv);
return false;
}
APValue Lit;
@@ -2835,7 +2923,7 @@ static bool handleAssignment(EvalInfo &Info, const Expr *E, const LValue &LVal,
return false;
if (!Info.getLangOpts().CPlusPlus14) {
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -2863,7 +2951,7 @@ struct CompoundAssignSubobjectHandler {
bool checkConst(QualType QT) {
// Assigning to a const object has undefined behavior.
if (QT.isConstQualified()) {
- Info.Diag(E, diag::note_constexpr_modify_const_type) << QT;
+ Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
return false;
}
return true;
@@ -2879,13 +2967,13 @@ struct CompoundAssignSubobjectHandler {
case APValue::ComplexInt:
case APValue::ComplexFloat:
// FIXME: Implement complex compound assignment.
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
case APValue::LValue:
return foundPointer(Subobj, SubobjType);
default:
// FIXME: can this happen?
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
}
@@ -2896,7 +2984,7 @@ struct CompoundAssignSubobjectHandler {
if (!SubobjType->isIntegerType() || !RHS.isInt()) {
// We don't support compound assignment on integer-cast-to-pointer
// values.
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -2924,7 +3012,7 @@ struct CompoundAssignSubobjectHandler {
if (PointeeType.isNull() || !RHS.isInt() ||
(Opcode != BO_Add && Opcode != BO_Sub)) {
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -2956,7 +3044,7 @@ static bool handleCompoundAssignment(
return false;
if (!Info.getLangOpts().CPlusPlus14) {
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -2978,7 +3066,7 @@ struct IncDecSubobjectHandler {
bool checkConst(QualType QT) {
// Assigning to a const object has undefined behavior.
if (QT.isConstQualified()) {
- Info.Diag(E, diag::note_constexpr_modify_const_type) << QT;
+ Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
return false;
}
return true;
@@ -3010,7 +3098,7 @@ struct IncDecSubobjectHandler {
return foundPointer(Subobj, SubobjType);
default:
// FIXME: can this happen?
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
}
@@ -3021,7 +3109,7 @@ struct IncDecSubobjectHandler {
if (!SubobjType->isIntegerType()) {
// We don't support increment / decrement on integer-cast-to-pointer
// values.
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -3080,7 +3168,7 @@ struct IncDecSubobjectHandler {
if (const PointerType *PT = SubobjType->getAs<PointerType>())
PointeeType = PT->getPointeeType();
else {
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -3105,7 +3193,7 @@ static bool handleIncDec(EvalInfo &Info, const Expr *E, const LValue &LVal,
return false;
if (!Info.getLangOpts().CPlusPlus14) {
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
@@ -3127,7 +3215,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();
+ Info.FFDiag(Object, diag::note_constexpr_nonliteral) << Object->getType();
return false;
}
@@ -3155,7 +3243,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
// member value, the behavior is undefined.
if (!MemPtr.getDecl()) {
// FIXME: Specific diagnostic.
- Info.Diag(RHS);
+ Info.FFDiag(RHS);
return nullptr;
}
@@ -3165,7 +3253,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
// derived-to-base path for the member pointer.
if (LV.Designator.MostDerivedPathLength + MemPtr.Path.size() >
LV.Designator.Entries.size()) {
- Info.Diag(RHS);
+ Info.FFDiag(RHS);
return nullptr;
}
unsigned PathLengthToMember =
@@ -3175,7 +3263,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
LV.Designator.Entries[PathLengthToMember + I]);
const CXXRecordDecl *MPDecl = MemPtr.Path[I];
if (LVDecl->getCanonicalDecl() != MPDecl->getCanonicalDecl()) {
- Info.Diag(RHS);
+ Info.FFDiag(RHS);
return nullptr;
}
}
@@ -3231,7 +3319,7 @@ static const ValueDecl *HandleMemberPointerAccess(EvalInfo &Info,
assert(BO->getOpcode() == BO_PtrMemD || BO->getOpcode() == BO_PtrMemI);
if (!EvaluateObjectArgument(Info, BO->getLHS(), LV)) {
- if (Info.keepEvaluatingAfterFailure()) {
+ if (Info.noteFailure()) {
MemberPtr MemPtr;
EvaluateMemberPointer(BO->getRHS(), MemPtr, Info);
}
@@ -3309,7 +3397,7 @@ static bool EvaluateDecl(EvalInfo &Info, const Decl *D) {
const Expr *InitE = VD->getInit();
if (!InitE) {
- Info.Diag(D->getLocStart(), diag::note_constexpr_uninitialized)
+ Info.FFDiag(D->getLocStart(), diag::note_constexpr_uninitialized)
<< false << VD->getType();
Val = APValue();
return false;
@@ -3338,6 +3426,7 @@ static bool EvaluateCond(EvalInfo &Info, const VarDecl *CondDecl,
return EvaluateAsBooleanCondition(Cond, Result, Info);
}
+namespace {
/// \brief A location where the result (returned value) of evaluating a
/// statement should be stored.
struct StmtResult {
@@ -3346,6 +3435,7 @@ struct StmtResult {
/// The location containing the result, if any (used to support RVO).
const LValue *Slot;
};
+}
static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
const Stmt *S,
@@ -3379,6 +3469,11 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
APSInt Value;
{
FullExpressionRAII Scope(Info);
+ if (const Stmt *Init = SS->getInit()) {
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, Init);
+ if (ESR != ESR_Succeeded)
+ return ESR;
+ }
if (SS->getConditionVariable() &&
!EvaluateDecl(Info, SS->getConditionVariable()))
return ESR_Failed;
@@ -3421,7 +3516,7 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info,
case ESR_CaseNotFound:
// This can only happen if the switch case is nested within a statement
// expression. We have no intention of supporting that.
- Info.Diag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported);
+ Info.FFDiag(Found->getLocStart(), diag::note_constexpr_stmt_expr_unsupported);
return ESR_Failed;
}
llvm_unreachable("Invalid EvalStmtResult!");
@@ -3512,7 +3607,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
return ESR_Succeeded;
}
- Info.Diag(S->getLocStart());
+ Info.FFDiag(S->getLocStart());
return ESR_Failed;
case Stmt::NullStmtClass:
@@ -3525,7 +3620,7 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
// 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.noteFailure())
return ESR_Failed;
}
return ESR_Succeeded;
@@ -3561,6 +3656,11 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
// Evaluate the condition, as either a var decl or as an expression.
BlockScopeRAII Scope(Info);
+ if (const Stmt *Init = IS->getInit()) {
+ EvalStmtResult ESR = EvaluateStmt(Result, Info, Init);
+ if (ESR != ESR_Succeeded)
+ return ESR;
+ }
bool Cond;
if (!EvaluateCond(Info, IS->getConditionVariable(), IS->getCond(), Cond))
return ESR_Failed;
@@ -3647,7 +3747,10 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
return ESR;
// Create the __begin and __end iterators.
- ESR = EvaluateStmt(Result, Info, FS->getBeginEndStmt());
+ ESR = EvaluateStmt(Result, Info, FS->getBeginStmt());
+ if (ESR != ESR_Succeeded)
+ return ESR;
+ ESR = EvaluateStmt(Result, Info, FS->getEndStmt());
if (ESR != ESR_Succeeded)
return ESR;
@@ -3736,7 +3839,8 @@ static bool CheckTrivialDefaultConstructor(EvalInfo &Info, SourceLocation Loc,
/// expression.
static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
const FunctionDecl *Declaration,
- const FunctionDecl *Definition) {
+ const FunctionDecl *Definition,
+ const Stmt *Body) {
// Potential constant expressions can contain calls to declared, but not yet
// defined, constexpr functions.
if (Info.checkingPotentialConstantExpression() && !Definition &&
@@ -3749,19 +3853,34 @@ static bool CheckConstexprFunction(EvalInfo &Info, SourceLocation CallLoc,
return false;
// Can we evaluate this function call?
- if (Definition && Definition->isConstexpr() && !Definition->isInvalidDecl())
+ if (Definition && Definition->isConstexpr() &&
+ !Definition->isInvalidDecl() && Body)
return true;
if (Info.getLangOpts().CPlusPlus11) {
const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
- // FIXME: If DiagDecl is an implicitly-declared special member function, we
- // should be much more explicit about why it's not constexpr.
- Info.Diag(CallLoc, diag::note_constexpr_invalid_function, 1)
- << DiagDecl->isConstexpr() << isa<CXXConstructorDecl>(DiagDecl)
- << DiagDecl;
+
+ // If this function is not constexpr because it is an inherited
+ // non-constexpr constructor, diagnose that directly.
+ auto *CD = dyn_cast<CXXConstructorDecl>(DiagDecl);
+ if (CD && CD->isInheritingConstructor()) {
+ auto *Inherited = CD->getInheritedConstructor().getConstructor();
+ if (!Inherited->isConstexpr())
+ DiagDecl = CD = Inherited;
+ }
+
+ // FIXME: If DiagDecl is an implicitly-declared special member function
+ // or an inheriting constructor, we should be much more explicit about why
+ // it's not constexpr.
+ if (CD && CD->isInheritingConstructor())
+ Info.FFDiag(CallLoc, diag::note_constexpr_invalid_inhctor, 1)
+ << CD->getInheritedConstructor().getConstructor()->getParent();
+ else
+ Info.FFDiag(CallLoc, diag::note_constexpr_invalid_function, 1)
+ << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
Info.Note(DiagDecl->getLocation(), diag::note_declared_at);
} else {
- Info.Diag(CallLoc, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(CallLoc, diag::note_invalid_subexpr_in_const_expr);
}
return false;
}
@@ -3795,7 +3914,7 @@ static bool EvaluateArgs(ArrayRef<const Expr*> Args, ArgVector &ArgValues,
if (!Evaluate(ArgValues[I - Args.begin()], Info, *I)) {
// If we're checking for a potential constant expression, evaluate all
// initializers even if some of them fail.
- if (!Info.keepEvaluatingAfterFailure())
+ if (!Info.noteFailure())
return false;
Success = false;
}
@@ -3848,37 +3967,34 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
if (ESR == ESR_Succeeded) {
if (Callee->getReturnType()->isVoidType())
return true;
- Info.Diag(Callee->getLocEnd(), diag::note_constexpr_no_return);
+ Info.FFDiag(Callee->getLocEnd(), diag::note_constexpr_no_return);
}
return ESR == ESR_Returned;
}
/// Evaluate a constructor call.
-static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
- ArrayRef<const Expr*> Args,
+static bool HandleConstructorCall(const Expr *E, const LValue &This,
+ APValue *ArgValues,
const CXXConstructorDecl *Definition,
EvalInfo &Info, APValue &Result) {
- ArgVector ArgValues(Args.size());
- if (!EvaluateArgs(Args, ArgValues, Info))
- return false;
-
+ SourceLocation CallLoc = E->getExprLoc();
if (!Info.CheckCallLimit(CallLoc))
return false;
const CXXRecordDecl *RD = Definition->getParent();
if (RD->getNumVBases()) {
- Info.Diag(CallLoc, diag::note_constexpr_virtual_base) << RD;
+ Info.FFDiag(CallLoc, diag::note_constexpr_virtual_base) << RD;
return false;
}
- CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data());
+ CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues);
// FIXME: Creating an APValue just to hold a nonexistent return value is
// wasteful.
APValue RetVal;
StmtResult Ret = {RetVal, nullptr};
- // If it's a delegating constructor, just delegate.
+ // If it's a delegating constructor, delegate.
if (Definition->isDelegatingConstructor()) {
CXXConstructorDecl::init_const_iterator I = Definition->init_begin();
{
@@ -3902,8 +4018,9 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
(Definition->isTrivial() && hasFields(Definition->getParent())))) {
LValue RHS;
RHS.setFrom(Info.Ctx, ArgValues[0]);
- return handleLValueToRValueConversion(Info, Args[0], Args[0]->getType(),
- RHS, Result);
+ return handleLValueToRValueConversion(
+ Info, E, Definition->getParamDecl(0)->getType().getNonReferenceType(),
+ RHS, Result);
}
// Reserve space for the struct members.
@@ -3987,7 +4104,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
*Value, FD))) {
// If we're checking for a potential constant expression, evaluate all
// initializers even if some of them fail.
- if (!Info.keepEvaluatingAfterFailure())
+ if (!Info.noteFailure())
return false;
Success = false;
}
@@ -3997,6 +4114,18 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This,
EvaluateStmt(Ret, Info, Definition->getBody()) != ESR_Failed;
}
+static bool HandleConstructorCall(const Expr *E, const LValue &This,
+ ArrayRef<const Expr*> Args,
+ const CXXConstructorDecl *Definition,
+ EvalInfo &Info, APValue &Result) {
+ ArgVector ArgValues(Args.size());
+ if (!EvaluateArgs(Args, ArgValues, Info))
+ return false;
+
+ return HandleConstructorCall(E, This, ArgValues.data(), Definition,
+ Info, Result);
+}
+
//===----------------------------------------------------------------------===//
// Generic Evaluation
//===----------------------------------------------------------------------===//
@@ -4022,14 +4151,16 @@ private:
assert(Info.checkingPotentialConstantExpression());
// Speculatively evaluate both arms.
+ SmallVector<PartialDiagnosticAt, 8> Diag;
{
- SmallVector<PartialDiagnosticAt, 8> Diag;
SpeculativeEvaluationRAII Speculate(Info, &Diag);
-
StmtVisitorTy::Visit(E->getFalseExpr());
if (Diag.empty())
return;
+ }
+ {
+ SpeculativeEvaluationRAII Speculate(Info, &Diag);
Diag.clear();
StmtVisitorTy::Visit(E->getTrueExpr());
if (Diag.empty())
@@ -4044,7 +4175,7 @@ private:
bool HandleConditionalOperator(const ConditionalOperator *E) {
bool BoolResult;
if (!EvaluateAsBooleanCondition(E->getCond(), BoolResult, Info)) {
- if (Info.checkingPotentialConstantExpression())
+ if (Info.checkingPotentialConstantExpression() && Info.noteFailure())
CheckPotentialConstantConditional(E);
return false;
}
@@ -4072,7 +4203,7 @@ public:
/// Report an evaluation error. This should only be called when an error is
/// first discovered. When propagating an error, just return false.
bool Error(const Expr *E, diag::kind D) {
- Info.Diag(E, D);
+ Info.FFDiag(E, D);
return false;
}
bool Error(const Expr *E) {
@@ -4275,7 +4406,7 @@ public:
const FunctionDecl *Definition = nullptr;
Stmt *Body = FD->getBody(Definition);
- if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition) ||
+ if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
!HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
Result, ResultSlot))
return false;
@@ -4397,7 +4528,7 @@ public:
if (BI + 1 == BE) {
const Expr *FinalExpr = dyn_cast<Expr>(*BI);
if (!FinalExpr) {
- Info.Diag((*BI)->getLocStart(),
+ Info.FFDiag((*BI)->getLocStart(),
diag::note_constexpr_stmt_expr_unsupported);
return false;
}
@@ -4412,7 +4543,7 @@ public:
// 'break', or 'continue', it would be nice to propagate that to
// the outer statement evaluation rather than bailing out.
if (ESR != ESR_Failed)
- Info.Diag((*BI)->getLocStart(),
+ Info.FFDiag((*BI)->getLocStart(),
diag::note_constexpr_stmt_expr_unsupported);
return false;
}
@@ -4425,6 +4556,15 @@ public:
void VisitIgnoredValue(const Expr *E) {
EvaluateIgnoredValue(Info, E);
}
+
+ /// Potentially visit a MemberExpr's base expression.
+ void VisitIgnoredBaseExpression(const Expr *E) {
+ // While MSVC doesn't evaluate the base expression, it does diagnose the
+ // presence of side-effecting behavior.
+ if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx))
+ return;
+ VisitIgnoredValue(E);
+ }
};
}
@@ -4651,7 +4791,7 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
return false;
if (V->isUninit()) {
if (!Info.checkingPotentialConstantExpression())
- Info.Diag(E, diag::note_constexpr_use_uninit_reference);
+ Info.FFDiag(E, diag::note_constexpr_use_uninit_reference);
return false;
}
return Success(*V, E);
@@ -4735,7 +4875,7 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
if (!E->isPotentiallyEvaluated())
return Success(E);
- Info.Diag(E, diag::note_constexpr_typeid_polymorphic)
+ Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic)
<< E->getExprOperand()->getType()
<< E->getExprOperand()->getSourceRange();
return false;
@@ -4748,14 +4888,14 @@ bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) {
// Handle static data members.
if (const VarDecl *VD = dyn_cast<VarDecl>(E->getMemberDecl())) {
- VisitIgnoredValue(E->getBase());
+ VisitIgnoredBaseExpression(E->getBase());
return VisitVarDecl(E, VD);
}
// Handle static member functions.
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) {
if (MD->isStatic()) {
- VisitIgnoredValue(E->getBase());
+ VisitIgnoredBaseExpression(E->getBase());
return Success(MD);
}
}
@@ -4823,7 +4963,7 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator(
// The overall lvalue result is the result of evaluating the LHS.
if (!this->Visit(CAO->getLHS())) {
- if (Info.keepEvaluatingAfterFailure())
+ if (Info.noteFailure())
Evaluate(RHS, this->Info, CAO->getRHS());
return false;
}
@@ -4844,7 +4984,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
APValue NewVal;
if (!this->Visit(E->getLHS())) {
- if (Info.keepEvaluatingAfterFailure())
+ if (Info.noteFailure())
Evaluate(NewVal, this->Info, E->getRHS());
return false;
}
@@ -4903,9 +5043,9 @@ public:
return false;
if (!Info.CurrentCall->This) {
if (Info.getLangOpts().CPlusPlus11)
- Info.Diag(E, diag::note_constexpr_this) << E->isImplicit();
+ Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit();
else
- Info.Diag(E);
+ Info.FFDiag(E);
return false;
}
Result = *Info.CurrentCall->This;
@@ -4932,7 +5072,7 @@ bool PointerExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
std::swap(PExp, IExp);
bool EvalPtrOK = EvaluatePointer(PExp, Result, Info);
- if (!EvalPtrOK && !Info.keepEvaluatingAfterFailure())
+ if (!EvalPtrOK && !Info.noteFailure())
return false;
llvm::APSInt Offset;
@@ -5135,7 +5275,7 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
// The offset must also have the correct alignment.
- if (OffsetResult.Offset.RoundUpToAlignment(Align) != OffsetResult.Offset) {
+ if (OffsetResult.Offset.alignTo(Align) != OffsetResult.Offset) {
Result.Designator.setInvalid();
APSInt Offset(64, false);
Offset = OffsetResult.Offset.getQuantity();
@@ -5265,14 +5405,21 @@ namespace {
Result = V;
return true;
}
- bool ZeroInitialization(const Expr *E);
+ bool ZeroInitialization(const Expr *E) {
+ return ZeroInitialization(E, E->getType());
+ }
+ bool ZeroInitialization(const Expr *E, QualType T);
bool VisitCallExpr(const CallExpr *E) {
return handleCallExpr(E, Result, &This);
}
bool VisitCastExpr(const CastExpr *E);
bool VisitInitListExpr(const InitListExpr *E);
- bool VisitCXXConstructExpr(const CXXConstructExpr *E);
+ bool VisitCXXConstructExpr(const CXXConstructExpr *E) {
+ return VisitCXXConstructExpr(E, E->getType());
+ }
+ bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
+ bool VisitCXXConstructExpr(const CXXConstructExpr *E, QualType T);
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
};
}
@@ -5327,8 +5474,8 @@ static bool HandleClassZeroInitialization(EvalInfo &Info, const Expr *E,
return true;
}
-bool RecordExprEvaluator::ZeroInitialization(const Expr *E) {
- const RecordDecl *RD = E->getType()->castAs<RecordType>()->getDecl();
+bool RecordExprEvaluator::ZeroInitialization(const Expr *E, QualType T) {
+ const RecordDecl *RD = T->castAs<RecordType>()->getDecl();
if (RD->isInvalidDecl()) return false;
if (RD->isUnion()) {
// C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
@@ -5348,7 +5495,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) {
}
if (isa<CXXRecordDecl>(RD) && cast<CXXRecordDecl>(RD)->getNumVBases()) {
- Info.Diag(E, diag::note_constexpr_virtual_base) << RD;
+ Info.FFDiag(E, diag::note_constexpr_virtual_base) << RD;
return false;
}
@@ -5417,12 +5564,34 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
return EvaluateInPlace(Result.getUnionValue(), Info, Subobject, InitExpr);
}
- assert((!isa<CXXRecordDecl>(RD) || !cast<CXXRecordDecl>(RD)->getNumBases()) &&
- "initializer list for class with base classes");
- Result = APValue(APValue::UninitStruct(), 0,
- std::distance(RD->field_begin(), RD->field_end()));
+ auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ if (Result.isUninit())
+ Result = APValue(APValue::UninitStruct(), CXXRD ? CXXRD->getNumBases() : 0,
+ std::distance(RD->field_begin(), RD->field_end()));
unsigned ElementNo = 0;
bool Success = true;
+
+ // Initialize base classes.
+ if (CXXRD) {
+ for (const auto &Base : CXXRD->bases()) {
+ assert(ElementNo < E->getNumInits() && "missing init for base class");
+ const Expr *Init = E->getInit(ElementNo);
+
+ LValue Subobject = This;
+ if (!HandleLValueBase(Info, Init, Subobject, CXXRD, &Base))
+ return false;
+
+ APValue &FieldVal = Result.getStructBase(ElementNo);
+ if (!EvaluateInPlace(FieldVal, Info, Subobject, Init)) {
+ if (!Info.noteFailure())
+ return false;
+ Success = false;
+ }
+ ++ElementNo;
+ }
+ }
+
+ // Initialize members.
for (const auto *Field : RD->fields()) {
// Anonymous bit-fields are not considered members of the class for
// purposes of aggregate initialization.
@@ -5452,7 +5621,7 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
if (!EvaluateInPlace(FieldVal, Info, Subobject, Init) ||
(Field->isBitField() && !truncateBitfieldValue(Info, Init,
FieldVal, Field))) {
- if (!Info.keepEvaluatingAfterFailure())
+ if (!Info.noteFailure())
return false;
Success = false;
}
@@ -5461,7 +5630,10 @@ bool RecordExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
return Success;
}
-bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
+bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
+ QualType T) {
+ // Note that E's type is not necessarily the type of our class here; we might
+ // be initializing an array element instead.
const CXXConstructorDecl *FD = E->getConstructor();
if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl()) return false;
@@ -5479,13 +5651,13 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
// lifetimes of all the base subobjects (there can be no data member
// subobjects in this case) per [basic.life]p1.
// Either way, ZeroInitialization is appropriate.
- return ZeroInitialization(E);
+ return ZeroInitialization(E, T);
}
const FunctionDecl *Definition = nullptr;
- FD->getBody(Definition);
+ auto Body = FD->getBody(Definition);
- if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
+ if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
return false;
// Avoid materializing a temporary for an elidable copy/move constructor.
@@ -5494,11 +5666,33 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E) {
= dyn_cast<MaterializeTemporaryExpr>(E->getArg(0)))
return Visit(ME->GetTemporaryExpr());
- if (ZeroInit && !ZeroInitialization(E))
+ if (ZeroInit && !ZeroInitialization(E, T))
return false;
auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
- return HandleConstructorCall(E->getExprLoc(), This, Args,
+ return HandleConstructorCall(E, This, Args,
+ cast<CXXConstructorDecl>(Definition), Info,
+ Result);
+}
+
+bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr(
+ const CXXInheritedCtorInitExpr *E) {
+ if (!Info.CurrentCall) {
+ assert(Info.checkingPotentialConstantExpression());
+ return false;
+ }
+
+ const CXXConstructorDecl *FD = E->getConstructor();
+ if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl())
+ return false;
+
+ const FunctionDecl *Definition = nullptr;
+ auto Body = FD->getBody(Definition);
+
+ if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
+ return false;
+
+ return HandleConstructorCall(E, This, Info.CurrentCall->Arguments,
cast<CXXConstructorDecl>(Definition), Info,
Result);
}
@@ -5902,7 +6096,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
Info, Subobject, Init) ||
!HandleLValueArrayAdjustment(Info, Init, Subobject,
CAT->getElementType(), 1)) {
- if (!Info.keepEvaluatingAfterFailure())
+ if (!Info.noteFailure())
return false;
Success = false;
}
@@ -5958,34 +6152,8 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
if (!Type->isRecordType())
return Error(E);
- const CXXConstructorDecl *FD = E->getConstructor();
-
- bool ZeroInit = E->requiresZeroInitialization();
- if (CheckTrivialDefaultConstructor(Info, E->getExprLoc(), FD, ZeroInit)) {
- if (HadZeroInit)
- return true;
-
- // See RecordExprEvaluator::VisitCXXConstructExpr for explanation.
- ImplicitValueInitExpr VIE(Type);
- return EvaluateInPlace(*Value, Info, Subobject, &VIE);
- }
-
- const FunctionDecl *Definition = nullptr;
- FD->getBody(Definition);
-
- if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition))
- return false;
-
- if (ZeroInit && !HadZeroInit) {
- ImplicitValueInitExpr VIE(Type);
- if (!EvaluateInPlace(*Value, Info, Subobject, &VIE))
- return false;
- }
-
- auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
- return HandleConstructorCall(E->getExprLoc(), Subobject, Args,
- cast<CXXConstructorDecl>(Definition),
- Info, *Value);
+ return RecordExprEvaluator(Info, Subobject, *Value)
+ .VisitCXXConstructExpr(E, Type);
}
//===----------------------------------------------------------------------===//
@@ -6076,7 +6244,7 @@ public:
}
bool VisitMemberExpr(const MemberExpr *E) {
if (CheckReferencedDecl(E, E->getMemberDecl())) {
- VisitIgnoredValue(E->getBase());
+ VisitIgnoredBaseExpression(E->getBase());
return true;
}
@@ -6149,7 +6317,7 @@ static bool EvaluateInteger(const Expr *E, APSInt &Result, EvalInfo &Info) {
if (!Val.isInt()) {
// FIXME: It would be better to produce the diagnostic for casting
// a pointer to an integer.
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
Result = Val.getInt();
@@ -6185,7 +6353,8 @@ bool IntExprEvaluator::CheckReferencedDecl(const Expr* E, const Decl* D) {
/// EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way
/// as GCC.
-static int EvaluateBuiltinClassifyType(const CallExpr *E) {
+static int EvaluateBuiltinClassifyType(const CallExpr *E,
+ const LangOptions &LangOpts) {
// The following enum mimics the values returned by GCC.
// FIXME: Does GCC differ between lvalue and rvalue references here?
enum gcc_type_class {
@@ -6205,37 +6374,123 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) {
if (E->getNumArgs() == 0)
return no_type_class;
- QualType ArgTy = E->getArg(0)->getType();
- if (ArgTy->isVoidType())
- return void_type_class;
- else if (ArgTy->isEnumeralType())
- return enumeral_type_class;
- else if (ArgTy->isBooleanType())
- return boolean_type_class;
- else if (ArgTy->isCharType())
- return string_type_class; // gcc doesn't appear to use char_type_class
- else if (ArgTy->isIntegerType())
- return integer_type_class;
- else if (ArgTy->isPointerType())
+ QualType CanTy = E->getArg(0)->getType().getCanonicalType();
+ const BuiltinType *BT = dyn_cast<BuiltinType>(CanTy);
+
+ switch (CanTy->getTypeClass()) {
+#define TYPE(ID, BASE)
+#define DEPENDENT_TYPE(ID, BASE) case Type::ID:
+#define NON_CANONICAL_TYPE(ID, BASE) case Type::ID:
+#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(ID, BASE) case Type::ID:
+#include "clang/AST/TypeNodes.def"
+ llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+
+ case Type::Builtin:
+ switch (BT->getKind()) {
+#define BUILTIN_TYPE(ID, SINGLETON_ID)
+#define SIGNED_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return integer_type_class;
+#define FLOATING_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: return real_type_class;
+#define PLACEHOLDER_TYPE(ID, SINGLETON_ID) case BuiltinType::ID: break;
+#include "clang/AST/BuiltinTypes.def"
+ case BuiltinType::Void:
+ return void_type_class;
+
+ case BuiltinType::Bool:
+ return boolean_type_class;
+
+ case BuiltinType::Char_U: // gcc doesn't appear to use char_type_class
+ case BuiltinType::UChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ return integer_type_class;
+
+ case BuiltinType::NullPtr:
+ return pointer_type_class;
+
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+ case BuiltinType::Id:
+#include "clang/Basic/OpenCLImageTypes.def"
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLNDRange:
+ case BuiltinType::OCLReserveID:
+ case BuiltinType::Dependent:
+ llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ };
+
+ case Type::Enum:
+ return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
+ break;
+
+ case Type::Pointer:
return pointer_type_class;
- else if (ArgTy->isReferenceType())
- return reference_type_class;
- else if (ArgTy->isRealType())
- return real_type_class;
- else if (ArgTy->isComplexType())
+ break;
+
+ case Type::MemberPointer:
+ if (CanTy->isMemberDataPointerType())
+ return offset_type_class;
+ else {
+ // We expect member pointers to be either data or function pointers,
+ // nothing else.
+ assert(CanTy->isMemberFunctionPointerType());
+ return method_type_class;
+ }
+
+ case Type::Complex:
return complex_type_class;
- else if (ArgTy->isFunctionType())
- return function_type_class;
- else if (ArgTy->isStructureOrClassType())
- return record_type_class;
- else if (ArgTy->isUnionType())
- return union_type_class;
- else if (ArgTy->isArrayType())
- return array_type_class;
- else if (ArgTy->isUnionType())
- return union_type_class;
- else // FIXME: offset_type_class, method_type_class, & lang_type_class?
+
+ case Type::FunctionNoProto:
+ case Type::FunctionProto:
+ return LangOpts.CPlusPlus ? function_type_class : pointer_type_class;
+
+ case Type::Record:
+ if (const RecordType *RT = CanTy->getAs<RecordType>()) {
+ switch (RT->getDecl()->getTagKind()) {
+ case TagTypeKind::TTK_Struct:
+ case TagTypeKind::TTK_Class:
+ case TagTypeKind::TTK_Interface:
+ return record_type_class;
+
+ case TagTypeKind::TTK_Enum:
+ return LangOpts.CPlusPlus ? enumeral_type_class : integer_type_class;
+
+ case TagTypeKind::TTK_Union:
+ return union_type_class;
+ }
+ }
llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ case Type::IncompleteArray:
+ return LangOpts.CPlusPlus ? array_type_class : pointer_type_class;
+
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::Auto:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::ObjCObjectPointer:
+ case Type::Pipe:
+ case Type::Atomic:
+ llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
+ }
+
+ llvm_unreachable("CallExpr::isBuiltinClassifyType(): unimplemented type");
}
/// EvaluateBuiltinConstantPForLValue - Determine the result of
@@ -6346,25 +6601,32 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) {
///
/// Please note: this function is specialized for how __builtin_object_size
/// views "objects".
+///
+/// If this encounters an invalid RecordDecl, it will always return true.
static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
assert(!LVal.Designator.Invalid);
- auto IsLastFieldDecl = [&Ctx](const FieldDecl *FD) {
- if (FD->getParent()->isUnion())
+ auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) {
+ const RecordDecl *Parent = FD->getParent();
+ Invalid = Parent->isInvalidDecl();
+ if (Invalid || Parent->isUnion())
return true;
- const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent());
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent);
return FD->getFieldIndex() + 1 == Layout.getFieldCount();
};
auto &Base = LVal.getLValueBase();
if (auto *ME = dyn_cast_or_null<MemberExpr>(Base.dyn_cast<const Expr *>())) {
if (auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
- if (!IsLastFieldDecl(FD))
- return false;
+ bool Invalid;
+ if (!IsLastOrInvalidFieldDecl(FD, Invalid))
+ return Invalid;
} else if (auto *IFD = dyn_cast<IndirectFieldDecl>(ME->getMemberDecl())) {
- for (auto *FD : IFD->chain())
- if (!IsLastFieldDecl(cast<FieldDecl>(FD)))
- return false;
+ for (auto *FD : IFD->chain()) {
+ bool Invalid;
+ if (!IsLastOrInvalidFieldDecl(cast<FieldDecl>(FD), Invalid))
+ return Invalid;
+ }
}
}
@@ -6387,8 +6649,9 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
return false;
BaseType = CT->getElementType();
} else if (auto *FD = getAsField(LVal.Designator.Entries[I])) {
- if (!IsLastFieldDecl(FD))
- return false;
+ bool Invalid;
+ if (!IsLastOrInvalidFieldDecl(FD, Invalid))
+ return Invalid;
BaseType = FD->getType();
} else {
assert(getAsBaseClass(LVal.Designator.Entries[I]) != nullptr &&
@@ -6607,7 +6870,7 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
case Builtin::BI__builtin_classify_type:
- return Success(EvaluateBuiltinClassifyType(E), E);
+ return Success(EvaluateBuiltinClassifyType(E, Info.getLangOpts()), E);
// FIXME: BI__builtin_clrsb
// FIXME: BI__builtin_clrsbl
@@ -6899,23 +7162,14 @@ class DataRecursiveIntBinOpEvaluator {
Job() = default;
Job(Job &&J)
: E(J.E), LHSResult(J.LHSResult), Kind(J.Kind),
- StoredInfo(J.StoredInfo), OldEvalStatus(J.OldEvalStatus) {
- J.StoredInfo = nullptr;
- }
+ SpecEvalRAII(std::move(J.SpecEvalRAII)) {}
void startSpeculativeEval(EvalInfo &Info) {
- OldEvalStatus = Info.EvalStatus;
- Info.EvalStatus.Diag = nullptr;
- StoredInfo = &Info;
- }
- ~Job() {
- if (StoredInfo) {
- StoredInfo->EvalStatus = OldEvalStatus;
- }
+ SpecEvalRAII = SpeculativeEvaluationRAII(Info);
}
+
private:
- EvalInfo *StoredInfo = nullptr; // non-null if status changed.
- Expr::EvalStatus OldEvalStatus;
+ SpeculativeEvaluationRAII SpecEvalRAII;
};
SmallVector<Job, 16> Queue;
@@ -6935,7 +7189,9 @@ public:
static bool shouldEnqueue(const BinaryOperator *E) {
return E->getOpcode() == BO_Comma ||
E->isLogicalOp() ||
- (E->getLHS()->getType()->isIntegralOrEnumerationType() &&
+ (E->isRValue() &&
+ E->getType()->isIntegralOrEnumerationType() &&
+ E->getLHS()->getType()->isIntegralOrEnumerationType() &&
E->getRHS()->getType()->isIntegralOrEnumerationType());
}
@@ -7017,7 +7273,7 @@ bool DataRecursiveIntBinOpEvaluator::
LHSResult.Failed = true;
// Since we weren't able to evaluate the left hand side, it
- // must have had side effects.
+ // might have had side effects.
if (!Info.noteSideEffect())
return false;
@@ -7033,7 +7289,7 @@ bool DataRecursiveIntBinOpEvaluator::
assert(E->getLHS()->getType()->isIntegralOrEnumerationType() &&
E->getRHS()->getType()->isIntegralOrEnumerationType());
- if (LHSResult.Failed && !Info.keepEvaluatingAfterFailure())
+ if (LHSResult.Failed && !Info.noteFailure())
return false; // Ignore RHS;
return true;
@@ -7185,10 +7441,34 @@ void DataRecursiveIntBinOpEvaluator::process(EvalResult &Result) {
llvm_unreachable("Invalid Job::Kind!");
}
+namespace {
+/// Used when we determine that we should fail, but can keep evaluating prior to
+/// noting that we had a failure.
+class DelayedNoteFailureRAII {
+ EvalInfo &Info;
+ bool NoteFailure;
+
+public:
+ DelayedNoteFailureRAII(EvalInfo &Info, bool NoteFailure = true)
+ : Info(Info), NoteFailure(NoteFailure) {}
+ ~DelayedNoteFailureRAII() {
+ if (NoteFailure) {
+ bool ContinueAfterFailure = Info.noteFailure();
+ (void)ContinueAfterFailure;
+ assert(ContinueAfterFailure &&
+ "Shouldn't have kept evaluating on failure.");
+ }
+ }
+};
+}
+
bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
+ // We don't call noteFailure immediately because the assignment happens after
+ // we evaluate LHS and RHS.
if (!Info.keepEvaluatingAfterFailure() && E->isAssignmentOp())
return Error(E);
+ DelayedNoteFailureRAII MaybeNoteFailureLater(Info, E->isAssignmentOp());
if (DataRecursiveIntBinOpEvaluator::shouldEnqueue(E))
return DataRecursiveIntBinOpEvaluator(*this, Result).Traverse(E);
@@ -7211,7 +7491,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else {
LHSOK = EvaluateComplex(E->getLHS(), LHS, Info);
}
- if (!LHSOK && !Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
if (E->getRHS()->getType()->isRealFloatingType()) {
@@ -7259,7 +7539,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat RHS(0.0), LHS(0.0);
bool LHSOK = EvaluateFloat(E->getRHS(), RHS, Info);
- if (!LHSOK && !Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
if (!EvaluateFloat(E->getLHS(), LHS, Info) || !LHSOK)
@@ -7293,7 +7573,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
LValue LHSValue, RHSValue;
bool LHSOK = EvaluatePointer(E->getLHS(), LHSValue, Info);
- if (!LHSOK && !Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
if (!EvaluatePointer(E->getRHS(), RHSValue, Info) || !LHSOK)
@@ -7387,7 +7667,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
// C, array of zero length). Pointer subtraction in such cases has
// undefined behavior, so is not constant.
if (ElementSize.isZero()) {
- Info.Diag(E, diag::note_constexpr_pointer_subtraction_zero_size)
+ Info.FFDiag(E, diag::note_constexpr_pointer_subtraction_zero_size)
<< ElementType;
return false;
}
@@ -7510,7 +7790,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
MemberPtr LHSValue, RHSValue;
bool LHSOK = EvaluateMemberPointer(E->getLHS(), LHSValue, Info);
- if (!LHSOK && Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
if (!EvaluateMemberPointer(E->getRHS(), RHSValue, Info) || !LHSOK)
@@ -8082,7 +8362,7 @@ bool FloatExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat RHS(0.0);
bool LHSOK = EvaluateFloat(E->getLHS(), Result, Info);
- if (!LHSOK && !Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
return EvaluateFloat(E->getRHS(), RHS, Info) && LHSOK &&
handleFloatFloatBinOp(Info, E, Result, E->getOpcode(), RHS);
@@ -8359,7 +8639,7 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
} else {
LHSOK = Visit(E->getLHS());
}
- if (!LHSOK && !Info.keepEvaluatingAfterFailure())
+ if (!LHSOK && !Info.noteFailure())
return false;
ComplexValue RHS;
@@ -8513,12 +8793,14 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat MaxCD = maxnum(abs(C), abs(D));
if (MaxCD.isFinite()) {
DenomLogB = ilogb(MaxCD);
- C = scalbn(C, -DenomLogB);
- D = scalbn(D, -DenomLogB);
+ C = scalbn(C, -DenomLogB, APFloat::rmNearestTiesToEven);
+ D = scalbn(D, -DenomLogB, APFloat::rmNearestTiesToEven);
}
APFloat Denom = C * C + D * D;
- ResR = scalbn((A * C + B * D) / Denom, -DenomLogB);
- ResI = scalbn((B * C - A * D) / Denom, -DenomLogB);
+ ResR = scalbn((A * C + B * D) / Denom, -DenomLogB,
+ APFloat::rmNearestTiesToEven);
+ ResI = scalbn((B * C - A * D) / Denom, -DenomLogB,
+ APFloat::rmNearestTiesToEven);
if (ResR.isNaN() && ResI.isNaN()) {
if (Denom.isPosZero() && (!A.isNaN() || !B.isNaN())) {
ResR = APFloat::getInf(ResR.getSemantics(), C.isNegative()) * A;
@@ -8758,10 +9040,10 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) {
if (!EvaluateAtomic(E, Result, Info))
return false;
} else if (Info.getLangOpts().CPlusPlus11) {
- Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType();
+ Info.FFDiag(E, diag::note_constexpr_nonliteral) << E->getType();
return false;
} else {
- Info.Diag(E, diag::note_invalid_subexpr_in_const_expr);
+ Info.FFDiag(E, diag::note_invalid_subexpr_in_const_expr);
return false;
}
@@ -8885,6 +9167,20 @@ bool Expr::EvaluateAsInt(APSInt &Result, const ASTContext &Ctx,
return true;
}
+bool Expr::EvaluateAsFloat(APFloat &Result, const ASTContext &Ctx,
+ SideEffectsKind AllowSideEffects) const {
+ if (!getType()->isRealFloatingType())
+ return false;
+
+ EvalResult ExprResult;
+ if (!EvaluateAsRValue(ExprResult, Ctx) || !ExprResult.Val.isFloat() ||
+ hasUnacceptableSideEffect(ExprResult, AllowSideEffects))
+ return false;
+
+ Result = ExprResult.Val.getFloat();
+ return true;
+}
+
bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const {
EvalInfo Info(Ctx, Result, EvalInfo::EM_ConstantFold);
@@ -9070,6 +9366,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::TypoExprClass:
case Expr::DependentScopeDeclRefExprClass:
case Expr::CXXConstructExprClass:
+ case Expr::CXXInheritedCtorInitExprClass:
case Expr::CXXStdInitializerListExprClass:
case Expr::CXXBindTemporaryExprClass:
case Expr::ExprWithCleanupsClass:
@@ -9089,6 +9386,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ObjCPropertyRefExprClass:
case Expr::ObjCSubscriptRefExprClass:
case Expr::ObjCIsaExprClass:
+ case Expr::ObjCAvailabilityCheckExprClass:
case Expr::ShuffleVectorExprClass:
case Expr::ConvertVectorExprClass:
case Expr::BlockExprClass:
@@ -9533,17 +9831,17 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
ArrayRef<const Expr*> Args;
- SourceLocation Loc = FD->getLocation();
-
APValue Scratch;
if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
// Evaluate the call as a constant initializer, to allow the construction
// of objects of non-literal types.
Info.setEvaluatingDecl(This.getLValueBase(), Scratch);
- HandleConstructorCall(Loc, This, Args, CD, Info, Scratch);
- } else
+ HandleConstructorCall(&VIE, This, Args, CD, Info, Scratch);
+ } else {
+ SourceLocation Loc = FD->getLocation();
HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
Args, FD->getBody(), Info, Scratch, nullptr);
+ }
return Diags.empty();
}
OpenPOWER on IntegriCloud