[cfe-commits] r60947 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/constructor.cpp test/SemaCXX/destructor.cpp

Douglas Gregor dgregor at apple.com
Fri Dec 12 00:25:50 PST 2008


Author: dgregor
Date: Fri Dec 12 02:25:50 2008
New Revision: 60947

URL: http://llvm.org/viewvc/llvm-project?rev=60947&view=rev
Log:
Enable out-of-line definitions of C++ constructors and destructors

Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/constructor.cpp
    cfe/trunk/test/SemaCXX/destructor.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=60947&r1=60946&r2=60947&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Fri Dec 12 02:25:50 2008
@@ -178,10 +178,12 @@
   
   IdentifierNamespace getIdentifierNamespace() const {
     switch (DeclKind) {
-    default: assert(0 && "Unknown decl kind!");
+    default: 
+      if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
+        return IDNS_Ordinary;
+      assert(0 && "Unknown decl kind!");
     case ImplicitParam:
     case Typedef:
-    case Function:
     case Var:
     case ParmVar:
     case EnumConstant:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 12 02:25:50 2008
@@ -246,6 +246,24 @@
   } else if (LookupCtx) {
     assert(getLangOptions().CPlusPlus && "No qualified name lookup in C");
 
+    switch (Name.getNameKind()) {
+    case DeclarationName::CXXConstructorName:
+      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
+        return const_cast<CXXRecordDecl *>(Record)->getConstructors();
+      else
+        return 0;
+
+    case DeclarationName::CXXDestructorName:
+      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(LookupCtx))
+        return Record->getDestructor();
+      else
+        return 0;
+
+    default:
+      // Normal name lookup.
+      break;
+    }
+
     // Perform qualified name lookup into the LookupCtx.
     // FIXME: Will need to look into base classes and such.
     DeclContext::lookup_const_iterator I, E;
@@ -932,6 +950,15 @@
     // after the point of declaration in a namespace that encloses the
     // declarations namespace.
     //
+    // FIXME: We need to perform this check later, once we know that
+    // we've actually found a redeclaration. Otherwise, just the fact
+    // that there is some entity with the same name will suppress this
+    // diagnostic, e.g., we fail to diagnose:
+    //   class X {
+    //     void f();
+    //   };
+    //
+    //   void X::f(int) { } // ill-formed, but we don't complain.
     if (PrevDecl == 0) {
       // No previous declaration in the qualifying scope.
       Diag(D.getIdentifierLoc(), diag::err_typecheck_no_member)

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec 12 02:25:50 2008
@@ -1104,16 +1104,16 @@
   // Check default arguments on the constructor
   CheckCXXDefaultArguments(ConDecl);
 
-  CXXRecordDecl *ClassDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
-  if (!ClassDecl) {
-    ConDecl->setInvalidDecl();
-    return ConDecl;
-  }
+  // Set the lexical context of this constructor
+  ConDecl->setLexicalDeclContext(CurContext);
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ConDecl->getDeclContext());
 
   // Make sure this constructor is an overload of the existing
   // constructors.
   OverloadedFunctionDecl::function_iterator MatchedDecl;
-  if (!IsOverload(ConDecl, ClassDecl->getConstructors(), MatchedDecl)) {
+  if (!IsOverload(ConDecl, ClassDecl->getConstructors(), MatchedDecl) &&
+      CurContext == (*MatchedDecl)->getLexicalDeclContext()) {
     Diag(ConDecl->getLocation(), diag::err_constructor_redeclared)
       << SourceRange(ConDecl->getLocation());
     Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
@@ -1122,7 +1122,6 @@
     return ConDecl;
   }
 
-
   // C++ [class.copy]p3:
   //   A declaration of a constructor for a class X is ill-formed if
   //   its first parameter is of type (optionally cv-qualified) X and
@@ -1155,16 +1154,23 @@
 Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
   assert(Destructor && "Expected to receive a destructor declaration");
 
-  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CurContext);
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Destructor->getDeclContext());
+
+  // Set the lexical context of this destructor
+  Destructor->setLexicalDeclContext(CurContext);
 
   // Make sure we aren't redeclaring the destructor.
   if (CXXDestructorDecl *PrevDestructor = ClassDecl->getDestructor()) {
-    Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
-    Diag(PrevDestructor->getLocation(),
-         PrevDestructor->isThisDeclarationADefinition() ?
-             diag::note_previous_definition
-           : diag::note_previous_declaration);
-    Destructor->setInvalidDecl();
+    if (CurContext == PrevDestructor->getLexicalDeclContext()) {
+      Diag(Destructor->getLocation(), diag::err_destructor_redeclared);
+      Diag(PrevDestructor->getLocation(),
+           PrevDestructor->isThisDeclarationADefinition() ?
+               diag::note_previous_definition
+             : diag::note_previous_declaration);
+      Destructor->setInvalidDecl();
+    }
+
+    // FIXME: Just drop the definition (for now).
     return Destructor;
   }
 
@@ -1179,7 +1185,10 @@
 Sema::DeclTy *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
   assert(Conversion && "Expected to receive a conversion function declaration");
 
-  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CurContext);
+  // Set the lexical context of this conversion function
+  Conversion->setLexicalDeclContext(CurContext);
+
+  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());
 
   // Make sure we aren't redeclaring the conversion function.
   QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());

Modified: cfe/trunk/test/SemaCXX/constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor.cpp?rev=60947&r1=60946&r2=60947&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor.cpp Fri Dec 12 02:25:50 2008
@@ -18,3 +18,6 @@
 
   int Foo(int, int); // expected-error{{constructor cannot have a return type}}
 };
+
+Foo::Foo(const Foo&) { }
+

Modified: cfe/trunk/test/SemaCXX/destructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/destructor.cpp?rev=60947&r1=60946&r2=60947&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/destructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/destructor.cpp Fri Dec 12 02:25:50 2008
@@ -38,3 +38,10 @@
 ~; // expected-error {{expected class name}}
 ~undef(); // expected-error {{expected class name}}
 ~F(){} // expected-error {{destructor must be a non-static member function}}
+
+struct G {
+  ~G();
+};
+
+G::~G() { }
+





More information about the cfe-commits mailing list