diff options
-rw-r--r-- | include/clang/AST/Expr.h | 6 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 12 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 20 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 42 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 106 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 34 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 56 | ||||
-rw-r--r-- | test/CXX/except/except.spec/p1.cpp | 2 | ||||
-rw-r--r-- | test/CXX/expr/expr.const/p2-0x.cpp | 28 | ||||
-rw-r--r-- | test/Parser/cxx0x-attributes.cpp | 4 | ||||
-rw-r--r-- | test/Sema/i-c-e.c | 4 | ||||
-rw-r--r-- | test/Sema/switch.c | 7 | ||||
-rw-r--r-- | test/SemaCXX/enum-bitfield.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/i-c-e-cxx.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/new-delete.cpp | 6 |
22 files changed, 266 insertions, 174 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 591640d30c..33f95afd32 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -415,6 +415,9 @@ public: /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location /// of the invalid expression. + /// + /// Note: This does not perform the implicit conversions required by C++11 + /// [expr.const]p5. bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, SourceLocation *Loc = 0, bool isEvaluated = true) const; @@ -422,6 +425,9 @@ public: /// isCXX11ConstantExpr - Return true if this expression is a constant /// expression in C++11. Can only be used in C++. + /// + /// Note: This does not perform the implicit conversions required by C++11 + /// [expr.const]p5. bool isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result = 0, SourceLocation *Loc = 0) const; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2138d1de98..7eef491e48 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -31,6 +31,18 @@ def err_cce_narrowing : Error< "%select{case value|enumerator value|non-type template argument}0 " "%select{cannot be narrowed from type %2 to %3|" "evaluates to %2, which cannot be narrowed to type %3}1">; +def err_ice_not_integral : Error< + "integral constant expression must have integral or unscoped enumeration " + "type, not %0">; +def err_ice_incomplete_type : Error< + "integral constant expression has incomplete class type %0">; +def err_ice_explicit_conversion : Error< + "integral constant expression requires explicit conversion from %0 to %1">; +def note_ice_conversion_here : Note< + "conversion to %select{integral|enumeration}0 type %1 declared here">; +def err_ice_ambiguous_conversion : Error< + "ambiguous conversion from type %0 to an integral or unscoped " + "enumeration type">; // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2069dc9704..c5915ca168 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6120,17 +6120,25 @@ public: /// 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. - bool VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result = 0, - unsigned DiagId = 0, - bool AllowFold = true); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic Diag, + bool AllowFold, + PartialDiagnostic FoldDiag); + ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic Diag, + bool AllowFold = true) { + return VerifyIntegerConstantExpression(E, Result, Diag, AllowFold, + PDiag(0)); + } + 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. /// Returns false on success. /// Can optionally return whether the bit-field is of width 0 - bool VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth, - bool *ZeroWidth = 0); + ExprResult VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, Expr *BitWidth, + bool *ZeroWidth = 0); enum CUDAFunctionTarget { CFT_Device, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0e5e6781a6..b68591ae93 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -8465,9 +8465,10 @@ void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { } // Note that FieldName may be null for anonymous bitfields. -bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, - QualType FieldTy, const Expr *BitWidth, - bool *ZeroWidth) { +ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, + IdentifierInfo *FieldName, + QualType FieldTy, Expr *BitWidth, + bool *ZeroWidth) { // Default to true; that shouldn't confuse checks for emptiness if (ZeroWidth) *ZeroWidth = true; @@ -8477,7 +8478,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { // Handle incomplete types with specific error. if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) - return true; + return ExprError(); if (FieldName) return Diag(FieldLoc, diag::err_not_integral_type_bitfield) << FieldName << FieldTy << BitWidth->getSourceRange(); @@ -8485,16 +8486,18 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, << FieldTy << BitWidth->getSourceRange(); } else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth), UPPC_BitFieldWidth)) - return true; + return ExprError(); // If the bit-width is type- or value-dependent, don't try to check // it now. if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) - return false; + return Owned(BitWidth); llvm::APSInt Value; - if (VerifyIntegerConstantExpression(BitWidth, &Value)) - return true; + ExprResult ICE = VerifyIntegerConstantExpression(BitWidth, &Value); + if (ICE.isInvalid()) + return ICE; + BitWidth = ICE.take(); if (Value != 0 && ZeroWidth) *ZeroWidth = false; @@ -8534,7 +8537,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, } } - return false; + return Owned(BitWidth); } /// ActOnField - Each field of a C struct/union is passed into this in order @@ -8700,11 +8703,13 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, bool ZeroWidth = false; // If this is declared as a bit-field, check the bit-field. - if (!InvalidDecl && BitWidth && - VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { - InvalidDecl = true; - BitWidth = 0; - ZeroWidth = false; + if (!InvalidDecl && BitWidth) { + BitWidth = VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth).take(); + if (!BitWidth) { + InvalidDecl = true; + BitWidth = 0; + ZeroWidth = false; + } } // Check that 'mutable' is consistent with the type of the declaration. @@ -9027,10 +9032,9 @@ Decl *Sema::ActOnIvar(Scope *S, if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 - if (VerifyBitField(Loc, II, T, BitWidth)) { + BitWidth = VerifyBitField(Loc, II, T, BitWidth).take(); + if (!BitWidth) D.setInvalidType(); - BitWidth = 0; - } } else { // Not a bitfield. @@ -9591,9 +9595,9 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, else Val = Converted.take(); } else if (!Val->isValueDependent() && - VerifyIntegerConstantExpression(Val, &EnumVal)) { + !(Val = VerifyIntegerConstantExpression(Val, + &EnumVal).take())) { // C99 6.7.2.2p2: Make sure we have an integer constant expression. - Val = 0; } else { if (!getLangOptions().CPlusPlus) { // C99 6.7.2.2p2: diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index d1dc0de5cb..54e7969e0d 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2604,18 +2604,19 @@ 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); - if (!E->isIntegerConstantExpr(Alignment, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_not_int) - << "aligned" << E->getSourceRange(); + ExprResult ICE = + VerifyIntegerConstantExpression(E, &Alignment, + PDiag(diag::err_attribute_argument_not_int) << "aligned", + /*AllowFold*/ false); + if (ICE.isInvalid()) return; - } if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) << E->getSourceRange(); return; } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E)); + D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take())); } void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS) { diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 7a648939e0..f36750ba74 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -9918,10 +9918,16 @@ Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_); if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { + // In a static_assert-declaration, the constant-expression shall be a + // constant expression that can be contextually converted to bool. + ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); + if (Converted.isInvalid()) + return 0; + llvm::APSInt Cond; - if (VerifyIntegerConstantExpression(AssertExpr, &Cond, - diag::err_static_assert_expression_is_not_constant, - /*AllowFold=*/false)) + if (VerifyIntegerConstantExpression(Converted.get(), &Cond, + PDiag(diag::err_static_assert_expression_is_not_constant), + /*AllowFold=*/false).isInvalid()) return 0; if (!Cond) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3d8758e94e..3056156951 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -8544,11 +8544,11 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, } else { // The conditional expression is required to be a constant expression. llvm::APSInt condEval(32); - SourceLocation ExpLoc; - if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc)) - return ExprError(Diag(ExpLoc, - diag::err_typecheck_choose_expr_requires_constant) - << CondExpr->getSourceRange()); + ExprResult CondICE = VerifyIntegerConstantExpression(CondExpr, &condEval, + PDiag(diag::err_typecheck_choose_expr_requires_constant), false); + if (CondICE.isInvalid()) + return ExprError(); + CondExpr = CondICE.take(); // If the condition is > zero, then the AST type is the same as the LSHExpr. Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; @@ -9120,16 +9120,61 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, return isInvalid; } -bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result, - unsigned DiagID, bool AllowFold) { +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, + llvm::APSInt *Result) { + return VerifyIntegerConstantExpression(E, Result, + PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus); +} + +ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, + PartialDiagnostic NotIceDiag, + bool AllowFold, + PartialDiagnostic FoldDiag) { + SourceLocation DiagLoc = E->getSourceRange().getBegin(); + + if (getLangOptions().CPlusPlus0x) { + // C++11 [expr.const]p5: + // If an expression of literal class type is used in a context where an + // integral constant expression is required, then that class type shall + // 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); + } 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); + } + if (Converted.isInvalid()) + return Converted; + E = Converted.take(); + if (!E->getType()->isIntegralOrUnscopedEnumerationType()) + 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(); + return ExprError(); + } + // Circumvent ICE checking in C++11 to avoid evaluating the expression twice // in the non-ICE case. - if (!getLangOptions().CPlusPlus0x) { - if (E->isIntegerConstantExpr(Context)) { - if (Result) - *Result = E->EvaluateKnownConstInt(Context); - return false; - } + if (!getLangOptions().CPlusPlus0x && E->isIntegerConstantExpr(Context)) { + if (Result) + *Result = E->EvaluateKnownConstInt(Context); + return Owned(E); } Expr::EvalResult EvalResult; @@ -9147,36 +9192,39 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result, if (Folded && getLangOptions().CPlusPlus0x && Notes.empty()) { if (Result) *Result = EvalResult.Val.getInt(); - return false; + return Owned(E); + } + + // If our only note is the usual "invalid subexpression" note, just point + // the caret at its location rather than producing an essentially + // redundant note. + if (Notes.size() == 1 && Notes[0].second.getDiagID() == + diag::note_invalid_subexpr_in_const_expr) { + DiagLoc = Notes[0].first; + Notes.clear(); } if (!Folded || !AllowFold) { - if (DiagID) - Diag(E->getSourceRange().getBegin(), DiagID) << E->getSourceRange(); - else - Diag(E->getSourceRange().getBegin(), diag::err_expr_not_ice) - << E->getSourceRange() << LangOpts.CPlusPlus; - - // We only show the notes if they're not the usual "invalid subexpression" - // or if they are actually in a subexpression. - if (Notes.size() != 1 || - Notes[0].second.getDiagID() != diag::note_invalid_subexpr_in_const_expr - || Notes[0].first != E->IgnoreParens()->getExprLoc()) { + if (NotIceDiag.getDiagID()) { + Diag(DiagLoc, NotIceDiag) << E->getSourceRange(); for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); } - return true; + return ExprError(); } - Diag(E->getSourceRange().getBegin(), diag::ext_expr_not_ice) - << E->getSourceRange() << LangOpts.CPlusPlus; + if (FoldDiag.getDiagID()) + Diag(DiagLoc, FoldDiag) << E->getSourceRange(); + else + Diag(DiagLoc, diag::ext_expr_not_ice) + << E->getSourceRange() << LangOpts.CPlusPlus; for (unsigned I = 0, N = Notes.size(); I != N; ++I) Diag(Notes[I].first, Notes[I].second); if (Result) *Result = EvalResult.Val.getInt(); - return false; + return Owned(E); } namespace { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 158e02a450..e2a9f83a1f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -900,11 +900,11 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; if (Expr *NumElts = (Expr *)Array.NumElts) { - if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() && - !NumElts->isIntegerConstantExpr(Context)) { - Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst) - << NumElts->getSourceRange(); - return ExprError(); + if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { + Array.NumElts = VerifyIntegerConstantExpression(NumElts, 0, + PDiag(diag::err_new_array_nonconst)).take(); + if (!Array.NumElts) + return ExprError(); } } } @@ -1034,6 +1034,8 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // std::bad_array_new_length. if (!ArraySize->isValueDependent()) { llvm::APSInt Value; + // We've already performed any required implicit conversion to integer or + // unscoped enumeration type. if (ArraySize->isIntegerConstantExpr(Value, Context)) { if (Value < llvm::APSInt( llvm::APInt::getNullValue(Value.getBitWidth()), @@ -3269,18 +3271,16 @@ static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, case ATT_ArrayExtent: { llvm::APSInt Value; uint64_t Dim; - if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) { - if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) { - Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << - DimExpr->getSourceRange(); - return false; - } - Dim = Value.getLimitedValue(); - } else { - Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + if (Self.VerifyIntegerConstantExpression(DimExpr, &Value, + Self.PDiag(diag::err_dimension_expr_not_constant_integer), + false).isInvalid()) + return 0; + if (Value.isSigned() && Value.isNegative()) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer), DimExpr->getSourceRange(); - return false; + return 0; } + Dim = Value.getLimitedValue(); if (T->isArrayType()) { unsigned D = 0; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 096ca7c93b..aa45c8333a 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2150,26 +2150,27 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, } /// Check that the given Index expression is a valid array designator -/// value. This is essentailly just a wrapper around +/// value. This is essentially just a wrapper around /// VerifyIntegerConstantExpression that also checks for negative values /// and produces a reasonable diagnostic if there is a -/// failure. Returns true if there was an error, false otherwise. If -/// everything went okay, Value will receive the value of the constant -/// expression. -static bool +/// failure. Returns the index expression, possibly with an implicit cast +/// added, on success. If everything went okay, Value will receive the +/// value of the constant expression. +static ExprResult CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { SourceLocation Loc = Index->getSourceRange().getBegin(); // Make sure this is an integer constant expression. - if (S.VerifyIntegerConstantExpression(Index, &Value)) - return true; + ExprResult Result = S.VerifyIntegerConstantExpression(Index, &Value); + if (Result.isInvalid()) + return Result; if (Value.isSigned() && Value.isNegative()) return S.Diag(Loc, diag::err_array_designator_negative) << Value.toString(10) << Index->getSourceRange(); Value.setIsUnsigned(true); - return false; + return Result; } ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, @@ -2194,9 +2195,9 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, case Designator::ArrayDesignator: { Expr *Index = static_cast<Expr *>(D.getArrayIndex()); llvm::APSInt IndexValue; - if (!Index->isTypeDependent() && - !Index->isValueDependent() && - CheckArrayDesignatorExpr(*this, Index, IndexValue)) + if (!Index->isTypeDependent() && !Index->isValueDependent()) + Index = CheckArrayDesignatorExpr(*this, Index, IndexValue).take(); + if (!Index) Invalid = true; else { Designators.push_back(ASTDesignator(InitExpressions.size(), @@ -2216,10 +2217,13 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, StartIndex->isValueDependent(); bool EndDependent = EndIndex->isTypeDependent() || EndIndex->isValueDependent(); - if ((!StartDependent && - CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) || - (!EndDependent && - CheckArrayDesignatorExpr(*this, EndIndex, EndValue))) + if (!StartDependent) + StartIndex = + CheckArrayDesignatorExpr(*this, StartIndex, StartValue).take(); + if (!EndDependent) + EndIndex = CheckArrayDesignatorExpr(*this, EndIndex, EndValue).take(); + + if (!StartIndex || !EndIndex) Invalid = true; else { // Make sure we're comparing values with the same bit width. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9527c0f298..5fe136a166 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -4841,8 +4841,8 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs<RecordType>(); if (!RecordTy || !getLangOptions().CPlusPlus) { - Diag(Loc, NotIntDiag) - << T << From->getSourceRange(); + if (NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << T << From->getSourceRange(); return Owned(From); } @@ -4877,7 +4877,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, switch (ViableConversions.size()) { case 0: - if (ExplicitConversions.size() == 1) { + if (ExplicitConversions.size() == 1 && ExplicitConvDiag.getDiagID()) { DeclAccessPair Found = ExplicitConversions[0]; CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); @@ -4948,6 +4948,9 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, } default: + if (!AmbigDiag.getDiagID()) + return Owned(From); + Diag(Loc, AmbigDiag) << T << From->getSourceRange(); for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { @@ -4960,9 +4963,9 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, return Owned(From); } - if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations)) - Diag(Loc, NotIntDiag) - << From->getType() << From->getSourceRange(); + if (!isIntegralOrEnumerationType(From->getType(), AllowScopedEnumerations) && + NotIntDiag.getDiagID()) + Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); return DefaultLvalueConversion(From); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 42b608e631..e49bcfada6 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -274,15 +274,17 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, if (!getLangOptions().CPlusPlus0x) { // C99 6.8.4.2p3: The expression shall be an integer constant. // However, GCC allows any evaluatable integer expression. - if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() && - VerifyIntegerConstantExpression(LHSVal)) - return StmtError(); + if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) { + LHSVal = VerifyIntegerConstantExpression(LHSVal).take(); + if (!LHSVal) + return StmtError(); + } // GCC extension: The expression shall be an integer constant. - if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() && - VerifyIntegerConstantExpression(RHSVal)) { - RHSVal = 0; // Recover by just forgetting about it. + if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent()) { + RHSVal = VerifyIntegerConstantExpression(RHSVal).take(); + // Recover from an error by just forgetting about it. } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index eca491f733..421e5e2141 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3912,11 +3912,11 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return ExprError(); - } else if (!Arg->isValueDependent() && - !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) { - Diag(NonConstantLoc, diag::err_template_arg_not_ice) - << ArgType << Arg->getSourceRange(); - return ExprError(); + } else if (!Arg->isValueDependent()) { + Arg = VerifyIntegerConstantExpression(Arg, &Value, + PDiag(diag::err_template_arg_not_ice) << ArgType, false).take(); + if (!Arg) + return ExprError(); } // From here on out, all we care about are the unqualified forms diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 023005cd19..a957f25ef2 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2347,17 +2347,12 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart()); if (E.isUsable()) { - SourceLocation ErrLoc; - llvm::APSInt NoexceptVal; NoexceptExpr = E.take(); if (!NoexceptExpr->isTypeDependent() && - !NoexceptExpr->isValueDependent() && - !NoexceptExpr->isIntegerConstantExpr(NoexceptVal, SemaRef.Context, - &ErrLoc, /*evaluated=*/false)){ - SemaRef.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) - << NoexceptExpr->getSourceRange(); - NoexceptExpr = 0; - } + !NoexceptExpr->isValueDependent()) + NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr, + 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression), + /*AllowFold*/ false).take(); } } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 684f355bfb..d613c395d3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1178,19 +1178,12 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, /// Check whether the specified array size makes the array type a VLA. If so, /// return true, if not, return the size of the array in SizeVal. -static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) { - // If the size is an ICE, it certainly isn't a VLA. - if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context)) - return false; - - // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable - // value as an extension. - if (S.LangOpts.GNUMode && ArraySize->EvaluateAsInt(SizeVal, S.Context)) { - S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant); - return false; - } - - return true; +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(); } @@ -1285,14 +1278,15 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } // C99 6.7.5.2p1: The size expression shall have integer type. - // TODO: in theory, if we were insane, we could allow contextual - // conversions to integer type here. - if (ArraySize && !ArraySize->isTypeDependent() && + // C++11 allows contextual conversions to such types. + if (!getLangOptions().CPlusPlus0x && + ArraySize && !ArraySize->isTypeDependent() && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) << ArraySize->getType() << ArraySize->getSourceRange(); return QualType(); } + llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType())); if (!ArraySize) { if (ASM == ArrayType::Star) @@ -1301,11 +1295,19 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, T = Context.getIncompleteArrayType(T, ASM, Quals); } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) { T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); - } else if (!T->isDependentType() && !T->isIncompleteType() && - !T->isConstantSizeType()) { + } else if ((!T->isDependentType() && !T->isIncompleteType() && + !T->isConstantSizeType()) || + isArraySizeVLA(*this, ArraySize, ConstVal)) { + // Even in C++11, don't allow contextual conversions in the array bound + // of a VLA. + if (getLangOptions().CPlusPlus0x && + !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { + Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); + return QualType(); + } + // C99: an array with an element type that has a non-constant-size is a VLA. - T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); - } else if (isArraySizeVLA(ArraySize, ConstVal, *this)) { // C99: an array with a non-ICE size is a VLA. We accept any expression // that we can fold to a non-zero positive value as an extension. T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); @@ -2283,15 +2285,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, NoexceptExpr->getType()->getCanonicalTypeUnqualified() == Context.BoolTy) && "Parser should have made sure that the expression is boolean"); - SourceLocation ErrLoc; - llvm::APSInt Dummy; - if (!NoexceptExpr->isValueDependent() && - !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc, - /*evaluated*/false)) - S.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) - < |