[cfe-commits] r153773 - in /cfe/trunk: include/clang/Basic/ include/clang/Sema/ lib/Sema/ test/CXX/dcl.decl/dcl.init/dcl.init.aggr/ test/CXX/special/class.copy/ test/CXX/special/class.ctor/ test/CXX/special/class.dtor/ test/SemaCXX/

Richard Smith richard-llvm at metafoo.co.uk
Fri Mar 30 13:53:29 PDT 2012


Author: rsmith
Date: Fri Mar 30 15:53:28 2012
New Revision: 153773

URL: http://llvm.org/viewvc/llvm-project?rev=153773&view=rev
Log:
PR10217: Provide diagnostics explaining why an implicitly-deleted special
member function is deleted.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
    cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
    cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
    cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
    cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
    cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp
    cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
    cfe/trunk/test/SemaCXX/cxx98-compat-flags.cpp
    cfe/trunk/test/SemaCXX/cxx98-compat.cpp
    cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp
    cfe/trunk/test/SemaCXX/dr1301.cpp
    cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
    cfe/trunk/test/SemaCXX/value-initialization.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar 30 15:53:28 2012
@@ -2821,6 +2821,37 @@
   "friend function %0 would be implicitly redefined in C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
 
+def note_deleted_dtor_no_operator_delete : Note<
+  "virtual destructor requires an unambiguous, accessible 'operator delete'">;
+def note_deleted_special_member_class_subobject : Note<
+  "%select{default constructor|copy constructor|move constructor|"
+  "copy assignment operator|move assignment operator|destructor}0 of "
+  "%select{||||union }4%1 is implicitly deleted because "
+  "%select{base class %3|field %3}2 has "
+  "%select{no|a deleted|multiple|an inaccessible|a non-trivial}4 "
+  "%select{%select{default constructor|copy constructor|move constructor|copy "
+  "assignment operator|move assignment operator|destructor}0|destructor}5"
+  "%select{||s||}4">;
+def note_deleted_default_ctor_uninit_field : Note<
+  "default constructor of %0 is implicitly deleted because field %1 of "
+  "%select{reference|const-qualified}3 type %2 would not be initialized">;
+def note_deleted_default_ctor_all_const : Note<
+  "default constructor of %0 is implicitly deleted because all "
+  "%select{data members|data members of an anonymous union member}1"
+  " are const-qualified">;
+def note_deleted_copy_ctor_rvalue_reference : Note<
+  "copy constructor of %0 is implicitly deleted because field %1 is of "
+  "rvalue reference type %2">;
+def note_deleted_copy_user_declared_move : Note<
+  "copy %select{constructor|assignment operator}0 is implicitly deleted because"
+  " %1 has a user-declared move %select{constructor|assignment operator}2">;
+def note_deleted_assign_field : Note<
+  "%select{copy|move}0 assignment operator of %0 is implicitly deleted "
+  "because field %1 is of %select{reference|const-qualified}3 type %2">;
+def note_deleted_move_assign_virtual_base : Note<
+  "move assignment operator of %0 is implicitly deleted because it has a "
+  "virtual base class %1">;
+
 // This should eventually be an error.
 def warn_undefined_internal : Warning<
   "%select{function|variable}0 %q1 has internal linkage but is not defined">,

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 30 15:53:28 2012
@@ -660,7 +660,17 @@
   /// This is used for determining parameter types of other objects and is
   /// utterly meaningless on other types of special members.
   class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode {
+  public:
+    enum Kind {
+      NoMemberOrDeleted,
+      Ambiguous,
+      SuccessNonConst,
+      SuccessConst
+    };
+
+  private:
     llvm::PointerIntPair<CXXMethodDecl*, 2> Pair;
+
   public:
     SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID)
       : FastFoldingSetNode(ID)
@@ -669,15 +679,11 @@
     CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
     void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
 
-    bool hasSuccess() const { return Pair.getInt() & 0x1; }
-    void setSuccess(bool B) {
-      Pair.setInt(unsigned(B) | hasConstParamMatch() << 1);
-    }
+    Kind getKind() const { return static_cast<Kind>(Pair.getInt()); }
+    void setKind(Kind K) { Pair.setInt(K); }
 
-    bool hasConstParamMatch() const { return Pair.getInt() & 0x2; }
-    void setConstParamMatch(bool B) {
-      Pair.setInt(B << 1 | unsigned(hasSuccess()));
-    }
+    bool hasSuccess() const { return getKind() >= SuccessNonConst; }
+    bool hasConstParamMatch() const { return getKind() == SuccessConst; }
   };
 
   /// \brief A cache of special member function overload resolution results
@@ -2421,6 +2427,7 @@
   bool CanUseDecl(NamedDecl *D);
   bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc,
                          const ObjCInterfaceDecl *UnknownObjCClass=0);
+  void NoteDeletedFunction(FunctionDecl *FD);
   std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD);
   bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD,
                                         ObjCMethodDecl *Getter,
@@ -3127,7 +3134,8 @@
 
   /// \brief Determine if a special member function should have a deleted
   /// definition when it is defaulted.
-  bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM);
+  bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                                 bool Diagnose = false);
 
   /// \brief Declare the implicit default constructor for the given class.
   ///

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Mar 30 15:53:28 2012
@@ -4333,6 +4333,7 @@
   Sema &S;
   CXXMethodDecl *MD;
   Sema::CXXSpecialMember CSM;
+  bool Diagnose;
 
   // Properties of the special member, computed for convenience.
   bool IsConstructor, IsAssignment, IsMove, ConstArg, VolatileArg;
@@ -4341,8 +4342,8 @@
   bool AllFieldsAreConst;
 
   SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
-                            Sema::CXXSpecialMember CSM)
-    : S(S), MD(MD), CSM(CSM),
+                            Sema::CXXSpecialMember CSM, bool Diagnose)
+    : S(S), MD(MD), CSM(CSM), Diagnose(Diagnose),
       IsConstructor(false), IsAssignment(false), IsMove(false),
       ConstArg(false), VolatileArg(false), Loc(MD->getLocation()),
       AllFieldsAreConst(true) {
@@ -4385,35 +4386,76 @@
                                  TQ & Qualifiers::Volatile);
   }
 
-  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, FieldDecl *Field);
+  typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;
 
-  bool shouldDeleteForBase(CXXRecordDecl *BaseDecl, bool IsVirtualBase);
+  bool shouldDeleteForBase(CXXBaseSpecifier *Base);
   bool shouldDeleteForField(FieldDecl *FD);
   bool shouldDeleteForAllConstMembers();
+
+  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj);
+  bool shouldDeleteForSubobjectCall(Subobject Subobj,
+                                    Sema::SpecialMemberOverloadResult *SMOR,
+                                    bool IsDtorCallInCtor);
 };
 }
 
