зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
58822c403c
Коммит
ab41fe914f
|
@ -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();
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -2354,9 +2354,10 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
|
|||
NoexceptExpr = E.take();
|
||||
if (!NoexceptExpr->isTypeDependent() &&
|
||||
!NoexceptExpr->isValueDependent())
|
||||
NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
|
||||
0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
|
||||
/*AllowFold*/ false).take();
|
||||
NoexceptExpr
|
||||
= SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
|
||||
0, diag::err_noexcept_needs_constant_expression,
|
||||
/*AllowFold*/ false).take();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1205,9 +1205,20 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
|
|||
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
|
||||
// If the size is an ICE, it certainly isn't a VLA. If we're in a GNU mode
|
||||
// (like gnu99, but not c99) accept any evaluatable value as an extension.
|
||||
return S.VerifyIntegerConstantExpression(
|
||||
ArraySize, &SizeVal, S.PDiag(), S.LangOpts.GNUMode,
|
||||
S.PDiag(diag::ext_vla_folded_to_constant)).isInvalid();
|
||||
class VLADiagnoser : public Sema::VerifyICEDiagnoser {
|
||||
public:
|
||||
VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
|
||||
|
||||
virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
|
||||
}
|
||||
|
||||
virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) {
|
||||
S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
|
||||
}
|
||||
} Diagnoser;
|
||||
|
||||
return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
|
||||
S.LangOpts.GNUMode).isInvalid();
|
||||
}
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче