[cfe-commits] r135210 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp test/SemaCXX/aggregate-initialization.cpp test/SemaCXX/generalized-initializers.cpp

Rafael Espindola rafael.espindola at gmail.com
Thu Jul 14 15:58:04 PDT 2011


Author: rafael
Date: Thu Jul 14 17:58:04 2011
New Revision: 135210

URL: http://llvm.org/viewvc/llvm-project?rev=135210&view=rev
Log:
Revert 135177 to fix PR10363.

Revert "For C++11, do more checking of initializer lists up-front, enabling some subset of the final functionality. C just leaves the function early. C++98 runs through the same code path, but has no changed functionality either."

This reverts commit ac420c5053d6aa41d59f782caad9e46e5baaf2c2.

Added:
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
    cfe/trunk/test/SemaCXX/generalized-initializers.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=135210&r1=135209&r2=135210&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 14 17:58:04 2011
@@ -7,7 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file implements semantic analysis for initializers.
+// This file implements semantic analysis for initializers. The main entry
+// point is Sema::CheckInitList(), but all of the work is performed
+// within the InitListChecker class.
 //
 //===----------------------------------------------------------------------===//
 
@@ -710,7 +712,7 @@
   } else if (SemaRef.getLangOptions().CPlusPlus) {
     // C++ [dcl.init.aggr]p12:
     //   All implicit type conversions (clause 4) are considered when
-    //   initializing the aggregate member with an initializer from
+    //   initializing the aggregate member with an ini- tializer from
     //   an initializer-list. If the initializer can initialize a
     //   member, the member is initialized. [...]
 
@@ -2382,10 +2384,52 @@
   }
 }
 
-static void SelectInitialization(Sema &S, const InitializedEntity &Entity,
-                                 const InitializationKind &Kind,
-                                 Expr **Args, unsigned NumArgs,
-                                 InitializationSequence &Sequence);
+/// \brief Attempt list initialization (C++0x [dcl.init.list])
+static void TryListInitialization(Sema &S,
+                                  const InitializedEntity &Entity,
+                                  const InitializationKind &Kind,
+                                  InitListExpr *InitList,
+                                  InitializationSequence &Sequence) {
+  // FIXME: We only perform rudimentary checking of list
+  // initializations at this point, then assume that any list
+  // initialization of an array, aggregate, or scalar will be
+  // well-formed. When we actually "perform" list initialization, we'll
+  // do all of the necessary checking.  C++0x initializer lists will
+  // force us to perform more checking here.
+
+  QualType DestType = Entity.getType();
+
+  // C++ [dcl.init]p13:
+  //   If T is a scalar type, then a declaration of the form
+  //
+  //     T x = { a };
+  //
+  //   is equivalent to
+  //
+  //     T x = a;
+  if (DestType->isScalarType()) {
+    if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) {
+      Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+      return;
+    }
+
+    // Assume scalar initialization from a single value works.
+  } else if (DestType->isAggregateType()) {
+    // Assume aggregate initialization works.
+  } else if (DestType->isVectorType()) {
+    // Assume vector initialization works.
+  } else if (DestType->isReferenceType()) {
+    // FIXME: C++0x defines behavior for this.
+    Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
+    return;
+  } else if (DestType->isRecordType()) {
+    // FIXME: C++0x defines behavior for this
+    Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+  }
+
+  // Add a general "list initialization" step.
+  Sequence.AddListInitializationStep(DestType);
+}
 
 /// \brief Try a reference initialization that involves calling a conversion
 /// function.
@@ -3244,185 +3288,6 @@
     << src->getSourceRange();
 }
 
-static bool hasDefaultConstructor(Sema &S, CXXRecordDecl *decl) {
-  DeclContext::lookup_const_iterator Con, ConEnd;
-  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(decl);
-       Con != ConEnd; ++Con) {
-    // FIXME: A constructor template can be a default constructor, but we don't
-    // handle this in other places as well.
-    if (isa<FunctionTemplateDecl>(*Con))
-      continue;
-    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
-    if (Constructor->isDefaultConstructor())
-      return true;
-  }
-  return false;
-}
-
-/// \brief Attempt list initialization (C++0x [dcl.init.list])
-static void TryListInitialization(Sema &S,
-                                  const InitializedEntity &Entity,
-                                  const InitializationKind &Kind,
-                                  InitListExpr *InitList,
-                                  InitializationSequence &Sequence) {
-  QualType DestType = Entity.getType();
-
-  // If we're not in C++ mode, defer everything to the init list checker.
-  if (!S.getLangOptions().CPlusPlus) {
-    Sequence.AddListInitializationStep(DestType);
-    return;
-  }
-
-  // Early error return for some C++11 features when we're in 98 mode.
-  if (!S.getLangOptions().CPlusPlus0x) {
-    if (DestType->isReferenceType()) {
-      Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList);
-      return;
-    }
-    if (DestType->isRecordType() && !DestType->isAggregateType()) {
-      Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
-      return;
-    }
-  }
-
-  // If we have a reference and not exactly one initializer (see below), unwrap
-  // the reference.
-  bool wasReference = false;
-  if (InitList->getNumInits() != 1) {
-    if (const ReferenceType *ref = DestType->getAs<ReferenceType>()) {
-      wasReference = true;
-      DestType = ref->getPointeeType();
-    }
-  }
-  // Create an object that automatically adds a ref binding step on successful
-  // return.
-  class AddRefBinding {
-    InitializationSequence &Sequence;
-    bool Bind;
-    QualType RefType;
-  public:
-    AddRefBinding(InitializationSequence &sequence, bool bind, QualType refType)
-        : Sequence(sequence), Bind(bind), RefType(refType) {}
-    ~AddRefBinding() {
-      if (Bind && Sequence) {
-        Sequence.AddReferenceBindingStep(RefType, /*temporary*/true);
-      }
-    }
-  } addRefBinding(Sequence, wasReference, Entity.getType());
-
-  // C++11 [dcl.init.list]p3:
-  //   List-initialization of an object or reference of type T is defined as
-  //   follows:
-  //
-  //    - If the initializer list has no elements and T is a class type with
-  //      a default constructor, the object is value-initialized.
-  //
-  // See DR990. This case is handled specially because if we let it get to
-  // overload resolution, std::initializer_list constructors would be chosen
-  // over the default constructor. When there's more than one initlist ctor,
-  // this would actually be ambiguous and fail.
-
-  const RecordType *recordType = DestType->getAs<RecordType>();
-  CXXRecordDecl *recordDecl = recordType ?
-      dyn_cast<CXXRecordDecl>(recordType->getDecl()) : 0;
-  if (recordDecl && InitList->getNumInits() == 0 &&
-      hasDefaultConstructor(S, recordDecl)) {
-    TryValueInitialization(S, Entity, Kind, Sequence);
-    return;
-  }
-
-  //    - Otherwise, if T is an aggregate, aggregate initialization is
-  //      performed.
-  //
-  // Aggregate initialization is the most complicated part. We delegate to
-  // an InitListChecker to build a representation of what's happening.
-  // We also treat vector types the same as aggregates.
-  if (DestType->isAggregateType() || DestType->isVectorType()) {
-    // FIXME: Deeper analysis necessary.
-    Sequence.AddListInitializationStep(DestType);
-    return;
-  }
-
-  //    - Otherwise, if T is a specialization of std::initializer_list<E>, an
-  //      initializer_list object is constructed as described below and used
-  //      to initialize the object according to the rules for initialization
-  //      of an object from a class of the same type.
-  //
-  // FIXME: Implement this case.
-
-  //    - Otherwise, if T is a class type, constructors are considered. The
-  //      applicable constructors are enumerated and the best one is chosen
-  //      through overload resolution.
-  if (recordDecl) {
-    // FIXME: initializer_list constructors are applicable.
-    TryConstructorInitialization(S, Entity, Kind, InitList->getInits(),
-                                 InitList->getNumInits(), DestType, Sequence);
-    return;
-  }
-
-  // At this point, there is most likely a defect in the standard. The next
-  // bullet grabs all reference targets and creates temporaries from the init
-  // list. However, this means that code such as this doesn't work:
-  //   int i;
-  //   int &ri { i }; // error: non-const lvalue ref cannot bind to temporary.
-  // This is rather startling, since this code works:
-  //   int &si ( i );
-  //
-  // DR934 (CD2 status) tried to address the problem by making the bullet about
-  // references be only about references to class types, letting references to
-  // other things fall through. This means the above works, but this still
-  // doesn't:
-  //   string s;
-  //   string &rs { s }; // cannot bind to temporary
-  //   string &ss ( s ); // fine
-  // And this works, but has different semantics:
-  //   const string &cs { s }; // binds to temporary copy
-  //   const string &ds ( s ); // binds directly to s
-  // Also, the wording change from that DR somehow got lost in the FDIS.
-  //
-  // DR1095 (FDIS status) again discovered the problem, but didn't actually
-  // fix it.
-  //
-  // GCC implements it this way. We swap the next two bullets instead, thus
-  // always letting a reference bind to the single element of an initializer
-  // list, and constructing a temporary only if the isn't exactly one element.
-  // So in our order, the next bullet is:
-  //
-  //    - Otherwise, if the initializer list has a single element, the object
-  //      or reference is initialized from that element;
-  if (InitList->getNumInits() == 1) {
-    SelectInitialization(S, Entity, Kind, InitList->getInits(),
-                         InitList->getNumInits(), Sequence);
-    // Adjust the type of the whole init list to be the same as that of the
-    // single initializer.
-    InitList->setType(InitList->getInits()[0]->getType());
-    return;
-  }
-
-  //    - Otherwise, if T is a reference type, a prvalue temporary of the type
-  //      referenced by T is list-initialized, and the reference is bound to
-  //      that temporary.
-  //
-  // We implement this by unwrapping references at the start of the function
-  // and adding a reference binding step at the bottom.
-
-  //    - Otherwise, if the initializer list has no elements, the object is
-  //      value-initialized.
-  if (InitList->getNumInits() == 0) {
-    TryValueInitialization(S, Entity, Kind, Sequence);
-    return;
-  }
-
-  //    - Otherwise, the program is ill-formed.
-  //
-  // The only way to get here ought to be for scalar types with > 1 inits.
-  assert(DestType->isScalarType() && "Something strange is list-initialized.");
-  assert(InitList->getNumInits() > 1 && "Strange number of initializers.");
-
-  Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
-  return;
-}
-
 /// \brief Determine whether we have compatible array types for the
 /// purposes of GNU by-copy array initialization.
 static bool hasCompatibleArrayTypes(ASTContext &Context,
@@ -3495,6 +3360,7 @@
                                                Expr **Args,
                                                unsigned NumArgs)
     : FailedCandidateSet(Kind.getLocation()) {
+  ASTContext &Context = S.Context;
 
   // C++0x [dcl.init]p16:
   //   The semantics of initializers are as follows. The destination type is
@@ -3502,8 +3368,9 @@
   //   type is the type of the initializer expression. The source type is not
   //   defined when the initializer is a braced-init-list or when it is a
   //   parenthesized list of expressions.
+  QualType DestType = Entity.getType();
 
-  if (Entity.getType()->isDependentType() ||
+  if (DestType->isDependentType() ||
       Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
     SequenceKind = DependentSequence;
     return;
@@ -3512,22 +3379,11 @@
   // Almost everything is a normal sequence.
   setSequenceKind(NormalSequence);
 
-  SelectInitialization(S, Entity, Kind, Args, NumArgs, *this);
-}
-
-static void SelectInitialization(Sema &S, const InitializedEntity &Entity,
-                                 const InitializationKind &Kind,
-                                 Expr **Args, unsigned NumArgs,
-                                 InitializationSequence &Sequence) {
-  ASTContext &Context = S.Context;
-  QualType DestType = Entity.getType();
-
   for (unsigned I = 0; I != NumArgs; ++I)
     if (Args[I]->getObjectKind() == OK_ObjCProperty) {
       ExprResult Result = S.ConvertPropertyForRValue(Args[I]);
       if (Result.isInvalid()) {
-        Sequence.SetFailed(
-            InitializationSequence::FK_ConversionFromPropertyFailed);
+        SetFailed(FK_ConversionFromPropertyFailed);
         return;
       }
       Args[I] = Result.take();
@@ -3544,7 +3400,7 @@
   //     - If the initializer is a braced-init-list, the object is
   //       list-initialized (8.5.4).
   if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) {
-    TryListInitialization(S, Entity, Kind, InitList, Sequence);
+    TryListInitialization(S, Entity, Kind, InitList, *this);
     return;
   }
 
@@ -3556,22 +3412,22 @@
     //   by an object that can be converted into a T.
     // (Therefore, multiple arguments are not permitted.)
     if (NumArgs != 1)
-      Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference);
+      SetFailed(FK_TooManyInitsForReference);
     else
-      TryReferenceInitialization(S, Entity, Kind, Args[0], Sequence);
+      TryReferenceInitialization(S, Entity, Kind, Args[0], *this);
     return;
   }
 
   //     - If the initializer is (), the object is value-initialized.
   if (Kind.getKind() == InitializationKind::IK_Value ||
       (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) {
-    TryValueInitialization(S, Entity, Kind, Sequence);
+    TryValueInitialization(S, Entity, Kind, *this);
     return;
   }
 
   // Handle default initialization.
   if (Kind.getKind() == InitializationKind::IK_Default) {
-    TryDefaultInitialization(S, Entity, Kind, Sequence);
+    TryDefaultInitialization(S, Entity, Kind, *this);
     return;
   }
 
@@ -3582,7 +3438,7 @@
   //       ill-formed.
   if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) {
     if (Initializer && IsStringInit(Initializer, DestAT, Context)) {
-      TryStringLiteralInitialization(S, Entity, Kind, Initializer, Sequence);
+      TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this);
       return;
     }
 
@@ -3595,17 +3451,16 @@
       const ArrayType *SourceAT
         = Context.getAsArrayType(Initializer->getType());
       if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT))
-        Sequence.SetFailed(InitializationSequence::FK_ArrayTypeMismatch);
+        SetFailed(FK_ArrayTypeMismatch);
       else if (Initializer->HasSideEffects(S.Context))
-        Sequence.SetFailed(InitializationSequence::FK_NonConstantArrayInit);
+        SetFailed(FK_NonConstantArrayInit);
       else {
-        Sequence.AddArrayInitStep(DestType);
+        AddArrayInitStep(DestType);
       }
     } else if (DestAT->getElementType()->isAnyCharacterType())
-      Sequence.SetFailed(
-          InitializationSequence::FK_ArrayNeedsInitListOrStringLiteral);
+      SetFailed(FK_ArrayNeedsInitListOrStringLiteral);
     else
-      Sequence.SetFailed(InitializationSequence::FK_ArrayNeedsInitList);
+      SetFailed(FK_ArrayNeedsInitList);
 
     return;
   }
@@ -3620,13 +3475,13 @@
   if (!S.getLangOptions().CPlusPlus) {
     // If allowed, check whether this is an Objective-C writeback conversion.
     if (allowObjCWritebackConversion &&
-        tryObjCWritebackConversion(S, Sequence, Entity, Initializer)) {
+        tryObjCWritebackConversion(S, *this, Entity, Initializer)) {
       return;
     }
     
     // Handle initialization in C
-    Sequence.AddCAssignmentStep(DestType);
-    MaybeProduceObjCObject(S, Sequence, Entity);
+    AddCAssignmentStep(DestType);
+    MaybeProduceObjCObject(S, *this, Entity);
     return;
   }
 
@@ -3643,7 +3498,7 @@
          (Context.hasSameUnqualifiedType(SourceType, DestType) ||
           S.IsDerivedFrom(SourceType, DestType))))
       TryConstructorInitialization(S, Entity, Kind, Args, NumArgs,
-                                   Entity.getType(), Sequence);
+                                   Entity.getType(), *this);
     //     - Otherwise (i.e., for the remaining copy-initialization cases),
     //       user-defined conversion sequences that can convert from the source
     //       type to the destination type or (when a conversion function is
@@ -3651,12 +3506,12 @@
     //       13.3.1.4, and the best one is chosen through overload resolution
     //       (13.3).
     else
-      TryUserDefinedConversion(S, Entity, Kind, Initializer, Sequence);
+      TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
     return;
   }
 
   if (NumArgs > 1) {
-    Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar);
+    SetFailed(FK_TooManyInitsForScalar);
     return;
   }
   assert(NumArgs == 1 && "Zero-argument case handled above");
@@ -3664,8 +3519,8 @@
   //    - Otherwise, if the source type is a (possibly cv-qualified) class
   //      type, conversion functions are considered.
   if (!SourceType.isNull() && SourceType->isRecordType()) {
-    TryUserDefinedConversion(S, Entity, Kind, Initializer, Sequence);
-    MaybeProduceObjCObject(S, Sequence, Entity);
+    TryUserDefinedConversion(S, Entity, Kind, Initializer, *this);
+    MaybeProduceObjCObject(S, *this, Entity);
     return;
   }
 
@@ -3701,22 +3556,22 @@
       LvalueICS.Standard.setAsIdentityConversion();
       LvalueICS.Standard.setAllToTypes(ICS.Standard.getToType(0));
       LvalueICS.Standard.First = ICS.Standard.First;
-      Sequence.AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
+      AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));
     }
-
-    Sequence.AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
+    
+    AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);
   } else if (ICS.isBad()) {
     DeclAccessPair dap;
     if (Initializer->getType() == Context.OverloadTy && 
           !S.ResolveAddressOfOverloadedFunction(Initializer
                       , DestType, false, dap))
-      Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
+      SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
     else
-      Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
+      SetFailed(InitializationSequence::FK_ConversionFailed);
   } else {
-    Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+    AddConversionSequenceStep(ICS, Entity.getType());
 
-    MaybeProduceObjCObject(S, Sequence, Entity);
+    MaybeProduceObjCObject(S, *this, Entity);
   }
 }
 

Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp?rev=135210&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp Thu Jul 14 17:58:04 2011
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
+
+// An aggregate is an array or a class...
+struct Aggr {
+private:
+  static const int n;
+  void f();
+protected:
+  struct Inner { int m; };
+public:
+  bool &br;
+};
+bool b;
+Aggr ag = { b };
+
+// with no user-provided constructors, ...
+struct NonAggr1a {
+  NonAggr1a(int, int);
+  int k;
+};
+// In C++03, this is {{non-aggregate type 'NonAggr1a'}}.
+// In C++0x, 'user-provided' is only defined for special member functions, so
+// this type is considered to be an aggregate. This is probably a langauge
+// defect.
+NonAggr1a na1a = { 42 };
+
+struct NonAggr1b {
+  NonAggr1b(const NonAggr1b &);
+  int k;
+};
+NonAggr1b na1b = { 42 }; // expected-error {{non-aggregate type 'NonAggr1b'}}
+
+// no brace-or-equal-initializers for non-static data members, ...
+struct NonAggr2 {
+  int m = { 123 };
+};
+NonAggr2 na2 = { 42 }; // expected-error {{non-aggregate type 'NonAggr2'}}
+
+// no private...
+struct NonAggr3 {
+private:
+  int n;
+};
+NonAggr3 na3 = { 42 }; // expected-error {{non-aggregate type 'NonAggr3'}}
+
+// or protected non-static data members, ...
+struct NonAggr4 {
+protected:
+  int n;
+};
+NonAggr4 na4 = { 42 }; // expected-error {{non-aggregate type 'NonAggr4'}}
+
+// no base classes, ...
+struct NonAggr5 : Aggr {
+};
+NonAggr5 na5 = { b }; // expected-error {{non-aggregate type 'NonAggr5'}}
+
+// and no virtual functions.
+struct NonAggr6 {
+  virtual void f();
+  int n;
+};
+NonAggr6 na6 = { 42 }; // expected-error {{non-aggregate type 'NonAggr6'}}

Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=135210&r1=135209&r2=135210&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Thu Jul 14 17:58:04 2011
@@ -1,7 +1,9 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s 
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s 
 
 // Verify that we can't initialize non-aggregates with an initializer
 // list.