+/// Check whether we should delete a special member due to the implicit
+/// definition containing a call to a special member of a subobject.
+bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
+    Subobject Subobj, Sema::SpecialMemberOverloadResult *SMOR,
+    bool IsDtorCallInCtor) {
+  CXXMethodDecl *Decl = SMOR->getMethod();
+  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
+
+  int DiagKind = -1;
+
+  if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
+    DiagKind = !Decl ? 0 : 1;
+  else if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
+    DiagKind = 2;
+  else if (S.CheckDirectMemberAccess(Loc, Decl, S.PDiag())
+             != Sema::AR_accessible)
+    DiagKind = 3;
+  else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
+           !Decl->isTrivial()) {
+    // A member of a union must have a trivial corresponding special member.
+    // As a weird special case, a destructor call from a union's constructor
+    // must be accessible and non-deleted, but need not be trivial. Such a
+    // destructor is never actually called, but is semantically checked as
+    // if it were.
+    DiagKind = 4;
+  }
+
+  if (DiagKind == -1)
+    return false;
+
+  if (Diagnose) {
+    if (Field) {
+      S.Diag(Field->getLocation(),
+             diag::note_deleted_special_member_class_subobject)
+        << CSM << MD->getParent() << /*IsField*/true
+        << Field << DiagKind << IsDtorCallInCtor;
+    } else {
+      CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
+      S.Diag(Base->getLocStart(),
+             diag::note_deleted_special_member_class_subobject)
+        << CSM << MD->getParent() << /*IsField*/false
+        << Base->getType() << DiagKind << IsDtorCallInCtor;
+    }
+
+    if (DiagKind == 1)
+      S.NoteDeletedFunction(Decl);
+    // FIXME: Explain inaccessibility if DiagKind == 3.
+  }
+
+  return true;
+}
+
 /// Check whether we should delete a special member function due to having a
 /// direct or virtual base class or static data member of class type M.
 bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
-    CXXRecordDecl *Class, FieldDecl *Field) {
-  // C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5:
-  // -- any direct or virtual base class [...] has a type with a destructor
-  //    that is deleted or inaccessible
-  if (!IsAssignment) {
-    CXXDestructorDecl *Dtor = S.LookupDestructor(Class);
-    if (Dtor->isDeleted())
-      return true;
-    if (S.CheckDestructorAccess(Loc, Dtor, S.PDiag()) != Sema::AR_accessible)
-      return true;
-
-    // C++11 [class.dtor]p5:
-    // -- X is a union-like class that has a variant member with a non-trivial
-    //    destructor
-    if (CSM == Sema::CXXDestructor && Field && Field->getParent()->isUnion() &&
-        !Dtor->isTrivial())
-      return true;
-  }
+    CXXRecordDecl *Class, Subobject Subobj) {
+  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
 
   // C++11 [class.ctor]p5:
   // -- any direct or virtual base class, or non-static data member with no
@@ -4426,58 +4468,62 @@
   //    overload resolution, as applied to B's corresponding special member,
   //    results in an ambiguity or a function that is deleted or inaccessible
   //    from the defaulted special member
-  if (CSM != Sema::CXXDestructor &&
-      !(CSM == Sema::CXXDefaultConstructor &&
+  // C++11 [class.dtor]p5:
+  // -- any direct or virtual base class [...] has a type with a destructor
+  //    that is deleted or inaccessible
+  if (!(CSM == Sema::CXXDefaultConstructor &&
         Field && Field->hasInClassInitializer())) {
     Sema::SpecialMemberOverloadResult *SMOR = lookupIn(Class);
-    if (!SMOR->hasSuccess())
-      return true;
-
     CXXMethodDecl *Member = SMOR->getMethod();
-    // A member of a union must have a trivial corresponding special member.
-    if (Field && Field->getParent()->isUnion() && !Member->isTrivial())
+    if (shouldDeleteForSubobjectCall(Subobj, SMOR, false))
       return true;
 
-    if (IsConstructor) {
+    // FIXME: CWG 1402 moves these bullets elsewhere.
+    if (CSM == Sema::CXXMoveConstructor) {
       CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(Member);
-      if (S.CheckConstructorAccess(Loc, Ctor, Ctor->getAccess(), S.PDiag())
-            != Sema::AR_accessible)
-        return true;
-
       // -- for the move constructor, a [...] direct or virtual base class with
       //    a type that does not have a move constructor and is not trivially
       //    copyable.
-      if (IsMove && !Ctor->isMoveConstructor() && !Class->isTriviallyCopyable())
+      if (!Ctor->isMoveConstructor() && !Class->isTriviallyCopyable())
         return true;
-    } else {
-      assert(IsAssignment && "unexpected kind of special member");
-      if (S.CheckDirectMemberAccess(Loc, Member, S.PDiag())
-            != Sema::AR_accessible)
-        return true;
-
+    } else if (CSM == Sema::CXXMoveAssignment) {
       // -- for the move assignment operator, a direct base class with a type
       //    that does not have a move assignment operator and is not trivially
       //    copyable.
-      if (IsMove && !Member->isMoveAssignmentOperator() &&
-          !Class->isTriviallyCopyable())
+      if (!Member->isMoveAssignmentOperator() && !Class->isTriviallyCopyable())
         return true;
     }
   }
 
+  // C++11 [class.ctor]p5, C++11 [class.copy]p11:
+  // -- any direct or virtual base class or non-static data member has a
+  //    type with a destructor that is deleted or inaccessible
+  if (IsConstructor) {
+    Sema::SpecialMemberOverloadResult *SMOR =
+        S.LookupSpecialMember(Class, Sema::CXXDestructor,
+                              false, false, false, false, false);
+    if (shouldDeleteForSubobjectCall(Subobj, SMOR, true))
+      return true;
+  }
+
   return false;
 }
 
 /// Check whether we should delete a special member function due to the class
 /// having a particular direct or virtual base class.
-bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXRecordDecl *BaseDecl,
-                                                    bool IsVirtualBase) {
+bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
   // C++11 [class.copy]p23:
   // -- for the move assignment operator, any direct or indirect virtual
   //    base class.
-  if (CSM == Sema::CXXMoveAssignment && IsVirtualBase)
+  if (CSM == Sema::CXXMoveAssignment && Base->isVirtual()) {
+    if (Diagnose)
+      S.Diag(Base->getLocStart(), diag::note_deleted_move_assign_virtual_base)
+        << MD->getParent() << Base->getType();
     return true;
+  }
 
-  if (shouldDeleteForClassSubobject(BaseDecl, 0))
+  if (shouldDeleteForClassSubobject(Base->getType()->getAsCXXRecordDecl(),
+                                    Base))
     return true;
 
   return false;
@@ -4492,29 +4538,52 @@
   if (CSM == Sema::CXXDefaultConstructor) {
     // For a default constructor, all references must be initialized in-class
     // and, if a union, it must have a non-const member.
-    if (FieldType->isReferenceType() && !FD->hasInClassInitializer())
+    if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
+          << MD->getParent() << FD << FieldType << /*Reference*/0;
       return true;
-
-    if (inUnion() && !FieldType.isConstQualified())
-      AllFieldsAreConst = false;
-
+    }
     // C++11 [class.ctor]p5: any non-variant non-static data member of
     // const-qualified type (or array thereof) with no
     // brace-or-equal-initializer does not have a user-provided default
     // constructor.
     if (!inUnion() && FieldType.isConstQualified() &&
         !FD->hasInClassInitializer() &&
-        (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor()))
+        (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
+          << MD->getParent() << FD << FieldType << /*Const*/1;
       return true;
+    }
+
+    if (inUnion() && !FieldType.isConstQualified())
+      AllFieldsAreConst = false;
   } else if (CSM == Sema::CXXCopyConstructor) {
     // For a copy constructor, data members must not be of rvalue reference
     // type.
-    if (FieldType->isRValueReferenceType())
+    if (FieldType->isRValueReferenceType()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference)
+          << MD->getParent() << FD << FieldType;
       return true;
+    }
   } else if (IsAssignment) {
     // For an assignment operator, data members must not be of reference type.
-    if (FieldType->isReferenceType())
+    if (FieldType->isReferenceType()) {
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
+          << IsMove << MD->getParent() << FD << FieldType << /*Reference*/0;
+      return true;
+    }
+    if (!FieldRecord && FieldType.isConstQualified()) {
+      // C++11 [class.copy]p23:
+      // -- a non-static data member of const non-class type (or array thereof)
+      if (Diagnose)
+        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
+          << IsMove << MD->getParent() << FD << FieldType << /*Const*/1;
       return true;
+    }
   }
 
   if (FieldRecord) {
@@ -4540,8 +4609,13 @@
 
       // At least one member in each anonymous union must be non-const
       if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
-          FieldRecord->field_begin() != FieldRecord->field_end())
+          FieldRecord->field_begin() != FieldRecord->field_end()) {
+        if (Diagnose)
+          S.Diag(FieldRecord->getLocation(),
+                 diag::note_deleted_default_ctor_all_const)
+            << MD->getParent() << /*anonymous union*/1;
         return true;
+      }
 
       // Don't check the implicit member of the anonymous union type.
       // This is technically non-conformant, but sanity demands it.
