[cfe-commits] r153894 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/CXX/special/class.copy/implicit-move.cpp test/CXX/special/class.ctor/p5-0x.cpp test/CXX/special/class.dtor/p5-0x.cpp test/SemaCXX/cxx0x-deleted-default-ctor.cpp test/SemaCXX/dr1301.cpp

Richard Smith richard-llvm at metafoo.co.uk
Mon Apr 2 13:59:25 PDT 2012


Author: rsmith
Date: Mon Apr  2 15:59:25 2012
New Revision: 153894

URL: http://llvm.org/viewvc/llvm-project?rev=153894&view=rev
Log:
Finish PR10217: Ensure we say that a special member was implicitly, not
explicitly, deleted in all relevant cases, and explain why.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/CXX/special/class.copy/implicit-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/dr1301.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr  2 15:59:25 2012
@@ -1989,8 +1989,9 @@
     "constructor (the implicit move constructor)|"
     "function (the implicit copy assignment operator)|"
     "function (the implicit move assignment operator)|"
-    "constructor (inherited)}0%1 "
-    "has been explicitly %select{made unavailable|deleted}2">;
+    "constructor (inherited)}0%1 has been "
+    "%select{explicitly made unavailable|explicitly deleted|"
+    "implicitly deleted}2">;
 
 // Giving the index of the bad argument really clutters this message, and
 // it's relatively unimportant because 1) it's generally obvious which
@@ -2508,7 +2509,7 @@
     "no function template matches function template specialization %0">;
 def err_function_template_spec_ambiguous : Error<
     "function template specialization %0 ambiguously refers to more than one "
-    "function template; explicitly specify%select{|additional }1 template "
+    "function template; explicitly specify%select{| additional}1 template "
     "arguments to identify a particular function template">;
 def note_function_template_spec_matched : Note<
     "function template matches specialization %0">;
@@ -2798,6 +2799,8 @@
 def note_unavailable_here : Note<
   "%select{declaration|function}0 has been explicitly marked "
   "%select{unavailable|deleted|deprecated}1 here">;
+def note_implicitly_deleted : Note<
+  "explicitly defaulted function was implicitly deleted here">;
 def warn_not_enough_argument : Warning<
   "not enough variable arguments in %0 declaration to fit a sentinel">,
   InGroup<Sentinel>;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Apr  2 15:59:25 2012
@@ -4636,6 +4636,13 @@
     return true;
   }
 
+  // For an anonymous struct or union, the copy and assignment special members
+  // will never be used, so skip the check. For an anonymous union declared at
+  // namespace scope, the constructor and destructor are used.
+  if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
+      RD->isAnonymousStructOrUnion())
+    return false;
+
   // 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
@@ -4667,6 +4674,9 @@
     }
   }
 
+  // Do access control from the special member function
+  ContextRAII MethodContext(*this, MD);
+
   // 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
@@ -4682,16 +4692,6 @@
     }
   }
 
-  // For an anonymous struct or union, the copy and assignment special members
-  // will never be used, so skip the check. For an anonymous union declared at
-  // namespace scope, the constructor and destructor are used.
-  if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
-      RD->isAnonymousStructOrUnion())
-    return false;
-
-  // Do access control from the special member function
-  ContextRAII MethodContext(*this, MD);
-
   SpecialMemberDeletionInfo SMI(*this, MD, CSM, Diagnose);
 
   for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(),

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr  2 15:59:25 2012
@@ -112,15 +112,18 @@
 void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
   CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Decl);
 
-  if (Method && Method->isImplicit()) {
+  if (Method && Method->isDeleted() && !Method->isDeletedAsWritten()) {
+    // If the method was explicitly defaulted, point at that declaration.
+    if (!Method->isImplicit())
+      Diag(Decl->getLocation(), diag::note_implicitly_deleted);
+
+    // Try to diagnose why this special member function was implicitly
+    // deleted. This might fail, if that reason no longer applies.
     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;
+    if (CSM != CXXInvalid)
+      ShouldDeleteSpecialMember(Method, CSM, /*Diagnose=*/true);
+
+    return;
   }
 
   Diag(Decl->getLocation(), diag::note_unavailable_here)

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Apr  2 15:59:25 2012
@@ -8237,7 +8237,8 @@
     OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
 
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
-      << FnKind << FnDesc << Fn->isDeleted();
+      << FnKind << FnDesc
+      << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0);
     MaybeEmitInheritedConstructorNote(S, Fn);
     return;
   }
