[cfe-commits] r90605 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/CodeGenCXX/mangle.cpp test/SemaCXX/implicit-member-functions.cpp

Anders Carlsson andersca at mac.com
Fri Dec 4 14:33:25 PST 2009


Author: andersca
Date: Fri Dec  4 16:33:25 2009
New Revision: 90605

URL: http://llvm.org/viewvc/llvm-project?rev=90605&view=rev
Log:
Diagnose declarations of implicit member functions.

Added:
    cfe/trunk/test/SemaCXX/implicit-member-functions.cpp
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=90605&r1=90604&r2=90605&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec  4 16:33:25 2009
@@ -762,6 +762,24 @@
   QualType PromotedType;
 };
 
+
+/// getSpecialMember - get the special member enum for a method.
+static Sema::CXXSpecialMember getSpecialMember(ASTContext &Ctx,
+                                               const CXXMethodDecl *MD) {
+  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
+    if (Ctor->isDefaultConstructor())
+      return Sema::CXXDefaultConstructor;
+    if (Ctor->isCopyConstructor(Ctx))
+      return Sema::CXXCopyConstructor;
+  } 
+  
+  if (isa<CXXDestructorDecl>(MD))
+    return Sema::CXXDestructor;
+  
+  assert(MD->isCopyAssignment() && "Must have copy assignment operator");
+  return Sema::CXXCopyAssignment;
+}
+
 /// MergeFunctionDecl - We just parsed a function 'New' from
 /// declarator D which has the same name and scope as a previous
 /// declaration 'Old'.  Figure out how to resolve this situation,
@@ -827,33 +845,45 @@
 
     const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
     const CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
-    if (OldMethod && NewMethod && !NewMethod->getFriendObjectKind() &&
-        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.
-      if (OldMethod->isStatic() || NewMethod->isStatic()) {
-        Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+    if (OldMethod && NewMethod) {
+      if (!NewMethod->getFriendObjectKind() &&
+          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.
+        if (OldMethod->isStatic() || NewMethod->isStatic()) {
+          Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member);
+          Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
+          return true;
+        }
+      
+        // C++ [class.mem]p1:
+        //   [...] A member shall not be declared twice in the
+        //   member-specification, except that a nested class or member
+        //   class template can be declared and then later defined.
+        unsigned NewDiag;
+        if (isa<CXXConstructorDecl>(OldMethod))
+          NewDiag = diag::err_constructor_redeclared;
+        else if (isa<CXXDestructorDecl>(NewMethod))
+          NewDiag = diag::err_destructor_redeclared;
+        else if (isa<CXXConversionDecl>(NewMethod))
+          NewDiag = diag::err_conv_function_redeclared;
+        else
+          NewDiag = diag::err_member_redeclared;
+
+        Diag(New->getLocation(), NewDiag);
         Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
-        return true;
+      } else {
+        if (OldMethod->isImplicit()) {
+          Diag(NewMethod->getLocation(),
+               diag::err_definition_of_implicitly_declared_member) 
+          << New << getSpecialMember(Context, OldMethod);
+        
+          Diag(OldMethod->getLocation(),
+               diag::note_previous_implicit_declaration);
+          return true;
+        }
       }
-
-      // C++ [class.mem]p1:
-      //   [...] A member shall not be declared twice in the
-      //   member-specification, except that a nested class or member
-      //   class template can be declared and then later defined.
-      unsigned NewDiag;
-      if (isa<CXXConstructorDecl>(OldMethod))
-        NewDiag = diag::err_constructor_redeclared;
-      else if (isa<CXXDestructorDecl>(NewMethod))
-        NewDiag = diag::err_destructor_redeclared;
-      else if (isa<CXXConversionDecl>(NewMethod))
-        NewDiag = diag::err_conv_function_redeclared;
-      else
-        NewDiag = diag::err_member_redeclared;
-
-      Diag(New->getLocation(), NewDiag);
-      Diag(Old->getLocation(), PrevDiag) << Old << Old->getType();
     }
 
     // (C++98 8.3.5p3):

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=90605&r1=90604&r2=90605&view=diff

==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Fri Dec  4 16:33:25 2009
@@ -208,8 +208,9 @@
 void extern_f(void) { }
 
 struct S7 {
-  struct S { S(); };
+  S7();
   
+  struct S { S(); };
   struct {
     S s;
   } a;

Added: cfe/trunk/test/SemaCXX/implicit-member-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-member-functions.cpp?rev=90605&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-member-functions.cpp (added)
+++ cfe/trunk/test/SemaCXX/implicit-member-functions.cpp Fri Dec  4 16:33:25 2009
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct A { }; // expected-note {{previous implicit declaration is here}}
+A::A() { } // expected-error {{definition of implicitly declared constructor}}
+
+struct B { }; // expected-note {{previous implicit declaration is here}}
+B::B(const B&) { } // expected-error {{definition of implicitly declared copy constructor}}
+
+struct C { }; // expected-note {{previous implicit declaration is here}}
+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}}
+D::~D() { } // expected-error {{definition of implicitly declared destructor}}
+





More information about the cfe-commits mailing list