@@ -4550,10 +4624,6 @@
 
     if (shouldDeleteForClassSubobject(FieldRecord, FD))
       return true;
-  } else if (IsAssignment && FieldType.isConstQualified()) {
-    // C++11 [class.copy]p23:
-    // -- a non-static data member of const non-class type (or array thereof)
-    return true;
   }
 
   return false;
@@ -4565,40 +4635,81 @@
 bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
   // This is a silly definition, because it gives an empty union a deleted
   // default constructor. Don't do that.
-  return CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
-    (MD->getParent()->field_begin() != MD->getParent()->field_end());
+  if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst &&
+      (MD->getParent()->field_begin() != MD->getParent()->field_end())) {
+    if (Diagnose)
+      S.Diag(MD->getParent()->getLocation(),
+             diag::note_deleted_default_ctor_all_const)
+        << MD->getParent() << /*not anonymous union*/0;
+    return true;
+  }
+  return false;
 }
 
 /// Determine whether a defaulted special member function should be defined as
 /// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
 /// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
-bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) {
+bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                                     bool Diagnose) {
   assert(!MD->isInvalidDecl());
   CXXRecordDecl *RD = MD->getParent();
   assert(!RD->isDependentType() && "do deletion after instantiation");
   if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl())
     return false;
 
-  // FIXME: Provide the ability to diagnose why a special member was deleted.
-
   // C++11 [expr.lambda.prim]p19:
   //   The closure type associated with a lambda-expression has a
   //   deleted (8.4.3) default constructor and a deleted copy
   //   assignment operator.
   if (RD->isLambda() &&
-      (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment))
+      (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) {
+    if (Diagnose)
+      Diag(RD->getLocation(), diag::note_lambda_decl);
     return true;
+  }
+
+  // C++11 [class.copy]p7, p18:
+  //   If the class definition declares a move constructor or move assignment
+  //   operator, an implicitly declared copy constructor or copy assignment
+  //   operator is defined as deleted.
+  if (MD->isImplicit() &&
+      (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
+    CXXMethodDecl *UserDeclaredMove = 0;
+
+    // In Microsoft mode, a user-declared move only causes the deletion of the
+    // corresponding copy operation, not both copy operations.
+    if (RD->hasUserDeclaredMoveConstructor() &&
+        (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) {
+      if (!Diagnose) return true;
+      UserDeclaredMove = RD->getMoveConstructor();
+    } else if (RD->hasUserDeclaredMoveAssignment() &&
+               (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) {
+      if (!Diagnose) return true;
+      UserDeclaredMove = RD->getMoveAssignmentOperator();
+    }
+
+    if (UserDeclaredMove) {
+      Diag(UserDeclaredMove->getLocation(),
+           diag::note_deleted_copy_user_declared_move)
+        << (CSM == CXXMoveAssignment) << RD
+        << UserDeclaredMove->isMoveAssignmentOperator();
+      return true;
+    }
+  }
 
   // C++11 [class.dtor]p5:
   // -- for a virtual destructor, lookup of the non-array deallocation function
   //    results in an ambiguity or in a function that is deleted or inaccessible
-  if (CSM == Sema::CXXDestructor && MD->isVirtual()) {
+  if (CSM == CXXDestructor && MD->isVirtual()) {
     FunctionDecl *OperatorDelete = 0;
     DeclarationName Name =
       Context.DeclarationNames.getCXXOperatorName(OO_Delete);
     if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
-                                 OperatorDelete, false))
+                                 OperatorDelete, false)) {
+      if (Diagnose)
+        Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete);
       return true;
+    }
   }
 
   // For an anonymous struct or union, the copy and assignment special members
@@ -4611,17 +4722,17 @@
   // Do access control from the special member function
   ContextRAII MethodContext(*this, MD);
 
-  SpecialMemberDeletionInfo SMI(*this, MD, CSM);
+  SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
 
   for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),
                                           BE = RD->bases_end(); BI != BE; ++BI)
     if (!BI->isVirtual() &&
-        SMI.shouldDeleteForBase(BI->getType()->getAsCXXRecordDecl(), false))
+        SMI.shouldDeleteForBase(BI))
       return true;
 
   for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(),
                                           BE = RD->vbases_end(); BI != BE; ++BI)
-    if (SMI.shouldDeleteForBase(BI->getType()->getAsCXXRecordDecl(), true))
+    if (SMI.shouldDeleteForBase(BI))
       return true;
 
   for (CXXRecordDecl::field_iterator FI = RD->field_begin(),
@@ -7603,12 +7714,9 @@
   //   assignment operator, there is no user-declared move constructor, and
   //   there is no user-declared move assignment operator, a copy assignment
   //   operator is implicitly declared as defaulted.
-  if ((ClassDecl->hasUserDeclaredMoveConstructor() &&
-          !getLangOpts().MicrosoftMode) ||
-      ClassDecl->hasUserDeclaredMoveAssignment() ||
-      ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
+  if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
     CopyAssignment->setDeletedAsWritten();
-  
+
   AddOverriddenMethods(ClassDecl, CopyAssignment);
   return CopyAssignment;
 }
@@ -8522,12 +8630,9 @@
   //   constructor, there is no user-declared move constructor, and there is no
   //   user-declared move assignment operator, a copy constructor is implicitly
   //   declared as defaulted.
-  if (ClassDecl->hasUserDeclaredMoveConstructor() ||
-      (ClassDecl->hasUserDeclaredMoveAssignment() &&
-          !getLangOpts().MicrosoftMode) ||
-      ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
+  if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
     CopyConstructor->setDeletedAsWritten();
-  
+
   return CopyConstructor;
 }
 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Mar 30 15:53:28 2012
@@ -108,6 +108,25 @@
     return Result;
 }
 
