[cfe-commits] r101122 - in /cfe/trunk: lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/class.access/class.friend/p1.cpp test/SemaCXX/implicit-member-functions.cpp

John McCall rjmccall at apple.com
Tue Apr 13 00:45:41 PDT 2010


Author: rjmccall
Date: Tue Apr 13 02:45:41 2010
New Revision: 101122

URL: http://llvm.org/viewvc/llvm-project?rev=101122&view=rev
Log:
Allow classes to befriend implicitly-declared members.  Fixes PR6207 for
members of non-templated classes.


Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
    cfe/trunk/test/SemaCXX/implicit-member-functions.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=101122&r1=101121&r2=101122&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Apr 13 02:45:41 2010
@@ -1058,10 +1058,14 @@
     }
 
     const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
-    const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+    CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
     if (OldMethod && NewMethod) {
-      if (!NewMethod->getFriendObjectKind() &&
-          NewMethod->getLexicalDeclContext()->isRecord()) {
+      // Preserve triviality.
+      NewMethod->setTrivial(OldMethod->isTrivial());
+
+      bool isFriend = NewMethod->getFriendObjectKind();
+
+      if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) {
         //    -- Member function declarations with the same name and the
         //       same parameter types cannot be overloaded if any of them
         //       is a static member function declaration.
@@ -1087,14 +1091,19 @@
 
         Diag(New->getLocation(), NewDiag);
         Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
-      } else {
-        if (OldMethod->isImplicit()) {
+
+      // Complain if this is an explicit declaration of a special
+      // member that was initially declared implicitly.
+      //
+      // As an exception, it's okay to befriend such methods in order
+      // to permit the implicit constructor/destructor/operator calls.
+      } else if (OldMethod->isImplicit()) {
+        if (isFriend) {
+          NewMethod->setImplicit();
+        } else {
           Diag(NewMethod->getLocation(),
                diag::err_definition_of_implicitly_declared_member) 
-          << New << getSpecialMember(Context, OldMethod);
-        
-          Diag(OldMethod->getLocation(),
-               diag::note_previous_implicit_declaration);
+            << New << getSpecialMember(Context, OldMethod);
           return true;
         }
       }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=101122&r1=101121&r2=101122&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Apr 13 02:45:41 2010
@@ -2682,8 +2682,12 @@
     }
   }
 
-  // Notify the class that we've added a constructor.
-  ClassDecl->addedConstructor(Context, Constructor);
+  // Notify the class that we've added a constructor.  In principle we
+  // don't need to do this for out-of-line declarations; in practice
+  // we only instantiate the most recent declaration of a method, so
+  // we have to call this for everything but friends.
+  if (!Constructor->getFriendObjectKind())
+    ClassDecl->addedConstructor(Context, Constructor);
 }
 
 /// CheckDestructor - Checks a fully-formed destructor for well-formedness, 

Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=101122&r1=101121&r2=101122&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Tue Apr 13 02:45:41 2010
@@ -211,3 +211,14 @@
     };
   }
 }
+
+// PR6207
+namespace test6 {
+  struct A {};
+
+  struct B {
+    friend A::A();
+    friend A::~A();
+    friend A &A::operator=(const A&);
+  };
+}

Modified: cfe/trunk/test/SemaCXX/implicit-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-member-functions.cpp?rev=101122&r1=101121&r2=101122&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-member-functions.cpp (original)
+++ cfe/trunk/test/SemaCXX/implicit-member-functions.cpp Tue Apr 13 02:45:41 2010
@@ -1,15 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-struct A { }; // expected-note {{previous implicit declaration is here}}
+struct A { };
 A::A() { } // expected-error {{definition of implicitly declared constructor}}
 
-struct B { }; // expected-note {{previous implicit declaration is here}}
+struct B { };
 B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}}
 
-struct C { }; // expected-note {{previous implicit declaration is here}}
+struct C { };
 C& C::operator=(const C&) { return *this; } // expected-error {{definition of implicitly declared copy assignment operator}}
 
-struct D { }; // expected-note {{previous implicit declaration is here}}
+struct D { };
 D::~D() { } // expected-error {{definition of implicitly declared destructor}}
 
 // Make sure that the special member functions are introduced for





More information about the cfe-commits mailing list