]> granicus.if.org Git - clang/commitdiff
In C++11 mode, when an integral constant expression is desired and we have a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 4 Feb 2012 09:53:13 +0000 (09:53 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 4 Feb 2012 09:53:13 +0000 (09:53 +0000)
value of class type, look for a unique conversion operator converting to
integral or unscoped enumeration type and use that. Implements [expr.const]p5.

Sema::VerifyIntegerConstantExpression now performs the conversion and returns
the converted result. Some important callers of Expr::isIntegralConstantExpr
have been switched over to using it (including all of those required for C++11
conformance); this switch brings a side-benefit of improved diagnostics and, in
several cases, simpler code. However, some language extensions and attributes
have not been moved across and will not perform implicit conversions on
constant expressions of literal class type where an ICE is required.

In passing, fix static_assert to perform a contextual conversion to bool on its
argument.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149776 91177308-0d34-0410-b5e6-96231b3b80d8

22 files changed:
include/clang/AST/Expr.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaInit.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaType.cpp
test/CXX/except/except.spec/p1.cpp
test/CXX/expr/expr.const/p2-0x.cpp
test/Parser/cxx0x-attributes.cpp
test/Sema/i-c-e.c
test/Sema/switch.c
test/SemaCXX/enum-bitfield.cpp
test/SemaCXX/i-c-e-cxx.cpp
test/SemaCXX/new-delete.cpp

index 591640d30c70e02a8543efaf36b9844bc1a0618b..33f95afd32a8c22e80efc5c55fcd1423ae58b5d0 100644 (file)
@@ -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;
 
index 2138d1de98d83b25c48f7453fb781d463544fa27..7eef491e48ae237f4b38fa361a1c1d67fc7d2631 100644 (file)
@@ -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<
index 2069dc9704dec10f234b48108a79be23889ee26e..c5915ca168a0feff0bd2a324b0ff0b06f237b18b 100644 (file)
@@ -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,
index 0e5e6781a68e16cca4690b47fc6f143b77dd1dcb..b68591ae93da31c7e1d27bdef1408da5647eb048 100644 (file)
@@ -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:
index d1dc0de5cb168fe5488feaa2a4492a490f2b855e..54e7969e0d40326b8911bd0f8e196e6d9a3e8286 100644 (file)
@@ -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) {
index 7a648939e0a793b2cc91774be68666505828f342..f36750ba747a92a6aed8ff2414413d4ccd743a3e 100644 (file)
@@ -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)
index 3d8758e94e442a73129ba2893a2ae70b4ea0a718..3056156951e0ba508a8a8c5f054296d1b401df4b 100644 (file)
@@ -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 {
index 158e02a450e4e9d447658176374c022251df8f44..e2a9f83a1f356409e48de35a2a56bf94ee455038 100644 (file)
@@ -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;
index 096ca7c93bf54f4d81f31fc208274715d57266f9..aa45c8333ad018231b01374a19c1f8940b2ca701 100644 (file)
@@ -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.
index 9527c0f2982d669216385f860a252e5aa055da3a..5fe136a16626355dbc4a7717076d945deb8a2b86 100644 (file)
@@ -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);
 }
index 42b608e631d4f4d345a6d74324461bb479482c62..e49bcfada6573b0232101bbc97ea96047bcf1212 100644 (file)
@@ -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.
     }
   }
 
index eca491f733ed070225735ea03a4ea6e4a855594d..421e5e21416a70dde548b3d16f73b4e3d630af4b 100644 (file)
@@ -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
index 023005cd197fd6d0b37085bab736ebf2a973775e..a957f25ef2747e173a239c1622d51709be57d761 100644 (file)
@@ -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();
       }
     }
 