+/// \brief Emit a note explaining that this function is deleted or unavailable.
+void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
+
+  if (Method && Method->isImplicit()) {
+    CXXSpecialMember CSM = getSpecialMember(Method);
+    // It is possible for us to no longer be able to determine why the special
+    // member function was deleted, due to a field or base class having acquired
+    // a new special member function by the addition of a default argument.
+    // FIXME: Add a test and a special-case diagnostic for this.
+    if (CSM != CXXInvalid &&
+        ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true))
+      return;
+  }
+
+  Diag(Decl->getLocation(), diag::note_unavailable_here)
+    << 1 << Decl->isDeleted();
+}
+
 /// \brief Determine whether the use of this declaration is valid, and
 /// emit any corresponding diagnostics.
 ///
@@ -151,7 +170,7 @@
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     if (FD->isDeleted()) {
       Diag(Loc, diag::err_deleted_function_use);
-      Diag(D->getLocation(), diag::note_unavailable_here) << 1 << true;
+      NoteDeletedFunction(FD);
       return true;
     }
   }

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Mar 30 15:53:28 2012
@@ -1899,8 +1899,7 @@
     if (Operator->isDeleted()) {
       if (Diagnose) {
         Diag(StartLoc, diag::err_deleted_function_use);
-        Diag(Operator->getLocation(), diag::note_unavailable_here)
-          << /*function*/ 1 << /*deleted*/ 1;
+        NoteDeletedFunction(Operator);
       }
       return true;
     }

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Mar 30 15:53:28 2012
@@ -4482,8 +4482,7 @@
     S.Diag(Loc, diag::err_temp_copy_deleted)
       << (int)Entity.getKind() << CurInitExpr->getType()
       << CurInitExpr->getSourceRange();
-    S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
-      << 1 << Best->Function->isDeleted();
+    S.NoteDeletedFunction(Best->Function);
     return ExprError();
   }
 
@@ -4592,8 +4591,7 @@
 
   case OR_Deleted:
     S.Diag(Loc, Diag);
-    S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
-      << 1 << Best->Function->isDeleted();
+    S.NoteDeletedFunction(Best->Function);
     break;
   }
 }
@@ -5362,26 +5360,6 @@
   return move(CurInit);
 }
 
-/// \brief Provide some notes that detail why a function was implicitly
-/// deleted.
-static void diagnoseImplicitlyDeletedFunction(Sema &S, CXXMethodDecl *Method) {
-  // FIXME: This is a work in progress. It should dig deeper to figure out
-  // why the function was deleted (e.g., because one of its members doesn't
-  // have a copy constructor, for the copy-constructor case).
-  if (!Method->isImplicit()) {
-    S.Diag(Method->getLocation(), diag::note_callee_decl)
-      << Method->getDeclName();
-  }
-  
-  if (Method->getParent()->isLambda()) {
-    S.Diag(Method->getParent()->getLocation(), diag::note_lambda_decl);
-    return;
-  }
-  
-  S.Diag(Method->getParent()->getLocation(), diag::note_defined_here)
-    << Method->getParent();
-}
-
 //===----------------------------------------------------------------------===//
 // Diagnose initialization failures
 //===----------------------------------------------------------------------===//
@@ -5469,8 +5447,7 @@
         = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best,
                                                 true);
       if (Ovl == OR_Deleted) {
-        S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
-          << 1 << Best->Function->isDeleted();
+        S.NoteDeletedFunction(Best->Function);
       } else {
         llvm_unreachable("Inconsistent overload resolution?");
       }
@@ -5661,20 +5638,15 @@
         // If this is a defaulted or implicitly-declared function, then
         // it was implicitly deleted. Make it clear that the deletion was
         // implicit.
-        if (S.isImplicitlyDeleted(Best->Function)) {
+        if (S.isImplicitlyDeleted(Best->Function))
           S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init)
-            << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function)) 
+            << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function))
             << DestType << ArgsRange;
-        
-          diagnoseImplicitlyDeletedFunction(S, 
-            cast<CXXMethodDecl>(Best->Function));            
-          break;
-        }
-        
-        S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
-          << true << DestType << ArgsRange;
-        S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
-          << 1 << Best->Function->isDeleted();
+        else
+          S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+            << true << DestType << ArgsRange;
+
+        S.NoteDeletedFunction(Best->Function);
         break;
       }
 

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Mar 30 15:53:28 2012
@@ -2274,8 +2274,9 @@
     CXXDestructorDecl *DD = RD->getDestructor();
     assert(DD && "record without a destructor");
     Result->setMethod(DD);
-    Result->setSuccess(!DD->isDeleted());
-    Result->setConstParamMatch(false);
+    Result->setKind(DD->isDeleted() ?
+                    SpecialMemberOverloadResult::NoMemberOrDeleted :
+                    SpecialMemberOverloadResult::SuccessNonConst);
     return Result;
   }
 
@@ -2345,7 +2346,8 @@
   // will always be a (possibly implicit) declaration to shadow any others.
   OverloadCandidateSet OCS((SourceLocation()));
   DeclContext::lookup_iterator I, E;
-  Result->setConstParamMatch(false);
+  SpecialMemberOverloadResult::Kind SuccessKind =
+      SpecialMemberOverloadResult::SuccessNonConst;
 
   llvm::tie(I, E) = RD->lookup(Name);
   assert((I != E) &&
@@ -2384,7 +2386,7 @@
         QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0);
         if (!ArgType->isReferenceType() ||
             ArgType->getPointeeType().isConstQualified())
-          Result->setConstParamMatch(true);
+          SuccessKind = SpecialMemberOverloadResult::SuccessConst;
       }
     } else if (FunctionTemplateDecl *Tmpl =
                  dyn_cast<FunctionTemplateDecl>(Cand)) {
@@ -2406,18 +2408,22 @@
   switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) {
     case OR_Success:
       Result->setMethod(cast<CXXMethodDecl>(Best->Function));
-      Result->setSuccess(true);
+      Result->setKind(SuccessKind);
       break;
 
     case OR_Deleted:
       Result->setMethod(cast<CXXMethodDecl>(Best->Function));
-      Result->setSuccess(false);
+      Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
       break;
 
     case OR_Ambiguous:
+      Result->setMethod(0);
+      Result->setKind(SpecialMemberOverloadResult::Ambiguous);
+      break;
+
     case OR_No_Viable_Function:
       Result->setMethod(0);
-      Result->setSuccess(false);
+      Result->setKind(SpecialMemberOverloadResult::NoMemberOrDeleted);
       break;
   }
 

