[cfe-commits] r107229 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/new-array-size-conv.cpp test/SemaCXX/new-delete.cpp

Douglas Gregor dgregor at apple.com
Tue Jun 29 17:20:43 PDT 2010


Author: dgregor
Date: Tue Jun 29 19:20:43 2010
New Revision: 107229

URL: http://llvm.org/viewvc/llvm-project?rev=107229&view=rev
Log:
Implement C++ DR299, which allows an implicit conversion from a class
type to an integral or enumeration type in the size of an array new
expression, e.g.,

  new int[ConvertibleToInt(10)];

This is a GNU and C++0x extension.

Added:
    cfe/trunk/test/SemaCXX/new-array-size-conv.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/SemaCXX/new-delete.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 29 19:20:43 2010
@@ -2327,6 +2327,19 @@
   "'operator delete'">;
 def err_array_size_not_integral : Error<
   "array size expression must have integral or enumerated type, not %0">;
+def err_array_size_incomplete_type : Error<
+  "array size expression has incomplete class type %0">;
+def err_array_size_explicit_conversion : Error<
+  "array size expression of type %0 requires explicit conversion to type %1">;
+def note_array_size_conversion : Note<
+  "conversion to %select{integral|enumeration}0 type %1 declared here">;
+def err_array_size_ambiguous_conversion : Error<
+  "ambiguous conversion of array size expression of type %0 to an integral or "
+  "enumeration type">;
+def ext_array_size_conversion : Extension<
+  "implicit conversion from array size expression of type %0 to "
+  "%select{integral|enumeration}1 type %2 is a C++0x extension">;
+  
 def err_default_init_const : Error<
   "default initialization of an object of const type %0"
   "%select{| requires a user-provided default constructor}1">;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun 29 19:20:43 2010
@@ -1195,7 +1195,8 @@
                                      const PartialDiagnostic &ExplicitConvDiag,
                                      const PartialDiagnostic &ExplicitConvNote,
                                      const PartialDiagnostic &AmbigDiag,
-                                     const PartialDiagnostic &AmbigNote);
+                                     const PartialDiagnostic &AmbigNote,
+                                     const PartialDiagnostic &ConvDiag);
   
   bool PerformObjectMemberConversion(Expr *&From,
                                      NestedNameSpecifier *Qualifier,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Jun 29 19:20:43 2010
@@ -721,12 +721,29 @@
   //   or enumeration type with a non-negative value."
   Expr *ArraySize = (Expr *)ArraySizeE.get();
   if (ArraySize && !ArraySize->isTypeDependent()) {
+    
     QualType SizeType = ArraySize->getType();
     
+    OwningExprResult ConvertedSize
+      = ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE), 
+                                       PDiag(diag::err_array_size_not_integral),
+                                     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(getLangOptions().CPlusPlus0x? 0 
+                                            : diag::ext_array_size_conversion));
+    if (ConvertedSize.isInvalid())
+      return ExprError();
+    
+    ArraySize = ConvertedSize.takeAs<Expr>();
+    ArraySizeE = Owned(ArraySize);
+    SizeType = ArraySize->getType();
     if (!SizeType->isIntegralOrEnumerationType())
-      return ExprError(Diag(ArraySize->getSourceRange().getBegin(),
-                            diag::err_array_size_not_integral)
-        << SizeType << ArraySize->getSourceRange());
+      return ExprError();
+    
     // Let's see if this is a constant < 0. If so, we reject it out of hand.
     // We don't care about special rules, so we tell the machinery it's not
     // evaluated - it gives us a result in more cases.

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jun 29 19:20:43 2010
@@ -3075,10 +3075,35 @@
 /// integral or enumeration type, if that class type only has a single
 /// conversion to an integral or enumeration type.
 ///
-/// \param From The expression we're converting from.
+/// \param Loc The source location of the construct that requires the
+/// conversion.
 ///
-/// \returns The expression converted to an integral or enumeration type,
-/// if successful, or an invalid expression.
+/// \param FromE The expression we're converting from.
+///
+/// \param NotIntDiag The diagnostic to be emitted if the expression does not
+/// have integral or enumeration type.
+///
+/// \param IncompleteDiag The diagnostic to be emitted if the expression has
+/// incomplete class type.
+///
+/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an
+/// explicit conversion function (because no implicit conversion functions
+/// were available). This is a recovery mode.
+///
+/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag,
+/// showing which conversion was picked.
+///
+/// \param AmbigDiag The diagnostic to be emitted if there is more than one
+/// conversion function that could convert to integral or enumeration type.
+///
+/// \param AmbigNote The note to be emitted with \p AmbigDiag for each 
+/// usable conversion function.
+///
+/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion
+/// function, which may be an extension in this case.
+///
+/// \returns The expression, converted to an integral or enumeration type if
+/// successful.
 Sema::OwningExprResult 
 Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE,
                                          const PartialDiagnostic &NotIntDiag,
