From 5cfc7d85fe13f144c9a8b264d6de9d38dfebc383 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 15 Mar 2012 04:53:45 +0000 Subject: [PATCH] Unrevert r152761 (reverted in r152772) with a fix for the issue which was breaking bootstrap. No test yet: it's quite hard to tickle the failure case. The specific testcase for this wouldn't be useful for testing anything more general than a reintroduction of this precise bug in any case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152775 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ExprConstant.cpp | 139 +++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 64 deletions(-) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7d65cf585b..b8b98da25d 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -480,9 +480,19 @@ namespace { return OptionalDiagnostic(); } + OptionalDiagnostic Diag(const Expr *E, diag::kind DiagId + = diag::note_invalid_subexpr_in_const_expr, + unsigned ExtraNotes = 0) { + if (EvalStatus.Diag) + return Diag(E->getExprLoc(), DiagId, ExtraNotes); + HasActiveDiagnostic = false; + return OptionalDiagnostic(); + } + /// Diagnose that the evaluation does not produce a C++11 core constant /// expression. - OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId + template + OptionalDiagnostic CCEDiag(LocArg Loc, diag::kind DiagId = diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes = 0) { // Don't override a previous diagnostic. @@ -556,7 +566,7 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, if (Invalid) return false; if (isOnePastTheEnd()) { - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_past_end_subobject) + Info.CCEDiag(E, diag::note_constexpr_past_end_subobject) << CSK; setInvalid(); return false; @@ -567,11 +577,11 @@ bool SubobjectDesignator::checkSubobject(EvalInfo &Info, const Expr *E, void SubobjectDesignator::diagnosePointerArithmetic(EvalInfo &Info, const Expr *E, uint64_t N) { if (MostDerivedPathLength == Entries.size() && MostDerivedArraySize) - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_array_index) + Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast(N) << /*array*/ 0 << static_cast(MostDerivedArraySize); else - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_array_index) + Info.CCEDiag(E, diag::note_constexpr_array_index) << static_cast(N) << /*non-array*/ 1; setInvalid(); } @@ -730,7 +740,7 @@ namespace { if (Designator.Invalid) return false; if (!Base) { - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_null_subobject) + Info.CCEDiag(E, diag::note_constexpr_null_subobject) << CSK; Designator.setInvalid(); return false; @@ -741,27 +751,30 @@ namespace { // Check this LValue refers to an object. If not, set the designator to be // invalid and emit a diagnostic. bool checkSubobject(EvalInfo &Info, const Expr *E, CheckSubobjectKind CSK) { + // Outside C++11, do not build a designator referring to a subobject of + // any object: we won't use such a designator for anything. + if (!Info.getLangOpts().CPlusPlus0x) + Designator.setInvalid(); return checkNullPointer(Info, E, CSK) && Designator.checkSubobject(Info, E, CSK); } void addDecl(EvalInfo &Info, const Expr *E, const Decl *D, bool Virtual = false) { - checkSubobject(Info, E, isa(D) ? CSK_Field : CSK_Base); - Designator.addDeclUnchecked(D, Virtual); + if (checkSubobject(Info, E, isa(D) ? CSK_Field : CSK_Base)) + Designator.addDeclUnchecked(D, Virtual); } void addArray(EvalInfo &Info, const Expr *E, const ConstantArrayType *CAT) { - checkSubobject(Info, E, CSK_ArrayToPointer); - Designator.addArrayUnchecked(CAT); + if (checkSubobject(Info, E, CSK_ArrayToPointer)) + Designator.addArrayUnchecked(CAT); } void addComplex(EvalInfo &Info, const Expr *E, QualType EltTy, bool Imag) { - checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real); - Designator.addComplexUnchecked(EltTy, Imag); + if (checkSubobject(Info, E, Imag ? CSK_Imag : CSK_Real)) + Designator.addComplexUnchecked(EltTy, Imag); } void adjustIndex(EvalInfo &Info, const Expr *E, uint64_t N) { - if (!checkNullPointer(Info, E, CSK_ArrayIndex)) - return; - Designator.adjustIndex(Info, E, N); + if (checkNullPointer(Info, E, CSK_ArrayIndex)) + Designator.adjustIndex(Info, E, N); } }; @@ -1020,10 +1033,10 @@ static bool CheckLiteralType(EvalInfo &Info, const Expr *E) { // Prvalue constant expressions must be of literal types. if (Info.getLangOpts().CPlusPlus0x) - Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral) + Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); else - Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1155,7 +1168,7 @@ static bool EvaluateAsBooleanCondition(const Expr *E, bool &Result, template static bool HandleOverflow(EvalInfo &Info, const Expr *E, const T &SrcValue, QualType DestType) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_overflow) + Info.Diag(E, diag::note_constexpr_overflow) << SrcValue << DestType; return false; } @@ -1240,7 +1253,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->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } unsigned BaseEltSize = EltAsInt.getBitWidth(); @@ -1253,7 +1266,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->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1414,7 +1427,7 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (Info.CheckingPotentialConstantExpression) return false; if (!Frame || !Frame->Arguments) { - Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = Frame->Arguments[PVD->getFunctionScopeIndex()]; @@ -1427,7 +1440,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->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1441,7 +1454,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->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1449,13 +1462,13 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E, // this in the cases where it matters for conformance. llvm::SmallVector Notes; if (!VD->evaluateValue(Notes)) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_var_init_non_constant, + Info.Diag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); return false; } else if (!VD->checkInitIsICE()) { - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_var_init_non_constant, + Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, Notes.size() + 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); Info.addNotes(Notes); @@ -1507,7 +1520,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // A diagnostic will have already been produced. return false; if (Sub.isOnePastTheEnd()) { - Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1529,7 +1542,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, if (CAT->getSize().ule(Index)) { // 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. - Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1551,7 +1564,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, // Next subobject is a complex number. uint64_t Index = Sub.Entries[I].ArrayIndex; if (Index > 1) { - Info.Diag(E->getExprLoc(), Info.getLangOpts().CPlusPlus0x ? + Info.Diag(E, Info.getLangOpts().CPlusPlus0x ? (unsigned)diag::note_constexpr_read_past_end : (unsigned)diag::note_invalid_subexpr_in_const_expr); return false; @@ -1568,7 +1581,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, return true; } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable()) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_ltor_mutable, 1) + Info.Diag(E, diag::note_constexpr_ltor_mutable, 1) << Field; Info.Note(Field->getLocation(), diag::note_declared_at); return false; @@ -1580,8 +1593,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { - Info.Diag(E->getExprLoc(), - diag::note_constexpr_read_inactive_union_member) + Info.Diag(E, diag::note_constexpr_read_inactive_union_member) << Field << !UnionField << UnionField; return false; } @@ -1593,11 +1605,11 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, if (ObjType.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { // FIXME: Include a description of the path to the volatile subobject. - Info.Diag(E->getExprLoc(), diag::note_constexpr_ltor_volatile_obj, 1) + Info.Diag(E, diag::note_constexpr_ltor_volatile_obj, 1) << 2 << Field; Info.Note(Field->getLocation(), diag::note_declared_at); } else { - Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); } return false; } @@ -1611,7 +1623,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E, if (O->isUninit()) { if (!Info.CheckingPotentialConstantExpression) - Info.Diag(E->getExprLoc(), diag::note_constexpr_read_uninit); + Info.Diag(E, diag::note_constexpr_read_uninit); return false; } } @@ -1702,11 +1714,10 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, return false; const Expr *Base = LVal.Base.dyn_cast(); - SourceLocation Loc = Conv->getExprLoc(); if (!LVal.Base) { // FIXME: Indirection through a null pointer deserves a specific diagnostic. - Info.Diag(Loc, diag::note_invalid_subexpr_in_const_expr); + Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1714,7 +1725,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, if (LVal.CallIndex) { Frame = Info.getCallFrame(LVal.CallIndex); if (!Frame) { - Info.Diag(Loc, diag::note_constexpr_lifetime_ended, 1) << !Base; + Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base; NoteLValueLocation(Info, LVal.Base); return false; } @@ -1726,9 +1737,9 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // semantics. if (Type.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) - Info.Diag(Loc, diag::note_constexpr_ltor_volatile_type) << Type; + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_type) << Type; else - Info.Diag(Loc); + Info.Diag(Conv); return false; } @@ -1742,7 +1753,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, if (const VarDecl *VDef = VD->getDefinition(Info.Ctx)) VD = VDef; if (!VD || VD->isInvalidDecl()) { - Info.Diag(Loc); + Info.Diag(Conv); return false; } @@ -1751,10 +1762,10 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, QualType VT = VD->getType(); if (VT.isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(Loc, diag::note_constexpr_ltor_volatile_obj, 1) << 1 << VD; + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 1 << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(Loc); + Info.Diag(Conv); } return false; } @@ -1765,10 +1776,10 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, } else if (VT->isIntegralOrEnumerationType()) { if (!VT.isConstQualified()) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(Loc, diag::note_constexpr_ltor_non_const_int, 1) << VD; + Info.Diag(Conv, diag::note_constexpr_ltor_non_const_int, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(Loc); + Info.Diag(Conv); } return false; } @@ -1777,18 +1788,18 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // static const data members of such types (supported as an extension) // more useful. if (Info.getLangOpts().CPlusPlus0x) { - Info.CCEDiag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + Info.CCEDiag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.CCEDiag(Loc); + Info.CCEDiag(Conv); } } else { // FIXME: Allow folding of values of any literal type in all languages. if (Info.getLangOpts().CPlusPlus0x) { - Info.Diag(Loc, diag::note_constexpr_ltor_non_constexpr, 1) << VD; + Info.Diag(Conv, diag::note_constexpr_ltor_non_constexpr, 1) << VD; Info.Note(VD->getLocation(), diag::note_declared_at); } else { - Info.Diag(Loc); + Info.Diag(Conv); } return false; } @@ -1812,7 +1823,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, if (unsigned CallIndex = RVal.getLValueCallIndex()) { Frame = Info.getCallFrame(CallIndex); if (!Frame) { - Info.Diag(Loc, diag::note_constexpr_lifetime_ended, 1) << !Base; + Info.Diag(Conv, diag::note_constexpr_lifetime_ended, 1) << !Base; NoteLValueLocation(Info, RVal.getLValueBase()); return false; } @@ -1824,10 +1835,10 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // Volatile temporary objects cannot be read in constant expressions. if (Base->getType().isVolatileQualified()) { if (Info.getLangOpts().CPlusPlus) { - Info.Diag(Loc, diag::note_constexpr_ltor_volatile_obj, 1) << 0; + Info.Diag(Conv, diag::note_constexpr_ltor_volatile_obj, 1) << 0; Info.Note(Base->getExprLoc(), diag::note_constexpr_temporary_here); } else { - Info.Diag(Loc); + Info.Diag(Conv); } return false; } @@ -1850,7 +1861,7 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv, // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant RVal = APValue(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0); } else { - Info.Diag(Conv->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(Conv, diag::note_invalid_subexpr_in_const_expr); return false; } @@ -1976,7 +1987,7 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, // Check this cast lands within the final derived-to-base subobject path. if (D.MostDerivedPathLength + E->path_size() > D.Entries.size()) { - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_downcast) + Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } @@ -1991,7 +2002,7 @@ static bool HandleBaseToDerivedCast(EvalInfo &Info, const CastExpr *E, else FinalType = getAsBaseClass(D.Entries[NewEntriesSize - 1]); if (FinalType->getCanonicalDecl() != TargetType->getCanonicalDecl()) { - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_downcast) + Info.CCEDiag(E, diag::note_constexpr_invalid_downcast) << D.MostDerivedType << TargetQT; return false; } @@ -2420,13 +2431,13 @@ protected: typedef ExprEvaluatorBase ExprEvaluatorBaseTy; OptionalDiagnostic CCEDiag(const Expr *E, diag::kind D) { - return Info.CCEDiag(E->getExprLoc(), D); + return Info.CCEDiag(E, D); } /// 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->getExprLoc(), D); + Info.Diag(E, D); return false; } bool Error(const Expr *E) { @@ -2957,7 +2968,7 @@ bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { return Success(E); CXXRecordDecl *RD = E->getExprOperand()->getType()->getAsCXXRecordDecl(); if (RD && RD->isPolymorphic()) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_typeid_polymorphic) + Info.Diag(E, diag::note_constexpr_typeid_polymorphic) << E->getExprOperand()->getType() << E->getExprOperand()->getSourceRange(); return false; @@ -3405,7 +3416,7 @@ bool RecordExprEvaluator::ZeroInitialization(const Expr *E) { } if (isa(RD) && cast(RD)->getNumVBases()) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_virtual_base) << RD; + Info.Diag(E, diag::note_constexpr_virtual_base) << RD; return false; } @@ -4115,7 +4126,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->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } Result = Val.getInt(); @@ -4338,10 +4349,10 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { case Builtin::BIstrlen: // A call to strlen is not a constant expression. if (Info.getLangOpts().CPlusPlus0x) - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_invalid_function) + Info.CCEDiag(E, diag::note_constexpr_invalid_function) << /*isConstexpr*/0 << /*isConstructor*/0 << "'strlen'"; else - Info.CCEDiag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); // Fall through. case Builtin::BI__builtin_strlen: // As an extension, we support strlen() and __builtin_strlen() as constant @@ -5981,17 +5992,17 @@ static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E) { Result = Info.CurrentCall->Temporaries[E]; } else if (E->getType()->isVoidType()) { if (Info.getLangOpts().CPlusPlus0x) - Info.CCEDiag(E->getExprLoc(), diag::note_constexpr_nonliteral) + Info.CCEDiag(E, diag::note_constexpr_nonliteral) << E->getType(); else - Info.CCEDiag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.CCEDiag(E, diag::note_invalid_subexpr_in_const_expr); if (!EvaluateVoid(E, Info)) return false; } else if (Info.getLangOpts().CPlusPlus0x) { - Info.Diag(E->getExprLoc(), diag::note_constexpr_nonliteral) << E->getType(); + Info.Diag(E, diag::note_constexpr_nonliteral) << E->getType(); return false; } else { - Info.Diag(E->getExprLoc(), diag::note_invalid_subexpr_in_const_expr); + Info.Diag(E, diag::note_invalid_subexpr_in_const_expr); return false; } -- 2.40.0