[cfe-commits] r150346 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Parse/ParseExprCXX.cpp lib/Sema/SemaCast.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/cxx0x-initializer-aggregates.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp test/SemaCXX/cxx98-compat.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Sun Feb 12 10:41:05 PST 2012


Author: cornedbee
Date: Sun Feb 12 12:41:05 2012
New Revision: 150346

URL: http://llvm.org/viewvc/llvm-project?rev=150346&view=rev
Log:
Proper initializer list support for new expressions and type construct expressions. Array new still missing.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
    cfe/trunk/test/SemaCXX/cxx98-compat.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Feb 12 12:41:05 2012
@@ -1232,6 +1232,8 @@
   "declaration of variable %0 with type %1 requires an initializer">;
 def err_auto_new_requires_ctor_arg : Error<
   "new expression for type %0 requires a constructor argument">;
+def err_auto_new_requires_parens : Error<
+  "new expression for type %0 cannot use list-initialization">;
 def err_auto_var_init_no_expression : Error<
   "initializer for variable %0 with type %1 is empty">;
 def err_auto_var_init_multiple_expressions : Error<
@@ -1257,6 +1259,10 @@
   "not found; include <initializer_list>">;
 def err_malformed_std_initializer_list : Error<
   "std::initializer_list must be a class template with a single type parameter">;
+def warn_dangling_std_initializer_list : Warning<
+  "array backing the initializer list will be destroyed at the end of "
+  "%select{the full-expression|the constructor}0">,
+  InGroup<DiagGroup<"dangling-initializer-list">>;
 
 // C++11 override control
 def override_keyword_only_allowed_on_virtual_member_functions : Error<

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Sun Feb 12 12:41:05 2012
@@ -1151,10 +1151,13 @@
          && "Expected '(' or '{'!");
 
   if (Tok.is(tok::l_brace)) {
-
-    // FIXME: Convert to a proper type construct expression.
-    return ParseBraceInitializer();
-
+    ExprResult Init = ParseBraceInitializer();
+    if (Init.isInvalid())
+      return Init;
+    Expr *InitList = Init.take();
+    return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(),
+                                             MultiExprArg(&InitList, 1),
+                                             SourceLocation());
   } else {
     GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
 

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Sun Feb 12 12:41:05 2012
@@ -77,7 +77,7 @@
     void CheckReinterpretCast();
     void CheckStaticCast();
     void CheckDynamicCast();
-    void CheckCXXCStyleCast(bool FunctionalCast);
+    void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
     void CheckCStyleCast();
 
     /// Complete an apparently-successful cast operation that yields
@@ -190,15 +190,15 @@
                                            QualType DestType, 
                                            Sema::CheckedConversionKind CCK,
                                            const SourceRange &OpRange,
-                                           unsigned &msg,
-                                           CastKind &Kind);
+                                           unsigned &msg, CastKind &Kind,
+                                           bool ListInitialization);
 static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
                                    QualType DestType, 
                                    Sema::CheckedConversionKind CCK,
                                    const SourceRange &OpRange,
-                                   unsigned &msg,
-                                   CastKind &Kind,
-                                   CXXCastPath &BasePath);
+                                   unsigned &msg, CastKind &Kind,
+                                   CXXCastPath &BasePath,
+                                   bool ListInitialization);
 static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
                                   bool CStyle, unsigned &msg);
 static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
@@ -752,7 +752,7 @@
   unsigned msg = diag::err_bad_cxx_cast_generic;
   TryCastResult tcr
     = TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
-                    Kind, BasePath);
+                    Kind, BasePath, /*ListInitialization=*/false);
   if (tcr != TC_Success && msg != 0) {
     if (SrcExpr.isInvalid())
       return;
@@ -782,8 +782,8 @@
                                    QualType DestType, 
                                    Sema::CheckedConversionKind CCK,
                                    const SourceRange &OpRange, unsigned &msg,
-                                   CastKind &Kind,
-                                   CXXCastPath &BasePath) {
+                                   CastKind &Kind, CXXCastPath &BasePath,
+                                   bool ListInitialization) {
   // Determine whether we have the semantics of a C-style cast.
   bool CStyle 
     = (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
@@ -808,23 +808,23 @@
   // C++ 5.2.9p5, reference downcast.
   // See the function for details.
   // DR 427 specifies that this is to be applied before paragraph 2.
-  tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange,
-                                   msg, Kind, BasePath);
+  tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle,
+                                   OpRange, msg, Kind, BasePath);
   if (tcr != TC_NotApplicable)
     return tcr;
 
   // C++0x [expr.static.cast]p3: 
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
   //   T2" if "cv2 T2" is reference-compatible with "cv1 T1".
-  tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath, 
-                              msg);
+  tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, 
+                              BasePath, msg);
   if (tcr != TC_NotApplicable)
     return tcr;
 
   // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
   //   [...] if the declaration "T t(e);" is well-formed, [...].
   tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
-                              Kind);
+                              Kind, ListInitialization);
   if (SrcExpr.isInvalid())
     return TC_Failed;
   if (tcr != TC_NotApplicable)
@@ -1295,7 +1295,7 @@
 TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
                       Sema::CheckedConversionKind CCK, 
                       const SourceRange &OpRange, unsigned &msg,
-                      CastKind &Kind) {
+                      CastKind &Kind, bool ListInitialization) {
   if (DestType->isRecordType()) {
     if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
                                  diag::err_bad_dynamic_cast_incomplete)) {
@@ -1304,15 +1304,13 @@
     }
   }
 
-  // FIXME: doesn't correctly identify T({1})
-  bool InitList = isa<InitListExpr>(SrcExpr.get());
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
   InitializationKind InitKind
     = (CCK == Sema::CCK_CStyleCast)
         ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
-                                               InitList)
+                                               ListInitialization)
     : (CCK == Sema::CCK_FunctionalCast)
-        ? InitializationKind::CreateFunctionalCast(OpRange, InitList)
+        ? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
     : InitializationKind::CreateCast(OpRange);
   Expr *SrcExprRaw = SrcExpr.get();
   InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1);
@@ -1756,7 +1754,8 @@
   return TC_Success;
 }                                     
 
-void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) {
+void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
+                                       bool ListInitialization) {
   // Handle placeholders.
   if (isPlaceholder()) {
     // C-style casts can resolve __unknown_any types.
@@ -1839,7 +1838,7 @@
   if (tcr == TC_NotApplicable) {
     // ... or if that is not possible, a static_cast, ignoring const, ...
     tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
-                        msg, Kind, BasePath);
+                        msg, Kind, BasePath, ListInitialization);
     if (SrcExpr.isInvalid())
       return;
 
@@ -2073,7 +2072,8 @@
   Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
 
   if (getLangOptions().CPlusPlus) {
-    Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false);
+    Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
+                          isa<InitListExpr>(CastExpr));
   } else {
     Op.CheckCStyleCast();
   }
@@ -2090,11 +2090,14 @@
                                             SourceLocation LPLoc,
                                             Expr *CastExpr,
                                             SourceLocation RPLoc) {
+  bool ListInitialization = LPLoc.isInvalid();
+  assert((!ListInitialization || isa<InitListExpr>(CastExpr)) &&
+         "List initialization must have initializer list as expression.");
   CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
   Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
   Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
 
-  Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true);
+  Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true, ListInitialization);
   if (Op.SrcExpr.isInvalid())
     return ExprError();
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Feb 12 12:41:05 2012
@@ -767,7 +767,6 @@
   unsigned NumExprs = exprs.size();
   Expr **Exprs = (Expr**)exprs.get();
   SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc();
-  SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc);
 
   if (Ty->isDependentType() ||
       CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) {
@@ -779,6 +778,12 @@
                                                     RParenLoc));
   }
 
+  bool ListInitialization = LParenLoc.isInvalid();
+  assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0])))
+         && "List initialization must have initializer list as expression.");
+  SourceRange FullRange = SourceRange(TyBeginLoc,
+      ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc);
+
   if (Ty->isArrayType())
     return ExprError(Diag(TyBeginLoc,
                           diag::err_value_init_for_array_type) << FullRange);
@@ -872,11 +877,24 @@
   return (del->getNumParams() == 2);
 }
 
-/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.:
+/// \brief Parsed a C++ 'new' expression (C++ 5.3.4).
+
+/// E.g.:
 /// @code new (memory) int[size][4] @endcode
 /// or
 /// @code ::new Foo(23, "hello") @endcode
-/// For the interpretation of this heap of arguments, consult the base version.
+///
+/// \param StartLoc The first location of the expression.
+/// \param UseGlobal True if 'new' was prefixed with '::'.
+/// \param PlacementLParen Opening paren of the placement arguments.
+/// \param PlacementArgs Placement new arguments.
+/// \param PlacementRParen Closing paren of the placement arguments.
+/// \param TypeIdParens If the type is in parens, the source range.
+/// \param D The type to be allocated, as well as array dimensions.
+/// \param ConstructorLParen Opening paren of the constructor args, empty if
+///                          initializer-list syntax is used.
+/// \param ConstructorArgs Constructor/initialization arguments.
+/// \param ConstructorRParen Closing paren of the constructor args.
 ExprResult
 Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal,
                   SourceLocation PlacementLParen, MultiExprArg PlacementArgs,
@@ -968,21 +986,25 @@
                             diag::err_auto_new_ctor_multiple_expressions)
                        << AllocType << TypeRange);
     }