Modified: 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=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp Fri Mar 30 15:53:28 2012
@@ -8,7 +8,7 @@
 protected:
   struct Inner { int m; };
 public:
-  bool &br;
+  bool &br; // expected-note {{default constructor of 'Aggr' is implicitly deleted because field 'br' of reference type 'bool &' would not be initialized}}
 };
 bool b;
 Aggr ag = { b };
@@ -54,7 +54,7 @@
 };
 NonAggr5 na5 = { b }; // expected-error {{no matching constructor for initialization of 'NonAggr5'}}
 template<typename...BaseList>
-struct MaybeAggr5a : BaseList... {}; // expected-note {{defined here}}
+struct MaybeAggr5a : BaseList... {}; // expected-note {{default constructor of 'MaybeAggr5a<Aggr>' is implicitly deleted because base class 'Aggr' has a deleted default constructor}}
 MaybeAggr5a<> ma5a0 = {}; // ok
 MaybeAggr5a<Aggr> ma5a1 = {}; // expected-error {{call to implicitly-deleted default constructor of 'MaybeAggr5a<Aggr>'}}
 

Modified: cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp Fri Mar 30 15:53:28 2012
@@ -87,9 +87,9 @@
   ~PrivateDestructor() noexcept;
 };
 
-struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{defined here}}
-struct ContainsPrivateDestructor { // expected-note{{defined here}}
-  PrivateDestructor pd;
+struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}}
+struct ContainsPrivateDestructor {
+  PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}}
 };
 
 struct NonTrivialCopyOnly {

Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.copy.cpp Fri Mar 30 15:53:28 2012
@@ -7,16 +7,16 @@
 // A defaulted copy constructor for a class X is defined as deleted if X has:
 
 // -- a variant member with a non-trivial corresponding constructor
-union DeletedNTVariant { // expected-note{{here}}
-  NonTrivial NT;
+union DeletedNTVariant {
+  NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant' is implicitly deleted because field 'NT' has a non-trivial copy constructor}}
   DeletedNTVariant();
 };
 DeletedNTVariant DVa;
 DeletedNTVariant DVb(DVa); // expected-error{{call to implicitly-deleted copy constructor}}
 
-struct DeletedNTVariant2 { // expected-note{{here}}
+struct DeletedNTVariant2 {
   union {
-    NonTrivial NT;
+    NonTrivial NT; // expected-note{{copy constructor of union 'DeletedNTVariant2' is implicitly deleted because field 'NT' has a non-trivial copy constructor}}
   };
   DeletedNTVariant2();
 };
@@ -34,8 +34,8 @@
   friend struct HasAccess;
 };
 
-struct HasNoAccess { // expected-note{{here}}
-  NoAccess NA;
+struct HasNoAccess {
+  NoAccess NA; // expected-note{{copy constructor of 'HasNoAccess' is implicitly deleted because field 'NA' has an inaccessible copy constructor}}
 };
 HasNoAccess HNAa;
 HasNoAccess HNAb(HNAa); // expected-error{{call to implicitly-deleted copy constructor}}
@@ -55,16 +55,16 @@
   Ambiguity(volatile Ambiguity&);
 };
 
-struct IsAmbiguous { // expected-note{{here}}
+struct IsAmbiguous {
   NonConst NC;
-  Ambiguity A;
+  Ambiguity A; // expected-note 2{{copy constructor of 'IsAmbiguous' is implicitly deleted because field 'A' has multiple copy constructors}}
   IsAmbiguous();
 };
 IsAmbiguous IAa;
 IsAmbiguous IAb(IAa); // expected-error{{call to implicitly-deleted copy constructor}}
 
-struct Deleted { // expected-note{{here}}
-  IsAmbiguous IA;
+struct Deleted {
+  IsAmbiguous IA; // expected-note{{copy constructor of 'Deleted' is implicitly deleted because field 'IA' has a deleted copy constructor}}
 };
 Deleted Da;
 Deleted Db(Da); // expected-error{{call to implicitly-deleted copy constructor}}
@@ -72,17 +72,17 @@
 // -- a direct or virtual base class B that cannot be copied because overload
 //    resolution results in an ambiguity or a function that is deleted or
 //    inaccessible
-struct AmbiguousCopyBase : Ambiguity { // expected-note {{here}}
+struct AmbiguousCopyBase : Ambiguity { // expected-note 2{{copy constructor of 'AmbiguousCopyBase' is implicitly deleted because base class 'Ambiguity' has multiple copy constructors}}
   NonConst NC;
 };
 extern AmbiguousCopyBase ACBa;
 AmbiguousCopyBase ACBb(ACBa); // expected-error {{deleted copy constructor}}
 
-struct DeletedCopyBase : AmbiguousCopyBase {}; // expected-note {{here}}
+struct DeletedCopyBase : AmbiguousCopyBase {}; // expected-note {{copy constructor of 'DeletedCopyBase' is implicitly deleted because base class 'AmbiguousCopyBase' has a deleted copy constructor}}
 extern DeletedCopyBase DCBa;
 DeletedCopyBase DCBb(DCBa); // expected-error {{deleted copy constructor}}
 
-struct InaccessibleCopyBase : NoAccess {}; // expected-note {{here}}
+struct InaccessibleCopyBase : NoAccess {}; // expected-note {{copy constructor of 'InaccessibleCopyBase' is implicitly deleted because base class 'NoAccess' has an inaccessible copy constructor}}
 extern InaccessibleCopyBase ICBa;
 InaccessibleCopyBase ICBb(ICBa); // expected-error {{deleted copy constructor}}
 
@@ -94,8 +94,8 @@
   friend struct HasAccessDtor;
 };
 
-struct HasNoAccessDtor { // expected-note{{here}}
-  NoAccessDtor NAD;
+struct HasNoAccessDtor {
+  NoAccessDtor NAD; // expected-note{{copy constructor of 'HasNoAccessDtor' is implicitly deleted because field 'NAD' has an inaccessible destructor}}
   HasNoAccessDtor();
   ~HasNoAccessDtor();
 };
@@ -108,14 +108,14 @@
 HasAccessDtor HADa;
 HasAccessDtor HADb(HADa);
 
-struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{here}}
+struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has an inaccessible destructor}}
 };
 extern HasNoAccessDtorBase HNADBa;
 HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}
 
 // -- a non-static data member of rvalue reference type
