diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-05-04 22:38:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-05-04 22:38:52 +0000 |
commit | ab41fe914f63bb470dfa7e400876ada72f57a931 (patch) | |
tree | e0aa909c06f48478c276804ff8180a4e9f8467f6 | |
parent | 58822c403cc8855adeecba92248612ee08dc1f3a (diff) |
Move Sema::VerifyIntegerConstantExpression() and
Sema::ConvertToIntegralOrEnumerationType() from PartialDiagnostics to
abstract "diagnoser" classes. Not much of a win here, but we're
-several PartialDiagnostics.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156217 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/Diagnostic.h | 11 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 84 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 174 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 79 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 53 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 58 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 17 |
12 files changed, 397 insertions, 116 deletions
diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index e1571786dd..80b49473db 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -781,13 +781,17 @@ class DiagnosticBuilder { void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT friend class DiagnosticsEngine; + + DiagnosticBuilder() + : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false) { } + explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true) { assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); } friend class PartialDiagnostic; - + protected: void FlushCounts() { DiagObj->NumDiagArgs = NumArgs; @@ -841,6 +845,11 @@ public: NumFixits = D.NumFixits; } + /// \brief Retrieve an empty diagnostic builder. + static DiagnosticBuilder getEmpty() { + return DiagnosticBuilder(); + } + /// Destructor - The dtor emits the diagnostic. ~DiagnosticBuilder() { Emit(); diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4c8a133e05..940eecbdde 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1463,6 +1463,8 @@ def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; def err_attribute_argument_not_int : Error< "'%0' attribute requires integer constant">; +def err_aligned_attribute_argument_not_int : Error< + "'aligned' attribute requires integer constant">; def err_attribute_argument_not_class : Error< "%0 attribute requires arguments that are class type or point to class type">; def err_attribute_first_argument_not_int_or_bool : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a3440086b8..c5bd25c7d7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1715,16 +1715,59 @@ public: ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); + /// \brief Abstract base class used to diagnose problems that occur while + /// trying to convert an expression to integral or enumeration type. + class ICEConvertDiagnoser { + public: + bool Suppress; + bool SuppressConversion; + + ICEConvertDiagnoser(bool Suppress = false, + bool SuppressConversion = false) + : Suppress(Suppress), SuppressConversion(SuppressConversion) { } + + /// \brief Emits a diagnostic complaining that the expression does not have + /// integral or enumeration type. + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a diagnostic when the expression has incomplete class type. + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a diagnostic when the only matching conversion function + /// is explicit. + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; + + /// \brief Emits a note for the explicit conversion function. + virtual DiagnosticBuilder + noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; + + /// \brief Emits a diagnostic when there are multiple possible conversion + /// functions. + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) = 0; + + /// \brief Emits a note for one of the candidate conversions. + virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) = 0; + + /// \brief Emits a diagnostic when we picked a conversion function + /// (for cases when we are not allowed to pick a conversion function). + virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) = 0; + + virtual ~ICEConvertDiagnoser() {} + }; + ExprResult ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, - const PartialDiagnostic &NotIntDiag, - const PartialDiagnostic &IncompleteDiag, - const PartialDiagnostic &ExplicitConvDiag, - const PartialDiagnostic &ExplicitConvNote, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag, + ICEConvertDiagnoser &Diagnoser, bool AllowScopedEnumerations); + enum ObjCSubscriptKind { OS_Array, OS_Dictionary, @@ -6738,20 +6781,29 @@ public: /// in the global scope. bool CheckObjCDeclScope(Decl *D); + /// \brief Abstract base class used for diagnosing integer constant + /// expression violations. + class VerifyICEDiagnoser { + public: + bool Suppress; + + VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { } + + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) =0; + virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR); + virtual ~VerifyICEDiagnoser() { } + }; + /// VerifyIntegerConstantExpression - Verifies that an expression is an ICE, /// and reports the appropriate diagnostics. Returns false on success. /// Can optionally return the value of the expression. ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - const PartialDiagnostic &Diag, - bool AllowFold, - const PartialDiagnostic &FoldDiag); + VerifyICEDiagnoser &Diagnoser, + bool AllowFold = true); ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - const PartialDiagnostic &Diag, - bool AllowFold = true) { - return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold, - PDiag(0)); - } - ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result = 0); + unsigned DiagID, + bool AllowFold = true); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result=0); /// VerifyBitField - verifies that a bit field expression is an ICE and has /// the correct width, and that the field type is valid. diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index ba1e69990f..af3fabb9d1 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2709,10 +2709,10 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E) { SourceLocation AttrLoc = AttrRange.getBegin(); // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); - ExprResult ICE = - VerifyIntegerConstantExpression(E, &Alignment, - PDiag(diag::err_attribute_argument_not_int) << "aligned", - /*AllowFold*/ false); + ExprResult ICE + = VerifyIntegerConstantExpression(E, &Alignment, + diag::err_aligned_attribute_argument_not_int, + /*AllowFold*/ false); if (ICE.isInvalid()) return; if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index e049121855..3c74f73163 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9906,7 +9906,7 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, llvm::APSInt Cond; if (VerifyIntegerConstantExpression(Converted.get(), &Cond, - PDiag(diag::err_static_assert_expression_is_not_constant), + diag::err_static_assert_expression_is_not_constant, /*AllowFold=*/false).isInvalid()) return 0; @@ -11302,7 +11302,7 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, if (!NoexceptExpr->isValueDependent()) NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0, - PDiag(diag::err_noexcept_needs_constant_expression), + diag::err_noexcept_needs_constant_expression, /*AllowFold*/ false).take(); EPI.NoexceptExpr = NoexceptExpr; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 36ba46b4f1..3ab0723ab0 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8868,8 +8868,9 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); - ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval, - PDiag(diag::err_typecheck_choose_expr_requires_constant), false); + ExprResult CondICE + = VerifyIntegerConstantExpression(CondExpr, &condEval, + diag::err_typecheck_choose_expr_requires_constant, false); if (CondICE.isInvalid()) return ExprError(); CondExpr = CondICE.take(); @@ -9452,15 +9453,44 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result) { - return VerifyIntegerConstantExpression(E, Result, - PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus); + class SimpleICEDiagnoser : public VerifyICEDiagnoser { + public: + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { + S.Diag(Loc, diag::err_expr_not_ice) << S.LangOpts.CPlusPlus << SR; + } + } Diagnoser; + + return VerifyIntegerConstantExpression(E, Result, Diagnoser); +} + +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result, + unsigned DiagID, + bool AllowFold) { + class IDDiagnoser : public VerifyICEDiagnoser { + unsigned DiagID; + + public: + IDDiagnoser(unsigned DiagID) + : VerifyICEDiagnoser(DiagID == 0), DiagID(DiagID) { } + + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { + S.Diag(Loc, DiagID) << SR; + } + } Diagnoser(DiagID); + + return VerifyIntegerConstantExpression(E, Result, Diagnoser, AllowFold); +} + +void Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc, + SourceRange SR) { + S.Diag(Loc, diag::ext_expr_not_ice) << SR << S.LangOpts.CPlusPlus; } ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, - const PartialDiagnostic &NotIceDiag, - bool AllowFold, - const PartialDiagnostic &FoldDiag) { + VerifyICEDiagnoser &Diagnoser, + bool AllowFold) { SourceLocation DiagLoc = E->getLocStart(); if (getLangOpts().CPlusPlus0x) { @@ -9470,23 +9500,111 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // have a single non-explicit conversion function to an integral or // unscoped enumeration type ExprResult Converted; - if (NotIceDiag.getDiagID()) { - Converted = ConvertToIntegralOrEnumerationType( - DiagLoc, E, - PDiag(diag::err_ice_not_integral), - PDiag(diag::err_ice_incomplete_type), - PDiag(diag::err_ice_explicit_conversion), - PDiag(diag::note_ice_conversion_here), - PDiag(diag::err_ice_ambiguous_conversion), - PDiag(diag::note_ice_conversion_here), - PDiag(0), - /*AllowScopedEnumerations*/ false); + if (!Diagnoser.Suppress) { + class CXX11ConvertDiagnoser : public ICEConvertDiagnoser { + public: + CXX11ConvertDiagnoser() : ICEConvertDiagnoser(false, true) { } + + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_ice_not_integral) << T; + } + + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, + SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_ice_incomplete_type) << T; + } + + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) { + return S.Diag(Loc, diag::err_ice_explicit_conversion) << T << ConvTy; + } + + virtual DiagnosticBuilder noteExplicitConv(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_ice_ambiguous_conversion) << T; + } + + virtual DiagnosticBuilder noteAmbiguous(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_ice_conversion_here) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseConversion(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + } ConvertDiagnoser; + + Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E, + ConvertDiagnoser, + /*AllowScopedEnumerations*/ false); } else { // The caller wants to silently enquire whether this is an ICE. Don't // produce any diagnostics if it isn't. - Converted = ConvertToIntegralOrEnumerationType( - DiagLoc, E, PDiag(), PDiag(), PDiag(), PDiag(), - PDiag(), PDiag(), PDiag(), false); + class SilentICEConvertDiagnoser : public ICEConvertDiagnoser { + public: + SilentICEConvertDiagnoser() : ICEConvertDiagnoser(true, true) { } + + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, + SourceLocation Loc, + QualType T) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder noteExplicitConv(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder noteAmbiguous(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + + virtual DiagnosticBuilder diagnoseConversion(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + } ConvertDiagnoser; + + Converted = ConvertToIntegralOrEnumerationType(DiagLoc, E, + ConvertDiagnoser, false); } if (Converted.isInvalid()) return Converted; @@ -9495,8 +9613,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, return ExprError(); } else if (!E->getType()->isIntegralOrUnscopedEnumerationType()) { // An ICE must be of integral or unscoped enumeration type. - if (NotIceDiag.getDiagID()) - Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + if (!Diagnoser.Suppress) + Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange()); return ExprError(); } @@ -9536,8 +9654,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, } if (!Folded || !AllowFold) { - if (NotIceDiag.getDiagID()) { - Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); + if (!Diagnoser.Suppress) { + Diagnoser.diagnoseNotICE(*this, DiagLoc, E->getSourceRange()); for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); } @@ -9545,11 +9663,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, return ExprError(); } - if (FoldDiag.getDiagID()) - Diag(DiagLoc, FoldDiag) << E->getSourceRange(); - else - Diag(DiagLoc, diag::ext_expr_not_ice) - << E->getSourceRange() << LangOpts.CPlusPlus; + Diagnoser.diagnoseFold(*this, DiagLoc, E->getSourceRange()); for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0e5d630e4a..7d987afe08 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -982,8 +982,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { - Array.NumElts = VerifyIntegerConstantExpression(NumElts, 0, - PDiag(diag::err_new_array_nonconst)).take(); + Array.NumElts + = VerifyIntegerConstantExpression(NumElts, 0, + diag::err_new_array_nonconst) + .take(); if (!Array.NumElts) return ExprError(); } @@ -1148,19 +1150,64 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // enumeration type, or a class type for which a single non-explicit // conversion function to integral or unscoped enumeration type exists. if (ArraySize && !ArraySize->isTypeDependent()) { - ExprResult ConvertedSize = ConvertToIntegralOrEnumerationType( - StartLoc, ArraySize, - PDiag(diag::err_array_size_not_integral) << getLangOpts().CPlusPlus0x, - PDiag(diag::err_array_size_incomplete_type) - << ArraySize->getSourceRange(), - PDiag(diag::err_array_size_explicit_conversion), - PDiag(diag::note_array_size_conversion), - PDiag(diag::err_array_size_ambiguous_conversion), - PDiag(diag::note_array_size_conversion), - PDiag(getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_array_size_conversion : - diag::ext_array_size_conversion), - /*AllowScopedEnumerations*/ false); + class SizeConvertDiagnoser : public ICEConvertDiagnoser { + Expr *ArraySize; + + public: + SizeConvertDiagnoser(Expr *ArraySize) + : ICEConvertDiagnoser(false, false), ArraySize(ArraySize) { } + + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_array_size_not_integral) + << S.getLangOpts().CPlusPlus0x << T; + } + + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_array_size_incomplete_type) + << T << ArraySize->getSourceRange(); + } + + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, + SourceLocation Loc, + QualType T, + QualType ConvTy) { + return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; + } + + virtual DiagnosticBuilder noteExplicitConv(Sema &S, + CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; + } + + virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) { + return S.Diag(Loc, + S.getLangOpts().CPlusPlus0x + ? diag::warn_cxx98_compat_array_size_conversion + : diag::ext_array_size_conversion) + << T << ConvTy->isEnumeralType() << ConvTy; + } + } SizeDiagnoser(ArraySize); + + ExprResult ConvertedSize + = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, SizeDiagnoser, + /*AllowScopedEnumerations*/ false); if (ConvertedSize.isInvalid()) return ExprError(); @@ -3610,7 +3657,7 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, llvm::APSInt Value; uint64_t Dim; if (Self.VerifyIntegerConstantExpression(DimExpr, &Value, - Self.PDiag(diag::err_dimension_expr_not_constant_integer), + diag::err_dimension_expr_not_constant_integer, false).isInvalid()) return 0; if (Value.isSigned() && Value.isNegative()) { diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index fb8ab47df6..007ea0fdcd 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5025,13 +5025,7 @@ static bool isIntegralOrEnumerationType(QualType T, bool AllowScopedEnum) { /// successful. ExprResult Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, - const PartialDiagnostic &NotIntDiag, - const PartialDiagnostic &IncompleteDiag, - const PartialDiagnostic &ExplicitConvDiag, - const PartialDiagnostic &ExplicitConvNote, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &AmbigNote, - const PartialDiagnostic &ConvDiag, + ICEConvertDiagnoser &Diagnoser, bool AllowScopedEnumerations) { // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) @@ -5055,22 +5049,23 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs<RecordType>(); if (!RecordTy || !getLangOpts().CPlusPlus) { - if (NotIntDiag.getDiagID()) - Diag(Loc, NotIntDiag) << T << From->getSourceRange(); + if (!Diagnoser.Suppress) + Diagnoser.diagnoseNotInt(*this, Loc, T) << From->getSourceRange(); return Owned(From); } // We must have a complete class type. struct TypeDiagnoserPartialDiag : TypeDiagnoser { - const PartialDiagnostic &PD; + ICEConvertDiagnoser &Diagnoser; + Expr *From; - TypeDiagnoserPartialDiag(const PartialDiagnostic &PD) - : TypeDiagnoser(PD.getDiagID() == 0), PD(PD) {} + TypeDiagnoserPartialDiag(ICEConvertDiagnoser &Diagnoser, Expr *From) + : TypeDiagnoser(Diagnoser.Suppress), Diagnoser(Diagnoser), From(From) {} virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) { - S.Diag(Loc, PD) << T; + Diagnoser.diagnoseIncomplete(S, Loc, T) << From->getSourceRange(); } - } IncompleteDiagnoser(IncompleteDiag); + } IncompleteDiagnoser(Diagnoser, From); if (RequireCompleteType(Loc, T, IncompleteDiagnoser)) return Owned(From); @@ -5102,7 +5097,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, switch (ViableConversions.size()) { case 0: - if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) { + if (ExplicitConversions.size() == 1 && !Diagnoser.Suppress) { DeclAccessPair Found = ExplicitConversions[0]; CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); @@ -5114,14 +5109,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, std::string TypeStr; ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy()); - Diag(Loc, ExplicitConvDiag) - << T << ConvTy + Diagnoser.diagnoseExplicitConv(*this, Loc, T, ConvTy) << FixItHint::CreateInsertion(From->getLocStart(), "static_cast<" + TypeStr + ">(") << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), ")"); - Diag(Conversion->getLocation(), ExplicitConvNote) - << ConvTy->isEnumeralType() << ConvTy; + Diagnoser.noteExplicitConv(*this, Conversion, ConvTy); // If we aren't in a SFINAE context, build a call to the // explicit conversion function. @@ -5152,12 +5145,12 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); QualType ConvTy = Conversion->getConversionType().getNonReferenceType(); - if (ConvDiag.getDiagID()) { + if (!Diagnoser.SuppressConversion) { if (isSFINAEContext()) return ExprError(); - Diag(Loc, ConvDiag) - << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); + Diagnoser.diagnoseConversion(*this, Loc, T, ConvTy) + << From->getSourceRange(); } ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion, @@ -5173,24 +5166,24 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, } default: - if (!AmbigDiag.getDiagID()) - return Owned(From); + if (Diagnoser.Suppress) + return ExprError(); - Diag(Loc, AmbigDiag) - << T << From->getSourceRange(); + Diagnoser.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange(); for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { CXXConversionDecl *Conv = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); QualType ConvTy = Conv->getConversionType().getNonReferenceType(); - Diag(Conv->getLocation(), AmbigNote) - << ConvTy->isEnumeralType() << ConvTy; + Diagnoser.noteAmbiguous(*this, Conv, ConvTy); } return Owned(From); } if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && - NotIntDiag.getDiagID()) - Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); + !Diagnoser.Suppress) { + Diagnoser.diagnoseNotInt(*this, Loc, From->getType()) + << From->getSourceRange(); + } return DefaultLvalueConversion(From); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 407323d5fa..77cc642b5e 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -521,16 +521,56 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, if (!Cond) return StmtError(); + class SwitchConvertDiagnoser : public ICEConvertDiagnoser { + Expr *Cond; + + public: + SwitchConvertDiagnoser(Expr *Cond) + : ICEConvertDiagnoser(false, true), Cond(Cond) { } + + virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_typecheck_statement_requires_integer) << T; + } + + virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_switch_incomplete_class_type) + << T << Cond->getSourceRange(); + } + + virtual DiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) { + return S.Diag(Loc, diag::err_switch_explicit_conversion) << T << ConvTy; + } + + virtual DiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, + QualType T) { + return S.Diag(Loc, diag::err_switch_multiple_conversions) << T; + } + + virtual DiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, + QualType ConvTy) { + return S.Diag(Conv->getLocation(), diag::note_switch_conversion) + << ConvTy->isEnumeralType() << ConvTy; + } + + virtual DiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, + QualType T, + QualType ConvTy) { + return DiagnosticBuilder::getEmpty(); + } + } SwitchDiagnoser(Cond); + CondResult - = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, - PDiag(diag::err_typecheck_statement_requires_integer), - PDiag(diag::err_switch_incomplete_class_type) - << Cond->getSourceRange(), - PDiag(diag::err_switch_explicit_conversion), - PDiag(diag::note_switch_conversion), - PDiag(diag::err_switch_multiple_conversions), - PDiag(diag::note_switch_conversion), - PDiag(0), + = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, SwitchDiagnoser, /*AllowScopedEnumerations*/ true); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 35d3cfa433..bde80fd5b1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4113,8 +4113,20 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Param->getLocation(), diag::note_template_param_here); return ExprError(); } else if (!Arg->isValueDependent()) { - Arg = VerifyIntegerConstantExpression(Arg, &Value, - PDiag(diag::err_template_arg_not_ice) << ArgType, false).take(); + class TmplArgICEDiagnoser : public VerifyICEDiagnoser { + QualType T; + + public: + TmplArgICEDiagnoser(QualType T) : T(T) { } + + virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, + SourceRange SR) { + S.Diag(Loc, diag::err_template_arg_not_ice) << T << SR; + } + } Diagnoser(ArgType); + + Arg = VerifyIntegerConstantExpression(Arg, &Value, Diagnoser, + false).take(); if (!Arg) return ExprError(); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 2da2fbcefd..51dffac59c 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2354,9 +2354,10 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, NoexceptExpr = E.take(); if (!NoexceptExpr->isTypeDependent() && !NoexceptExpr->isValueDependent()) - NoexceptExpr = SemaRef.VerifyInt |