@@ -10086,9 +10087,11 @@
           << getSpecialMember(Method)
           << BinaryOperator::getOpcodeStr(Opc)
           << getDeletedOrUnavailableSuffix(Best->Function);
-        
-        if (Method->getParent()->isLambda()) {
-          Diag(Method->getParent()->getLocation(), diag::note_lambda_decl);
+
+        if (getSpecialMember(Method) != CXXInvalid) {
+          // The user probably meant to call this special member. Just
+          // explain why it's deleted.
+          NoteDeletedFunction(Method);
           return ExprError();
         }
       } else {

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=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp (original)
+++ cfe/trunk/test/CXX/special/class.copy/implicit-move.cpp Mon Apr  2 15:59:25 2012
@@ -25,10 +25,10 @@
   HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false);
 };
 
-struct HasMoveConstructor { // expected-note {{implicit copy assignment}}
+struct HasMoveConstructor {
   ThrowingCopy tc;
   HasMoveConstructor() noexcept;
-  HasMoveConstructor(HasMoveConstructor &&) noexcept;
+  HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{deleted because 'HasMoveConstructor' has a user-declared move constructor}}
 };
 
 struct HasMoveAssignment { // expected-note {{implicit 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=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.ctor/p5-0x.cpp Mon Apr  2 15:59:25 2012
@@ -31,11 +31,9 @@
 // - any non-static data member with no brace-or-equal-initializer is of
 // reference type,
 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() = default;  // expected-note 4{{implicitly deleted here}}
+  int &a; // expected-note 4{{because field 'a' of reference type 'int &' would not be initialized}}
+};
 Deleted2a d2a; // expected-error {{implicitly-deleted default constructor}}
 struct Deleted2b {
   int &&b; // expected-note {{default constructor of 'Deleted2b' is implicitly deleted because field 'b' of reference type 'int &&' would not be initialized}}

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=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp (original)
+++ cfe/trunk/test/CXX/special/class.dtor/p5-0x.cpp Mon Apr  2 15:59:25 2012
@@ -90,15 +90,15 @@
 public:
   virtual ~D1() = default;
 } d1; // ok
-struct D2 : D1 { // expected-note {{deleted here}}
+struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
   // implicitly-virtual destructor
 } d2; // expected-error {{deleted function}}
-struct D3 {
-  virtual ~D3() = default; // expected-note {{deleted here}}
+struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+  virtual ~D3() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}}
   void operator delete(void*, double = 0.0);
   void operator delete(void*, char = 0);
 } d3; // expected-error {{deleted function}}
-struct D4 {
-  virtual ~D4() = default; // expected-note {{deleted here}}
+struct D4 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+  virtual ~D4() = default; // expected-note {{implicitly deleted here}}
   void operator delete(void*) = delete;
 } d4; // expected-error {{deleted function}}

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=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-deleted-default-ctor.cpp Mon Apr  2 15:59:25 2012
@@ -59,7 +59,7 @@
 good_const gc;
 
 struct no_default {
-  no_default() = delete; // expected-note 2{{deleted here}}
+  no_default() = delete; // expected-note 3{{deleted here}}
 };
 struct no_dtor {
   ~no_dtor() = delete; // expected-note 2{{deleted here}}
@@ -108,8 +108,8 @@
 has_friend hf;
 
 struct defaulted_delete {
-  no_default nd;
-  defaulted_delete() = default; // expected-note{{deleted here}}
+  no_default nd; // expected-note {{because field 'nd' has a deleted default constructor}}
+  defaulted_delete() = default; // expected-note{{implicitly deleted here}}
 };
 defaulted_delete dd; // expected-error {{call to implicitly-deleted default constructor}}
 

Modified: cfe/trunk/test/SemaCXX/dr1301.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dr1301.cpp?rev=153894&r1=153893&r2=153894&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dr1301.cpp (original)
+++ cfe/trunk/test/SemaCXX/dr1301.cpp Mon Apr  2 15:59:25 2012
@@ -6,7 +6,7 @@
 int a = A().n; // expected-error {{no matching constructor}}
 
 struct B {
-  B() = delete; // expected-note 2{{here}}
+  B() = delete; // expected-note 3{{here}}
   int n;
 };
 int b = B().n; // expected-error {{call to deleted}}
@@ -18,7 +18,7 @@
 
 struct D {
   D() = default; // expected-note {{here}}
-  B b;
+  B b; // expected-note {{'b' has a deleted default constructor}}
 };
 int d = D().b.n; // expected-error {{call to implicitly-deleted default}}
 





More information about the cfe-commits mailing list