index 684f355bfbcdac5bb1c19f0b1d83cba0254fa651..d613c395d357fb6c35e2a885955cf584b144eec6 100644 (file)
@@ -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)
-                  << NoexceptExpr->getSourceRange();
-            else
-              EPI.NoexceptExpr = NoexceptExpr;
+            if (!NoexceptExpr->isValueDependent())
+              NoexceptExpr = S.VerifyIntegerConstantExpression(NoexceptExpr, 0,
+                S.PDiag(diag::err_noexcept_needs_constant_expression),
+                /*AllowFold*/ false).take();
+            EPI.NoexceptExpr = NoexceptExpr;
           }
         } else if (FTI.getExceptionSpecType() == EST_None &&
                    ImplicitlyNoexcept && chunkIndex == 0) {
index a6e785024778840c5b74dd6020368b6345deb5bd..c68ec56a24912baebca6724f5277d96d42f966a8 100644 (file)
@@ -74,7 +74,7 @@ namespace noexcept_unevaluated {
 
 namespace PR11084 {
   template<int X> struct A { 
-    static int f() noexcept(1/X) { return 10; }  // expected-error{{argument to noexcept specifier must be a constant expression}}
+    static int f() noexcept(1/X) { return 10; }  // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}
   };
 
   void g() { A<0>::f(); } // expected-note{{in instantiation of template class 'PR11084::A<0>' requested here}}
index 0b22151a878097e6d9db979174b93f7debb26726..ac759cb356dbfa30d580467e69afd628331f8ed6 100644 (file)
@@ -268,12 +268,14 @@ namespace LValueToRValue {
   //   non-volatile const object with a preceding initialization, initialized
   //   with a constant expression  [Note: a string literal (2.14.5 [lex.string])
   //   corresponds to an array of such objects. -end note], or
-  volatile const int vi = 1; // expected-note {{here}}
+  volatile const int vi = 1; // expected-note 2{{here}}
   const int ci = 1;
   volatile const int &vrci = ci;
-  static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}}
+  static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
   static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
-  static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+  static_assert(vrci, ""); // ok, vrci is converted to a prvalue before
+                           // evaluation and loses its volatility in the
+                           // conversion.
 
   // - a non-volatile glvalue of literal type that refers to a non-volatile
   //   object defined with constexpr, or that refers to a sub-object of such an
@@ -282,23 +284,23 @@ namespace LValueToRValue {
     constexpr S(int=0) : i(1), v(1) {}
     constexpr S(const S &s) : i(2), v(2) {}
     int i;
-    volatile int v;
+    volatile int v; // expected-note {{here}}
   };
   constexpr S s;
-  constexpr volatile S vs; // expected-note {{here}}
+  constexpr volatile S vs; // expected-note 2{{here}}
   constexpr const volatile S &vrs = s;
   static_assert(s.i, "");
-  static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
-  static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+  static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile member 'v'}}
+  static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}}
   static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}}
-  static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+  static_assert(vrs.i, ""); // ok
 
   // - a non-volatile glvalue of literal type that refers to a non-volatile
   //   temporary object whose lifetime has not ended, initialized with a
   //   constant expression;
   constexpr volatile S f() { return S(); }
   static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here!
-  static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+  static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}}
 }
 
 // DR1312: The proposed wording for this defect has issues, so we ignore this
@@ -385,7 +387,7 @@ namespace PseudoDtor {
   int k;
   typedef int I;
   struct T {
-    int n : (k.~I(), 0); // expected-error {{constant expression}} expected-note{{subexpression}}
+    int n : (k.~I(), 0); // expected-error {{constant expression}}
   };
 }
 
@@ -419,8 +421,8 @@ namespace TypeId {
 namespace NewDelete {
   int *p = 0;
   struct T {
-    int n : *new int(4); // expected-error {{constant expression}} expected-note {{subexpression}}
-    int m : (delete p, 2); // expected-error {{constant expression}} expected-note {{subexpression}}
+    int n : *new int(4); // expected-error {{constant expression}}
+    int m : (delete p, 2); // expected-error {{constant expression}}
   };
 }
 
@@ -540,7 +542,7 @@ namespace Assignment {
 // - a throw-expression (15.1)
 namespace Throw {
   struct S {
-    int n : (throw "hello", 10); // expected-error {{constant expression}} expected-note {{subexpression}}
+    int n : (throw "hello", 10); // expected-error {{constant expression}}
   };
 }
 
index ff9118a0e157c60d6fab4c6ea0db5d8eda0cbdf2..198da778cd0edeb1b3f95c2b504464f522d50f6d 100644 (file)
@@ -24,7 +24,7 @@ class foo {
 };
 extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
 [[]] template <typename T> void before_template_attr (); // expected-error {{an attribute list cannot appear here}}
-[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}}
+[[]] namespace ns { int i; } // expected-error {{an attribute list cannot appear here}} expected-note {{declared here}}
 [[]] static_assert(true, ""); //expected-error {{an attribute list cannot appear here}}
 [[]] asm(""); // expected-error {{an attribute list cannot appear here}}
 
@@ -33,7 +33,7 @@ extern "C++" [[]] { } // expected-error {{an attribute list cannot appear here}}
 
 // Argument tests
 alignas int aligned_no_params; // expected-error {{expected '('}}
-alignas(i) int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}}
+alignas(i) int aligned_nonconst; // expected-error {{'aligned' attribute requires integer constant}} expected-note {{read of non-const variable 'i'}}
 
 // Statement tests
 void foo () {
index a25bc1fec59f2b0e1ce7e4d5020e04fa73d25317..ee61ac34a81a4a01765047fc2d9c67d2a02d3b48 100644 (file)
@@ -19,9 +19,9 @@ char floatArith[(int)(1.0+2.0)]; // expected-warning {{must be an integer consta
 char b[__builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+2.0) : -1];
 
 struct c {
-  int a : (  // expected-error {{expression is not an integer constant expression}}
+  int a : (
            __builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+
-     expr  // expected-note {{subexpression not valid in a constant expression}}
+     expr // expected-error {{expression is not an integer constant expression}}
            ) : -1);
 };
 