-struct RValue { // expected-note{{here}}
-  int && ri = 1;
+struct RValue {
+  int && ri = 1; // expected-note{{copy constructor of 'RValue' is implicitly deleted because field 'ri' is of rvalue reference type 'int &&'}}
 };
 RValue RVa;
 RValue RVb(RVa); // expected-error{{call to implicitly-deleted copy constructor}}

Modified: cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/p11.0x.move.cpp Fri Mar 30 15:53:28 2012
@@ -82,7 +82,7 @@
 // -- any direct or virtual base class or non-static data member of a type with
 //    a destructor that is deleted or inaccessible
 struct NoAccessDtor {
-  NoAccessDtor(NoAccessDtor&&);
+  NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}}
 private:
   ~NoAccessDtor();
   friend struct HasAccessDtor;
@@ -100,7 +100,7 @@
 };
 HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default;
 
-struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{here}}
+struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}}
 };
 extern HasNoAccessDtorBase HNADBa;
 HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}

Modified: cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Fri Mar 30 15:53:28 2012
@@ -2,9 +2,9 @@
 
 struct DefaultedDefCtor1 {};
 struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; };
-struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); };
+struct DeletedDefCtor { DeletedDefCtor() = delete; DeletedDefCtor(int); }; // expected-note {{explicitly marked deleted here}}
 class PrivateDefCtor { PrivateDefCtor() = default; public: PrivateDefCtor(int); };
-struct DeletedDtor { ~DeletedDtor() = delete; };
+struct DeletedDtor { ~DeletedDtor() = delete; }; // expected-note 4{{explicitly marked deleted here}}
 class PrivateDtor { ~PrivateDtor() = default; };
 class Friend {
   Friend() = default; ~Friend() = default;
@@ -21,7 +21,7 @@
 
 // - X is a union-like class that has a variant member with a non-trivial
 // default constructor,
-union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{defined here}}
+union Deleted1a { UserProvidedDefCtor u; }; // expected-note {{default constructor of union 'Deleted1a' is implicitly deleted because field 'u' has a non-trivial default constructor}}
 Deleted1a d1a; // expected-error {{implicitly-deleted default constructor}}
 union NotDeleted1a { DefaultedDefCtor1 nu; };
 NotDeleted1a nd1a;
@@ -30,13 +30,15 @@
 
 // - any non-static data member with no brace-or-equal-initializer is of
 // reference type,
-class Deleted2a {  // expected-note {{defined here}}
-  Deleted2a() = default;  // expected-note {{declared here}}
+class Deleted2a {
+  // FIXME: We should explain that the function was implicitly deleted as a
+  // result of being defaulted, and why.
+  Deleted2a() = default;  // expected-note 4{{explicitly marked deleted here}}
   int &a; 
 }; 
 Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted2b { // expected-note {{here}}
-  int &&b;
+struct Deleted2b {
+  int &&b; // expected-note {{default constructor of 'Deleted2b' is implicitly deleted because field 'b' of reference type 'int &&' would not be initialized}}
 };
 Deleted2b d2b; // expected-error {{deleted default constructor}}
 class NotDeleted2a { int &a = n; };
@@ -49,13 +51,13 @@
 // - any non-variant non-static data member of const qualified type (or array
 // thereof) with no brace-or-equal-initializer does not have a user-provided
 // default constructor,
-class Deleted3a { const int a; }; // expected-note {{here}} \
+class Deleted3a { const int a; }; // expected-note {{because field 'a' of const-qualified type 'const int' would not be initialized}} \
                                      expected-warning {{does not declare any constructor}} \
                                      expected-note {{will never be initialized}}
 Deleted3a d3a; // expected-error {{implicitly-deleted default constructor}}
-class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{here}}
+class Deleted3b { const DefaultedDefCtor1 a[42]; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor1' would not be initialized}}
 Deleted3b d3b; // expected-error {{implicitly-deleted default constructor}}
-class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{defined here}}
+class Deleted3c { const DefaultedDefCtor2 a; }; // expected-note {{because field 'a' of const-qualified type 'const DefaultedDefCtor2' would not be initialized}}
 Deleted3c d3c; // expected-error {{implicitly-deleted default constructor}}
 class NotDeleted3a { const int a = 0; };
 NotDeleted3a nd3a;
@@ -74,14 +76,21 @@
 
 // - X is a union and all of its variant members are of const-qualified type (or
 // array thereof),
-union Deleted4a { const int a; const int b; const UserProvidedDefCtor c; }; // expected-note {{here}}
+union Deleted4a {
+  const int a;
+  const int b;
+  const UserProvidedDefCtor c; // expected-note {{because field 'c' has a non-trivial default constructor}}
+};
 Deleted4a d4a; // expected-error {{implicitly-deleted default constructor}}
 union NotDeleted4a { const int a; int b; };
 NotDeleted4a nd4a;
 
 // - X is a non-union class and all members of any anonymous union member are of
 // const-qualified type (or array thereof),
-struct Deleted5a { union { const int a; }; union { int b; }; }; // expected-note {{here}}
+struct Deleted5a {
+  union { const int a; }; // expected-note {{because all data members of an anonymous union member are const-qualified}}
+  union { int b; };
+};
 Deleted5a d5a; // expected-error {{implicitly-deleted default constructor}}
 struct NotDeleted5a { union { const int a; int b; }; union { const int c; int d; }; };
 NotDeleted5a nd5a;
@@ -91,17 +100,17 @@
 // M has no default constructor or overload resolution as applied to M's default
 // constructor results in an ambiguity or in a function that is deleted or
 // inaccessible from the defaulted default constructor, or
-struct Deleted6a : Deleted2a {}; // expected-note {{here}}
+struct Deleted6a : Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}}
 Deleted6a d6a; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted6b : virtual Deleted2a {}; // expected-note {{here}}
+struct Deleted6b : virtual Deleted2a {}; // expected-note {{because base class 'Deleted2a' has a deleted default constructor}}
 Deleted6b d6b; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted6c { Deleted2a a; }; // expected-note {{here}}
+struct Deleted6c { Deleted2a a; }; // expected-note {{because field 'a' has a deleted default constructor}}
 Deleted6c d6c; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted6d { DeletedDefCtor a; }; // expected-note {{here}}
+struct Deleted6d { DeletedDefCtor a; }; // expected-note {{because field 'a' has a deleted default constructor}}
 Deleted6d d6d; // expected-error {{implicitly-deleted default constructor}}
 struct NotDeleted6a { DeletedDefCtor a = 0; };
 NotDeleted6a nd6a;
-struct Deleted6e { PrivateDefCtor a; }; // expected-note {{here}}
+struct Deleted6e { PrivateDefCtor a; }; // expected-note {{because field 'a' has an inaccessible default constructor}}
 Deleted6e d6e; // expected-error {{implicitly-deleted default constructor}}
 struct NotDeleted6b { PrivateDefCtor a = 0; };
 NotDeleted6b nd6b;
@@ -111,21 +120,21 @@
 // - any direct or virtual base class or non-static data member has a type with
 // a destructor that is deleted or inaccessible from the defaulted default
 // constructor.
-struct Deleted7a : DeletedDtor {}; // expected-note {{here}}
+struct Deleted7a : DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}}
 Deleted7a d7a; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7b : virtual DeletedDtor {}; // expected-note {{here}}