@@ -3086,7 +3111,8 @@
                                      const PartialDiagnostic &ExplicitConvDiag,
                                      const PartialDiagnostic &ExplicitConvNote,
                                          const PartialDiagnostic &AmbigDiag,
-                                         const PartialDiagnostic &AmbigNote) {
+                                         const PartialDiagnostic &AmbigNote,
+                                         const PartialDiagnostic &ConvDiag) {
   Expr *From = static_cast<Expr *>(FromE.get());
   
   // We can't perform any more checking for type-dependent expressions.
@@ -3111,7 +3137,7 @@
     
   // We must have a complete class type.
   if (RequireCompleteType(Loc, T, IncompleteDiag))
-    return ExprError();
+    return move(FromE);
   
   // Look for a conversion to an integral or enumeration type.
   UnresolvedSet<4> ViableConversions;
@@ -3174,6 +3200,19 @@
     // Apply this conversion.
     DeclAccessPair Found = ViableConversions[0];
     CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+    
+    CXXConversionDecl *Conversion
+      = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+    QualType ConvTy
+      = Conversion->getConversionType().getNonReferenceType();    
+    if (ConvDiag.getDiagID()) {
+      if (isSFINAEContext())
+        return ExprError();
+      
+      Diag(Loc, ConvDiag)
+        << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange();
+    }
+    
     From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found,
                           cast<CXXConversionDecl>(Found->getUnderlyingDecl()));
     FromE = Owned(From);

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Tue Jun 29 19:20:43 2010
@@ -435,7 +435,8 @@
                                    PDiag(diag::err_switch_explicit_conversion),
                                          PDiag(diag::note_switch_conversion),
                                    PDiag(diag::err_switch_multiple_conversions),
-                                         PDiag(diag::note_switch_conversion));
+                                         PDiag(diag::note_switch_conversion),
+                                         PDiag(0));
   if (ConvertedCond.isInvalid())
     return StmtError();
   

Added: cfe/trunk/test/SemaCXX/new-array-size-conv.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-array-size-conv.cpp?rev=107229&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/new-array-size-conv.cpp (added)
+++ cfe/trunk/test/SemaCXX/new-array-size-conv.cpp Tue Jun 29 19:20:43 2010
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -pedantic -verify %s
+
+struct ValueInt
+{
+  ValueInt(int v = 0) : ValueLength(v) {}
+  operator int () const { return ValueLength; } // expected-note 3{{conversion to integral type 'int' declared here}}
+private:
+  int ValueLength;
+};
+
+enum E { e };
+struct ValueEnum {
+  operator E() const; // expected-note{{conversion to enumeration type 'E' declared here}}
+};
+
+struct ValueBoth : ValueInt, ValueEnum { };
+
+struct IndirectValueInt : ValueInt { };
+struct TwoValueInts : ValueInt, IndirectValueInt { };
+
+void test() {
+  (void)new int[ValueInt(10)]; // expected-warning{{implicit conversion from array size expression of type 'ValueInt' to integral type 'int' is a C++0x extension}}
+  (void)new int[ValueEnum()]; // expected-warning{{implicit conversion from array size expression of type 'ValueEnum' to enumeration type 'E' is a C++0x extension}}
+  (void)new int[ValueBoth()]; // expected-error{{ambiguous conversion of array size expression of type 'ValueBoth' to an integral or enumeration type}}
+
+  (void)new int[TwoValueInts()]; // expected-error{{ambiguous conversion of array size expression of type 'TwoValueInts' to an integral or enumeration type}}
+}

Modified: cfe/trunk/test/SemaCXX/new-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/new-delete.cpp?rev=107229&r1=107228&r2=107229&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/new-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/new-delete.cpp Tue Jun 29 19:20:43 2010
@@ -287,3 +287,4 @@
   (void)new S2(); // expected-error {{is a private member}}
 }
 }
+





More information about the cfe-commits mailing list