index 2dc965f4a0bc91e1802eb02b2351472abac9ff6b..ea9be590244d22d26469d9a2676b7bb5a87d44ac 100644 (file)
@@ -50,12 +50,15 @@ void test4()
   }
   
   switch (cond) {
-  case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
+  case g() // expected-error {{expression is not an integer constant expression}}
+      && 0:
     break;
   }
   
   switch (cond) {
-  case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in a constant expression}}
+  case 0 ...
+      g() // expected-error {{expression is not an integer constant expression}}
+      || 1:
     break;
   }
 }
index 831b9825111b7bf505f767b8bc99bf92c05509f1..63445ca0583fa76ea90225e43b9eaf95ad962452 100644 (file)
@@ -14,5 +14,5 @@ struct X {
 
 struct Y {
   enum E : int(2);
-  enum E : Z(); // expected-error{{not an integral constant}}
+  enum E : Z(); // expected-error{{integral constant expression must have integral or unscoped enumeration type, not 'Z'}}
 };
index 0bfd221a4cb1f85869f0aa00a0c8c0bb959208ed..5631577e0fa9e158ce82075a6236eadd3d6bc5fe 100644 (file)
@@ -60,9 +60,9 @@ int* y = reinterpret_cast<const char&>(x); // expected-error {{cannot initialize
 
 // This isn't an integral constant expression, but make sure it folds anyway.
 struct PR8836 { char _; long long a; }; // expected-warning {{long long}}
-int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}}
+int PR8836test[(__typeof(sizeof(int)))&reinterpret_cast<const volatile char&>((((PR8836*)0)->a))]; // expected-warning {{folded to constant array as an extension}} expected-note {{cast which performs the conversions of a reinterpret_cast is not allowed in a constant expression}}
 
-const int nonconst = 1.0;
-int arr[nonconst]; // expected-warning {{folded to constant array as an extension}}
+const int nonconst = 1.0; // expected-note {{declared here}}
+int arr[nonconst]; // expected-warning {{folded to constant array as an extension}} expected-note {{initializer of 'nonconst' is not a constant expression}}
 const int castfloat = static_cast<int>(1.0);
 int arr2[castfloat]; // ok
index 45d4f3d0ec3c66e5712003e34731ee6e6304a073..4daa65efc224a9a63eaf3e0d7905202b3d0fad97 100644 (file)
@@ -61,13 +61,13 @@ struct abstract {
 
 void bad_news(int *ip)
 {
-  int i = 1;
+  int i = 1; // expected-note 2{{here}}
   (void)new; // expected-error {{expected a type}}
   (void)new 4; // expected-error {{expected a type}}
   (void)new () int; // expected-error {{expected expression}}
   (void)new int[1.1]; // expected-error {{array size expression must have integral or enumeration type, not 'double'}}
-  (void)new int[1][i]; // expected-error {{only the first dimension}}
-  (void)new (int[1][i]); // expected-error {{only the first dimension}}
+  (void)new int[1][i]; // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
+  (void)new (int[1][i]); // expected-error {{only the first dimension}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
   (void)new (int[i]); // expected-warning {{when type is in parentheses}}
   (void)new int(*(S*)0); // expected-error {{no viable conversion from 'S' to 'int'}}
   (void)new int(1, 2); // expected-error {{excess elements in scalar initializer}}