+struct Deleted7b : virtual DeletedDtor {}; // expected-note {{because base class 'DeletedDtor' has a deleted destructor}}
 Deleted7b d7b; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7c { DeletedDtor a; }; // expected-note {{here}}
+struct Deleted7c { DeletedDtor a; }; // expected-note {{because field 'a' has a deleted destructor}}
 Deleted7c d7c; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{here}}
+struct Deleted7d { DeletedDtor a = {}; }; // expected-note {{because field 'a' has a deleted destructor}}
 Deleted7d d7d; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7e : PrivateDtor {}; // expected-note {{here}}
+struct Deleted7e : PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}}
 Deleted7e d7e; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7f : virtual PrivateDtor {}; // expected-note {{here}}
+struct Deleted7f : virtual PrivateDtor {}; // expected-note {{base class 'PrivateDtor' has an inaccessible destructor}}
 Deleted7f d7f; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7g { PrivateDtor a; }; // expected-note {{here}}
+struct Deleted7g { PrivateDtor a; }; // expected-note {{field 'a' has an inaccessible destructor}}
 Deleted7g d7g; // expected-error {{implicitly-deleted default constructor}}
-struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{here}}
+struct Deleted7h { PrivateDtor a = {}; }; // expected-note {{field 'a' has an inaccessible destructor}}
 Deleted7h d7h; // expected-error {{implicitly-deleted default constructor}}
 struct NotDeleted7i : Friend {};
 NotDeleted7i d7i;

Modified: cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp Fri Mar 30 15:53:28 2012
@@ -4,7 +4,7 @@
   ~NonTrivDtor();
 };
 struct DeletedDtor {
-  ~DeletedDtor() = delete;
+  ~DeletedDtor() = delete; // expected-note 5 {{deleted here}}
 };
 class InaccessibleDtor {
   ~InaccessibleDtor() = default;
@@ -14,73 +14,74 @@
 
 // -- X is a union-like class that has a variant member with a non-trivial
 // destructor.
-union A1 { // expected-note {{here}}
+union A1 {
   A1();
-  NonTrivDtor n;
+  NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}}
 };
 A1 a1; // expected-error {{deleted function}}
-struct A2 { // expected-note {{here}}
+struct A2 {
   A2();
   union {
-    NonTrivDtor n;
+    NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}}
   };
 };
 A2 a2; // expected-error {{deleted function}}
-union A3 { // expected-note {{here}}
+union A3 {
   A3();
-  NonTrivDtor n[3];
+  NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}}
 };
 A3 a3; // expected-error {{deleted function}}
-struct A4 { // expected-note {{here}}
+struct A4 {
   A4();
   union {
-    NonTrivDtor n[3];
+    NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}}
   };
 };
 A4 a4; // expected-error {{deleted function}}
 
 // -- any of the non-static data members has class type M (or array thereof) and
 // M has a deleted or inaccessible destructor.
-struct B1 { // expected-note {{here}}
+struct B1 {
   B1();
-  DeletedDtor a;
+  DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}}
 };
 B1 b1; // expected-error {{deleted function}}
-struct B2 { // expected-note {{here}}
+struct B2 {
   B2();
-  InaccessibleDtor a;
+  InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}}
 };
 B2 b2; // expected-error {{deleted function}}
-struct B3 { // expected-note {{here}}
+struct B3 {
   B3();
-  DeletedDtor a[4];
+  DeletedDtor a[4]; // expected-note {{because field 'a' has a deleted destructor}}
 };
 B3 b3; // expected-error {{deleted function}}
-struct B4 { // expected-note {{here}}
+struct B4 {
   B4();
-  InaccessibleDtor a[4];
+  InaccessibleDtor a[4]; // expected-note {{because field 'a' has an inaccessible destructor}}
 };
 B4 b4; // expected-error {{deleted function}}
-union B5 { // expected-note {{here}}
+union B5 {
   B5();
-  union {
-    DeletedDtor a;
+  // FIXME: Describe the anonymous union member better than ''.
+  union { // expected-note {{because field '' has a deleted destructor}}
+    DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}}
   };
 };
 B5 b5; // expected-error {{deleted function}}
-union B6 { // expected-note {{here}}
+union B6 {
   B6();
-  union {
-    InaccessibleDtor a;
+  union { // expected-note {{because field '' has a deleted destructor}}
+    InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}}
   };
 };
 B6 b6; // expected-error {{deleted function}}
 
 // -- any direct or virtual base class has a deleted or inaccessible destructor.
-struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{here}}
-struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{here}}
-struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{here}}
-struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{here}}
+struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}}
+struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}}
+struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}}
+struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}}
 
 // -- for a virtual destructor, lookup of the non-array deallocation function
 // results in an ambiguity or a function that is deleted or inaccessible.

Modified: cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp Fri Mar 30 15:53:28 2012
@@ -7,23 +7,23 @@
   ~non_trivial();
 };
 