+// FIXME: Note that due to a (likely) standard bug, this is technically an
+//        aggregate.
 struct NonAggr1 {
   NonAggr1(int) { }
 
@@ -22,7 +24,7 @@
   virtual void f();
 };
 
-NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}}
+NonAggr1 na1 = { 17 };
 NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}}
 NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}}
 NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}
@@ -46,9 +48,8 @@
   A();
   A(int);
   ~A();
-
-private:
-  A(const A&) {} // expected-note 4 {{declared private here}}
+  
+  A(const A&) = delete; // expected-note 2 {{function has been explicitly marked deleted here}}
 };
 
 struct B {
@@ -61,10 +62,10 @@
 
 void f() {
   A as1[1] = { };
-  A as2[1] = { 1 }; // expected-error {{calling a private constructor of class 'A'}} expected-warning {{requires an accessible copy constructor}}
+  A as2[1] = { 1 }; // expected-error {{copying array element of type 'A' invokes deleted constructor}}
 
   B b1 = { };
-  B b2 = { 1 }; // expected-error {{field of type 'A' has private copy constructor}} expected-warning {{requires an accessible copy constructor}}
+  B b2 = { 1 }; // expected-error {{copying member subobject of type 'A' invokes deleted constructor}}
   
   C c1 = { 1 };
 }

Modified: cfe/trunk/test/SemaCXX/generalized-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generalized-initializers.cpp?rev=135210&r1=135209&r2=135210&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/generalized-initializers.cpp (original)
+++ cfe/trunk/test/SemaCXX/generalized-initializers.cpp Thu Jul 14 17:58:04 2011
@@ -224,39 +224,5 @@
     S s3{ 1, 2, 3, 4, 5, 6 }; // xpected-error
     S s4{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // xpected-error
     S s5{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // xpected-error
-    // May still omit stuff, though.
-    S s6{ {1}, {}, { {}, {} } };
   }
 }
-
-namespace references {
-  // From [dcl.init.list]p3 bullet 5:
-  struct S {
-    S(std::initializer_list<double>);
-    S(const std::string&);
-  };
-  void test() {
-    const S &r1 = { 1, 2, 3.0 }; // no-error (constructor #1)
-    const S &r2{ "Spinach" }; // no-error (constructor #2)
-    S &r3 = { 1, 2, 3 }; // xpected-error (binding to non-const)
-    const int &i1 = { 1 }; // no-error
-    const int &i2 = { 1.1 }; // xpected-error {{narrowing}}
-    const int (&iar)[2] = { 1, 2 }; // no-error
-
-    // Edge case: the standard says this must create a temporary and thus
-    // fail to bind, but that's almost certainly a defect.
-    int i;
-    int &ri1{ i };
-    int &ri2 = { i };
-    S s{ "Spinach" };
-    S &rs1{ s };
-    S &rs2 = { s };
-  }
-}
-
-namespace incomplete {
-  // Just to make sure it doesn't crash.
-  struct S;
-  S s { 1, 2, 3 }; // expected-error {{incomplete}}
-  S t = { 1, 2, 3 }; // expected-error {{incomplete}}
-}





More information about the cfe-commits mailing list