+    Expr *Deduce = ConstructorArgs.get()[0];
+    if (ConstructorLParen.isInvalid()) {
+      return ExprError(Diag(Deduce->getSourceRange().getBegin(),
+                            diag::err_auto_new_requires_parens)
+                       << AllocType << TypeRange);
+    }
     TypeSourceInfo *DeducedType = 0;
-    if (DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType) ==
+    if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) ==
             DAR_Failed)
       return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure)
-                       << AllocType
-                       << ConstructorArgs.get()[0]->getType()
-                       << TypeRange
-                       << ConstructorArgs.get()[0]->getSourceRange());
+                       << AllocType << Deduce->getType()
+                       << TypeRange << Deduce->getSourceRange());
     if (!DeducedType)
       return ExprError();
 
     AllocTypeInfo = DeducedType;
     AllocType = AllocTypeInfo->getType();
   }
-  
+
   // Per C++0x [expr.new]p5, the type being constructed may be a
   // typedef of an array type.
   if (!ArraySize) {
@@ -998,6 +1020,17 @@
   if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange))
     return ExprError();
 
+  bool ListInitialization = ConstructorLParen.isInvalid() &&
+                            ConstructorArgs.size() > 0;
+  assert((!ListInitialization || (ConstructorArgs.size() == 1 &&
+                                  isa<InitListExpr>(ConstructorArgs.get()[0])))
+         && "List initialization means a braced-init-list for arguments.");
+  if (ListInitialization && isStdInitializerList(AllocType, 0)) {
+    Diag(AllocTypeInfo->getTypeLoc().getBeginLoc(),
+         diag::warn_dangling_std_initializer_list)
+      << /*at end of FE*/0 << ConstructorArgs.get()[0]->getSourceRange();
+  }
+
   // In ARC, infer 'retaining' for the allocated 
   if (getLangOptions().ObjCAutoRefCount &&
       AllocType.getObjCLifetime() == Qualifiers::OCL_None &&
@@ -1153,7 +1186,7 @@
     }
   }
 
-  bool Init = ConstructorLParen.isValid();
+  bool Init = ConstructorLParen.isValid() || ConstructorArgs.size() > 0;
   // --- Choosing a constructor ---
   CXXConstructorDecl *Constructor = 0;
   bool HadMultipleCandidates = false;
@@ -1172,7 +1205,7 @@
 
   if (!AllocType->isDependentType() &&
       !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {
-    // C++0x [expr.new]p15:
+    // C++11 [expr.new]p15:
     //   A new-expression that creates an object of type T initializes that
     //   object as follows:
     InitializationKind Kind
@@ -1182,9 +1215,12 @@
       = !Init? InitializationKind::CreateDefault(TypeRange.getBegin())
     //     - Otherwise, the new-initializer is interpreted according to the
     //       initialization rules of 8.5 for direct-initialization.
-             : InitializationKind::CreateDirect(TypeRange.getBegin(),
-                                                ConstructorLParen,
-                                                ConstructorRParen);
+             : ListInitialization ? InitializationKind::CreateDirectList(
+                                                          TypeRange.getBegin())
+                                  : InitializationKind::CreateDirect(
+                                                          TypeRange.getBegin(),
+                                                          ConstructorLParen,
+                                                          ConstructorRParen);
 
     InitializedEntity Entity
       = InitializedEntity::InitializeNew(StartLoc, AllocType);

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Sun Feb 12 12:41:05 2012
@@ -27,6 +27,13 @@
     S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
   }
 
+  void bracing_new() {
+    new S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+    new S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+    new S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+    new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+  }
+
   struct String {
     String(const char*);
   };

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Sun Feb 12 12:41:05 2012
@@ -25,7 +25,7 @@
   }
 
   void inline_init() {
-    (void) int{1};
+    auto v = int{1};
     (void) new int{1};
   }
 
@@ -59,5 +59,7 @@
   void edge_cases() {
     // FIXME: very poor error message
     int a({0}); // expected-error {{cannot initialize}}
+    (void) int({0}); // expected-error {{functional-style cast}}
+    new int({0});  // expected-error {{cannot initialize}}
   }
 }

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Sun Feb 12 12:41:05 2012
@@ -122,3 +122,8 @@
 
   for (int i : {1, 2, 3, 4}) {}
 }
+
+void dangle() {
+  new auto{1, 2, 3}; // expected-error {{cannot use list-initialization}}
+  new std::initializer_list<int>{1, 2, 3}; // expected-warning {{at the end of the full-expression}}
+}

Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=150346&r1=150345&r2=150346&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Sun Feb 12 12:41:05 2012
@@ -41,7 +41,8 @@
 int InitList() {
   (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
                     // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
-  (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+  (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+               // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
   int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
   return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
 }





More information about the cfe-commits mailing list