-union bad_union { // expected-note {{defined here}}
-  non_trivial nt;
+union bad_union {
+  non_trivial nt; // expected-note {{non-trivial default constructor}}
 };
 bad_union u; // expected-error {{call to implicitly-deleted default constructor}}
-union bad_union2 { // expected-note {{defined here}}
+union bad_union2 { // expected-note {{all data members are const-qualified}}
   const int i;
 };
 bad_union2 u2; // expected-error {{call to implicitly-deleted default constructor}}
 
-struct bad_anon { // expected-note {{defined here}}
+struct bad_anon {
   union {
-    non_trivial nt;
+    non_trivial nt; // expected-note {{non-trivial default constructor}}
   };
 };
 bad_anon a; // expected-error {{call to implicitly-deleted default constructor}}
-struct bad_anon2 { // expected-note {{defined here}}
-  union {
+struct bad_anon2 {
+  union { // expected-note {{all data members of an anonymous union member are const-qualified}}
     const int i;
   };
 };
@@ -48,8 +48,8 @@
 };
 good g;
 
-struct bad_const { // expected-note {{defined here}}
-  const good g;
+struct bad_const {
+  const good g; // expected-note {{field 'g' of const-qualified type 'const good' would not be initialized}}
 };
 bad_const bc; // expected-error {{call to implicitly-deleted default constructor}}
 
@@ -59,25 +59,25 @@
 good_const gc;
 
 struct no_default {
-  no_default() = delete;
+  no_default() = delete; // expected-note 2{{deleted here}}
 };
 struct no_dtor {
-  ~no_dtor() = delete;
+  ~no_dtor() = delete; // expected-note 2{{deleted here}}
 };
 
-struct bad_field_default { // expected-note {{defined here}}
-  no_default nd;
+struct bad_field_default {
+  no_default nd; // expected-note {{field 'nd' has a deleted default constructor}}
 };
 bad_field_default bfd; // expected-error {{call to implicitly-deleted default constructor}}
-struct bad_base_default : no_default { // expected-note {{defined here}}
+struct bad_base_default : no_default { // expected-note {{base class 'no_default' has a deleted default constructor}}
 };
 bad_base_default bbd; // expected-error {{call to implicitly-deleted default constructor}}
 
-struct bad_field_dtor { // expected-note {{defined here}}
-  no_dtor nd;
+struct bad_field_dtor {
+  no_dtor nd; // expected-note {{field 'nd' has a deleted destructor}}
 };
 bad_field_dtor bfx; // expected-error {{call to implicitly-deleted default constructor}}
-struct bad_base_dtor : no_dtor { // expected-note {{defined here}}
+struct bad_base_dtor : no_dtor { // expected-note {{base class 'no_dtor' has a deleted destructor}}
 };
 bad_base_dtor bbx; // expected-error {{call to implicitly-deleted default constructor}}
 
@@ -85,16 +85,16 @@
   ambiguous_default();
   ambiguous_default(int = 2);
 };
-struct has_amb_field { // expected-note {{defined here}}
-  ambiguous_default ad;
+struct has_amb_field {
+  ambiguous_default ad; // expected-note {{field 'ad' has multiple default constructors}}
 };
 has_amb_field haf; // expected-error {{call to implicitly-deleted default constructor}}
 
 class inaccessible_default {
   inaccessible_default();
 };
-struct has_inacc_field { // expected-note {{defined here}}
-  inaccessible_default id;
+struct has_inacc_field {
+  inaccessible_default id; // expected-note {{field 'id' has an inaccessible default constructor}}
 };
 has_inacc_field hif; // expected-error {{call to implicitly-deleted default constructor}}
 
@@ -107,9 +107,9 @@
 };
 has_friend hf;
 
-struct defaulted_delete { // expected-note {{defined here}}
+struct defaulted_delete {
   no_default nd;
-  defaulted_delete() = default; // expected-note{{declared here}}
+  defaulted_delete() = default; // expected-note{{deleted here}}
 };
 defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
 

Modified: cfe/trunk/test/SemaCXX/cxx98-compat-flags.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat-flags.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat-flags.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat-flags.cpp Fri Mar 30 15:53:28 2012
@@ -24,10 +24,8 @@
     Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}}
     Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}}
   };
-  struct Deleted { // expected-note {{here}}
-    // Copy ctor implicitly defined as deleted because Private's copy ctor is
-    // inaccessible.
-    Private p;
+  struct Deleted {
+    Private p; // expected-note {{copy constructor of 'Deleted' is implicitly deleted because field 'p' has an inaccessible copy constructor}}
   };
 
   const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}}

Modified: cfe/trunk/test/SemaCXX/cxx98-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx98-compat.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx98-compat.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx98-compat.cpp Fri Mar 30 15:53:28 2012
@@ -214,10 +214,8 @@
     Ambiguous(const Ambiguous &, int = 0); // expected-note {{candidate}}
     Ambiguous(const Ambiguous &, double = 0); // expected-note {{candidate}}
   };
-  struct Deleted { // expected-note {{here}}
-    // Copy ctor implicitly defined as deleted because Private's copy ctor is
-    // inaccessible.
-    Private p;
+  struct Deleted {
+    Private p; // expected-note {{implicitly deleted}}
   };
 
   const Private &a = Private(); // expected-warning {{copying variable of type 'CopyCtorIssues::Private' when binding a reference to a temporary would invoke an inaccessible constructor in C++98}}

Modified: cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp (original)
+++ cfe/trunk/test/SemaCXX/defaulted-private-dtor.cpp Fri Mar 30 15:53:28 2012
@@ -12,12 +12,12 @@
   BadDtor dd; // expected-error {{private destructor}}
   throw dd; // expected-error {{private destructor}}
 }
-struct V { // expected-note {{here}}
+struct V {
   V();
-  BadDtor bd;
+  BadDtor bd; // expected-note {{inaccessible destructor}}
 };
 V v; // expected-error {{deleted function}}
-struct W : BadDtor { // expected-note {{here}}
+struct W : BadDtor { // expected-note {{inaccessible destructor}}
   W();
 };
 W w; // expected-error {{deleted function}}

Modified: cfe/trunk/test/SemaCXX/dr1301.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dr1301.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dr1301.cpp (original)
+++ cfe/trunk/test/SemaCXX/dr1301.cpp Fri Mar 30 15:53:28 2012
@@ -6,18 +6,18 @@
 int a = A().n; // expected-error {{no matching constructor}}
 
 struct B {
-  B() = delete; // expected-note {{here}}
+  B() = delete; // expected-note 2{{here}}
   int n;
 };
 int b = B().n; // expected-error {{call to deleted}}
 
-struct C { // expected-note {{here}}
-  B b;
+struct C {
+  B b; // expected-note {{deleted default constructor}}
 };
 int c = C().b.n; // expected-error {{call to implicitly-deleted default}}
 
-struct D { // expected-note {{defined here}}
-  D() = default; // expected-note {{declared here}}
+struct D {
+  D() = default; // expected-note {{here}}
   B b;
 };
 int d = D().b.n; // expected-error {{call to implicitly-deleted default}}
@@ -34,8 +34,8 @@
 };
 int f = F().n; // ok
 
-union G { // expected-note {{here}}
-  F f;
+union G {
+  F f; // expected-note {{non-trivial default constructor}}
 };
 int g = G().f.n; // expected-error {{call to implicitly-deleted default}}
 
@@ -46,8 +46,8 @@
 };
 int h = H().n; // expected-error {{private constructor}}
 
-struct I { // expected-note {{here}}
-  H h;
+struct I {
+  H h; // expected-note {{inaccessible default constructor}}
 };
 int i = I().h.n; // expected-error {{call to implicitly-deleted default}}
 
@@ -59,8 +59,8 @@
 int j1 = J().n; // ok
 int j2 = J().f(); // ok
 
-union K { // expected-note 2{{here}}
-  J j;
+union K {
+  J j; // expected-note 2{{non-trivial default constructor}}
   int m;
 };
 int k1 = K().j.n; // expected-error {{call to implicitly-deleted default}}

Modified: cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp Fri Mar 30 15:53:28 2012
@@ -54,9 +54,9 @@
 // The same problem arises in delayed parsing of default arguments,
 // which clang does not yet support.
 namespace DefaultArgument {
-  struct Default { // expected-note {{defined here}}
+  struct Default {
     struct T {
       T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}}
-    } t;
+    } t; // expected-note {{has no default constructor}}
   };
 }

Modified: cfe/trunk/test/SemaCXX/value-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/value-initialization.cpp?rev=153773&r1=153772&r2=153773&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/value-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/value-initialization.cpp Fri Mar 30 15:53:28 2012
@@ -1,8 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
 
-struct A { //expected-note {{defined here}} \
-     // expected-warning {{does not declare any constructor to initialize}}
-     const int i; // expected-note{{const member 'i' will never be initialized}}
+struct A { // expected-warning {{does not declare any constructor to initialize}}
+     const int i; // expected-note{{const member 'i' will never be initialized}} expected-note {{implicitly deleted}}
      virtual void f() { } 
 };
 





More information about the cfe-commits mailing list