[cfe-commits] r61048 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def lib/AST/DeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaOverload.cpp test/SemaCXX/constructor.cpp test/SemaCXX/overload-decl.cpp

Douglas Gregor dgregor at apple.com
Mon Dec 15 13:24:18 PST 2008


Author: dgregor
Date: Mon Dec 15 15:24:18 2008
New Revision: 61048

URL: http://llvm.org/viewvc/llvm-project?rev=61048&view=rev
Log:
Place constructors and destructors into the DeclContext of the class,
just like all other members, and remove the special variables in
CXXRecordDecl to store them. This eliminates a lot of special-case
code for constructors and destructors, including
ActOnConstructor/ActOnDeclarator and special lookup rules in
LookupDecl. The result is far more uniform and manageable.

Diagnose the redeclaration of member functions.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/constructor.cpp
    cfe/trunk/test/SemaCXX/overload-decl.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Dec 15 15:24:18 2008
@@ -260,9 +260,13 @@
   bool UserDeclaredConstructor : 1;
 
   /// UserDeclaredCopyConstructor - True when this class has a
-  /// user-defined copy constructor.
+  /// user-declared copy constructor.
   bool UserDeclaredCopyConstructor : 1;
 
+  /// UserDeclaredDestructor - True when this class has a
+  /// user-declared destructor.
+  bool UserDeclaredDestructor : 1;
+
   /// Aggregate - True when this class is an aggregate.
   bool Aggregate : 1;
 
@@ -277,14 +281,6 @@
   /// NumBases - The number of base class specifiers in Bases.
   unsigned NumBases;
 
-  /// Constructors - Overload set containing the constructors of this
-  /// C++ class. Each of the entries in this overload set is a
-  /// CXXConstructorDecl.
-  OverloadedFunctionDecl Constructors;
-
-  // Destructor - The destructor of this C++ class.
-  CXXDestructorDecl *Destructor;
-
   /// Conversions - Overload set containing the conversion functions
   /// of this C++ class (but not its inherited conversion
   /// functions). Each of the entries in this overload set is a
@@ -321,20 +317,14 @@
   base_class_iterator       bases_end()         { return Bases + NumBases; }
   base_class_const_iterator bases_end()   const { return Bases + NumBases; }
 
-  /// getConstructors - Retrieve the overload set containing all of
-  /// the constructors of this class.
-  OverloadedFunctionDecl       *getConstructors()       { return &Constructors; }
-
-  /// getConstructors - Retrieve the overload set containing all of
-  /// the constructors of this class.
-  const OverloadedFunctionDecl *getConstructors() const { return &Constructors; }
-
   /// hasConstCopyConstructor - Determines whether this class has a
   /// copy constructor that accepts a const-qualified argument.
   bool hasConstCopyConstructor(ASTContext &Context) const;
 
-  /// addConstructor - Add another constructor to the list of constructors.
-  void addConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
+  /// addedConstructor - Notify the class that another constructor has
+  /// been added. This routine helps maintain information about the
+  /// class based on which constructors have been added.
+  void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
 
   /// hasUserDeclaredConstructor - Whether this class has any
   /// user-declared constructors. When true, a default constructor
@@ -348,13 +338,16 @@
     return UserDeclaredCopyConstructor;
   }
 
-  /// getDestructor - Retrieve the destructor for this class. 
-  CXXDestructorDecl *getDestructor() const { return Destructor; }
-
-  /// setDestructor - Set the destructor for this class.
-  void setDestructor(CXXDestructorDecl *Destructor) {
-    assert(!this->Destructor && "Already have a destructor!");
-    this->Destructor = Destructor;
+  /// hasUserDeclaredDestructor - Whether this class has a
+  /// user-declared destructor. When false, a destructor will be
+  /// implicitly declared.
+  bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
+
+  /// setUserDeclaredDestructor - Set whether this class has a
+  /// user-declared destructor. If not set by the time the class is
+  /// fully defined, a destructor will be implicitly declared.
+  void setUserDeclaredDestructor(bool UCD = true) { 
+    UserDeclaredDestructor = UCD; 
   }
 
   /// getConversions - Retrieve the overload set containing all of the
@@ -402,8 +395,6 @@
     return static_cast<CXXRecordDecl *>(const_cast<DeclContext*>(DC));
   }
 
-  virtual void Destroy(ASTContext& C);
-
 protected:
   /// EmitImpl - Serialize this CXXRecordDecl.  Called by Decl::Emit.
   // FIXME: Implement this.

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61048&r1=61047&r2=61048&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 15 15:24:18 2008
@@ -1169,6 +1169,7 @@
      "incomplete definition of type %0")
 DIAG(err_typecheck_no_member, ERROR,
      "no member named %0")
+DIAG(err_member_redeclared, ERROR, "class member cannot be redeclared")
 DIAG(err_typecheck_ivar_variable_size, ERROR,
      "instance variables must have a constant size")
 // FIXME: Improve with %select

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=61048&r1=61047&r2=61048&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Dec 15 15:24:18 2008
@@ -40,9 +40,8 @@
                              SourceLocation L, IdentifierInfo *Id) 
   : RecordDecl(CXXRecord, TK, DC, L, Id),
     UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
-    Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
-    Constructors(DC, DeclarationName()),
-    Destructor(0), 
+    UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false), 
+    Bases(0), NumBases(0),
     Conversions(DC, DeclarationName()) { }
 
 CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
@@ -58,18 +57,6 @@
   delete [] Bases;
 }
 
-void CXXRecordDecl::Destroy(ASTContext &C) {
-  for (OverloadedFunctionDecl::function_iterator func 
-         = Constructors.function_begin();
-       func != Constructors.function_end(); ++func)
-    (*func)->Destroy(C);
-
-  if (isDefinition())
-    Destructor->Destroy(C);
-
-  RecordDecl::Destroy(C);
-}
-
 void 
 CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, 
                         unsigned NumBases) {
@@ -88,20 +75,35 @@
 }
 
 bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
-  for (OverloadedFunctionDecl::function_const_iterator Con 
-         = Constructors.function_begin();
-       Con != Constructors.function_end(); ++Con) {
-    unsigned TypeQuals;
+  QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
+  DeclarationName ConstructorName 
+    = Context.DeclarationNames.getCXXConstructorName(
+                                           Context.getCanonicalType(ClassType));
+  unsigned TypeQuals;
+  DeclContext::lookup_const_result Lookup 
+    = this->lookup(Context, ConstructorName);
+  if (Lookup.first == Lookup.second)
+    return false;
+  else if (OverloadedFunctionDecl *Constructors             
+             = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+    for (OverloadedFunctionDecl::function_const_iterator Con 
+           = Constructors->function_begin();
+         Con != Constructors->function_end(); ++Con) {
     if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
         (TypeQuals & QualType::Const != 0))
       return true;
+    }
+  } else if (CXXConstructorDecl *Constructor 
+               = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
+    return Constructor->isCopyConstructor(Context, TypeQuals) &&
+           (TypeQuals & QualType::Const != 0);
   }
   return false;
 }
 
 void 
-CXXRecordDecl::addConstructor(ASTContext &Context, 
-                              CXXConstructorDecl *ConDecl) {
+CXXRecordDecl::addedConstructor(ASTContext &Context, 
+                                CXXConstructorDecl *ConDecl) {
   if (!ConDecl->isImplicitlyDeclared()) {
     // Note that we have a user-declared constructor.
     UserDeclaredConstructor = true;
@@ -116,8 +118,6 @@
     if (ConDecl->isCopyConstructor(Context))
       UserDeclaredCopyConstructor = true;
   }
-
-  Constructors.addOverload(ConDecl);
 }
 
 void CXXRecordDecl::addConversionFunction(ASTContext &Context, 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61048&r1=61047&r2=61048&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Dec 15 15:24:18 2008
@@ -963,8 +963,6 @@
                                  FunctionDecl::StorageClass& SC);
   bool CheckConversionDeclarator(Declarator &D, QualType &R,
                                  FunctionDecl::StorageClass& SC);
-  DeclTy *ActOnConstructorDeclarator(CXXConstructorDecl *Constructor);
-  DeclTy *ActOnDestructorDeclarator(CXXDestructorDecl *Destructor);
   DeclTy *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
 
   //===--------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Dec 15 15:24:18 2008
@@ -138,20 +138,20 @@
                                              FD->getDeclName());
         Ovl->addOverload(cast<FunctionDecl>(Prev));
         
-       // If there is an ame binding for the existing FunctionDecl,
-       // remove it.
-       for (IdentifierResolver::iterator I 
-              = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(), 
-                                 false/*LookInParentCtx*/),
-              E = IdResolver.end(); I != E; ++I) {
-         if (*I == Prev) {
-           IdResolver.RemoveDecl(*I);
-           S->RemoveDecl(*I);
-           break;
-         }
-       }
+        // If there is a name binding for the existing FunctionDecl,
+        // remove it.
+        for (IdentifierResolver::iterator I 
+               = IdResolver.begin(FD->getDeclName(), FD->getDeclContext(), 
+                                  false/*LookInParentCtx*/),
+               E = IdResolver.end(); I != E; ++I) {
+          if (*I == Prev) {
+            IdResolver.RemoveDecl(*I);
+            S->RemoveDecl(*I);
+            break;
+          }
+        }
        
-       // Add the name binding for the OverloadedFunctionDecl.
+        // Add the name binding for the OverloadedFunctionDecl.
         IdResolver.AddDecl(Ovl);
 
         // Update the context with the newly-created overloaded
@@ -246,24 +246,6 @@
   } 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;
@@ -565,6 +547,26 @@
         Diag(Old->getLocation(), PrevDiag);
         return New;
       }
+
+      // 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.
+      if (OldMethod->getLexicalDeclContext() == 
+            NewMethod->getLexicalDeclContext()) {
+        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);
+      }
     }
 
     // (C++98 8.3.5p3):
@@ -1117,6 +1119,11 @@
     // Handle attributes.
     ProcessDeclAttributes(NewFD, D);
 
+    // Set the lexical context. If the declarator has a C++
+    // scope specifier, the lexical context will be different
+    // from the semantic context.
+    NewFD->setLexicalDeclContext(CurContext);
+
     // Handle GNU asm-label extension (encoded as an attribute).
     if (Expr *E = (Expr*) D.getAsmLabel()) {
       // The parser guarantees this is a string.
@@ -1189,18 +1196,33 @@
       }
     }
 
-    // C++ constructors and destructors are handled by separate
-    // routines, since they don't require any declaration merging (C++
-    // [class.mfct]p2) and they aren't ever pushed into scope, because
-    // they can't be found by name lookup anyway (C++ [class.ctor]p2).
-    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
-      return ActOnConstructorDeclarator(Constructor);
-    else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(NewFD))
-      return ActOnDestructorDeclarator(Destructor);
-    
-    // Extra checking for conversion functions, including recording
-    // the conversion function in its class.
-    if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+    if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) {
+      CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DC);
+
+      // 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
+      //   either there are no other parameters or else all other
+      //   parameters have default arguments.
+      if ((Constructor->getNumParams() == 1) || 
+          (Constructor->getNumParams() > 1 && 
+           Constructor->getParamDecl(1)->getDefaultArg() != 0)) {
+        QualType ParamType = Constructor->getParamDecl(0)->getType();
+        QualType ClassTy = Context.getTagDeclType(ClassDecl);
+        if (Context.getCanonicalType(ParamType).getUnqualifiedType() 
+              == ClassTy) {
+          Diag(Constructor->getLocation(), diag::err_constructor_byvalue_arg)
+            << SourceRange(Constructor->getParamDecl(0)->getLocation());
+          Constructor->setInvalidDecl();
+        }
+      }
+
+      // Notify the class that we've added a constructor.
+      ClassDecl->addedConstructor(Context, Constructor);
+    }
+    else if (isa<CXXDestructorDecl>(NewFD))
+      cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
+    else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
       ActOnConversionDeclarator(Conversion);
 
     // Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -1268,11 +1290,6 @@
             CheckCXXDefaultArguments(NewFD);
           }
 
-         // Set the lexical context. If the declarator has a C++
-         // scope specifier, the lexical context will be different
-         // from the semantic context.
-         NewFD->setLexicalDeclContext(CurContext);
-
          return NewFD;
         }
       }
@@ -1965,7 +1982,9 @@
     //   function return type, in the declaration of a class member
     //   within its class declaration (9.2), and where the extern
     //   specifier is explicitly used.
-    if (Type->isReferenceType() && Var->getStorageClass() != VarDecl::Extern) {
+    if (Type->isReferenceType() && 
+        Var->getStorageClass() != VarDecl::Extern &&
+        Var->getStorageClass() != VarDecl::PrivateExtern) {
       Diag(Var->getLocation(), diag::err_reference_var_requires_init)
         << Var->getDeclName()
         << SourceRange(Var->getLocation(), Var->getLocation());
@@ -1984,7 +2003,9 @@
       QualType InitType = Type;
       if (const ArrayType *Array = Context.getAsArrayType(Type))
         InitType = Array->getElementType();
-      if (InitType->isRecordType()) {
+      if (Var->getStorageClass() != VarDecl::Extern &&
+          Var->getStorageClass() != VarDecl::PrivateExtern &&
+          InitType->isRecordType()) {
         const CXXConstructorDecl *Constructor
           = PerformInitializationByConstructor(InitType, 0, 0, 
                                                Var->getLocation(),

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 15 15:24:18 2008
@@ -744,7 +744,10 @@
                                  /*isInline=*/true,
                                  /*isImplicitlyDeclared=*/true);
     DefaultCon->setAccess(AS_public);
-    ClassDecl->addConstructor(Context, DefaultCon);
+    ClassDecl->addDecl(Context, DefaultCon);
+
+    // Notify the class that we've added a constructor.
+    ClassDecl->addedConstructor(Context, DefaultCon);
   }
 
   if (!ClassDecl->hasUserDeclaredCopyConstructor()) {
@@ -820,10 +823,27 @@
                                                  ArgType, VarDecl::None, 0, 0);
     CopyConstructor->setParams(&FromParam, 1);
 
-    ClassDecl->addConstructor(Context, CopyConstructor);
+    ClassDecl->addedConstructor(Context, CopyConstructor);
+    DeclContext::lookup_result Lookup = ClassDecl->lookup(Context, Name);
+    if (Lookup.first == Lookup.second 
+        || (!isa<CXXConstructorDecl>(*Lookup.first) &&
+            !isa<OverloadedFunctionDecl>(*Lookup.first)))
+      ClassDecl->addDecl(Context, CopyConstructor);
+    else {
+      OverloadedFunctionDecl *Ovl 
+        = dyn_cast<OverloadedFunctionDecl>(*Lookup.first);
+      if (!Ovl) {
+        Ovl = OverloadedFunctionDecl::Create(Context, ClassDecl, Name);
+        Ovl->addOverload(cast<CXXConstructorDecl>(*Lookup.first));
+        ClassDecl->insert(Context, Ovl);
+      }
+
+      Ovl->addOverload(CopyConstructor);
+      ClassDecl->addDecl(Context, CopyConstructor, false);
+    }
   }
 
-  if (!ClassDecl->getDestructor()) {
+  if (!ClassDecl->hasUserDeclaredDestructor()) {
     // C++ [class.dtor]p2:
     //   If a class has no user-declared destructor, a destructor is
     //   declared implicitly. An implicitly-declared destructor is an
@@ -838,7 +858,7 @@
                                   /*isInline=*/true,
                                   /*isImplicitlyDeclared=*/true);
     Destructor->setAccess(AS_public);
-    ClassDecl->setDestructor(Destructor);
+    ClassDecl->addDecl(Context, Destructor);
   }
 
   // FIXME: Implicit copy assignment operator
@@ -1087,101 +1107,6 @@
   return isInvalid;
 }
 
-/// ActOnConstructorDeclarator - Called by ActOnDeclarator to complete
-/// the declaration of the given C++ constructor ConDecl that was
-/// built from declarator D. This routine is responsible for checking
-/// that the newly-created constructor declaration is well-formed and
-/// for recording it in the C++ class. Example:
-///
-/// @code 
-/// class X {
-///   X(); // X::X() will be the ConDecl.
-/// };
-/// @endcode
-Sema::DeclTy *Sema::ActOnConstructorDeclarator(CXXConstructorDecl *ConDecl) {
-  assert(ConDecl && "Expected to receive a constructor declaration");
-
-  // Check default arguments on the constructor
-  CheckCXXDefaultArguments(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 (CurContext == (*MatchedDecl)->getLexicalDeclContext()) {
-      Diag(ConDecl->getLocation(), diag::err_constructor_redeclared)
-        << SourceRange(ConDecl->getLocation());
-      Diag((*MatchedDecl)->getLocation(), diag::note_previous_declaration)
-        << SourceRange((*MatchedDecl)->getLocation());
-      ConDecl->setInvalidDecl();
-      return 0;
-    }
-
-    // FIXME: Just drop the definition (for now).
-    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
-  //   either there are no other parameters or else all other
-  //   parameters have default arguments.
-  if ((ConDecl->getNumParams() == 1) || 
-      (ConDecl->getNumParams() > 1 && 
-       ConDecl->getParamDecl(1)->getDefaultArg() != 0)) {
-    QualType ParamType = ConDecl->getParamDecl(0)->getType();
-    QualType ClassTy = Context.getTagDeclType(
-                         const_cast<CXXRecordDecl*>(ConDecl->getParent()));
-    if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
-      Diag(ConDecl->getLocation(), diag::err_constructor_byvalue_arg)
-        << SourceRange(ConDecl->getParamDecl(0)->getLocation());
-      ConDecl->setInvalidDecl();
-      return ConDecl;
-    }
-  }
-      
-  // Add this constructor to the set of constructors of the current
-  // class. 
-  ClassDecl->addConstructor(Context, ConDecl);
-  return (DeclTy *)ConDecl;
-}
-
-/// ActOnDestructorDeclarator - Called by ActOnDeclarator to complete
-/// the declaration of the given C++ @p Destructor. This routine is
-/// responsible for recording the destructor in the C++ class, if
-/// possible.
-Sema::DeclTy *Sema::ActOnDestructorDeclarator(CXXDestructorDecl *Destructor) {
-  assert(Destructor && "Expected to receive a destructor declaration");
-
-  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()) {
-    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;
-  }
-
-  ClassDecl->setDestructor(Destructor);
-  return (DeclTy *)Destructor;
-}
-
 /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
 /// the declaration of the given C++ conversion function. This routine
 /// is responsible for recording the conversion function in the C++
@@ -1437,18 +1362,35 @@
   OverloadCandidateSet CandidateSet;
 
   // Add constructors to the overload set.
-  OverloadedFunctionDecl *Constructors 
-    = const_cast<OverloadedFunctionDecl *>(ClassDecl->getConstructors());
-  for (OverloadedFunctionDecl::function_iterator Con 
-         = Constructors->function_begin();
-       Con != Constructors->function_end(); ++Con) {
-    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+  DeclarationName ConstructorName 
+    = Context.DeclarationNames.getCXXConstructorName(
+                       Context.getCanonicalType(ClassType.getUnqualifiedType()));
+  DeclContext::lookup_const_result Lookup 
+    = ClassDecl->lookup(Context, ConstructorName);
+  if (Lookup.first == Lookup.second)
+    /* No constructors */;
+  else if (OverloadedFunctionDecl *Constructors 
+             = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+    for (OverloadedFunctionDecl::function_iterator Con 
+           = Constructors->function_begin();
+         Con != Constructors->function_end(); ++Con) {
+      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
+      if ((Kind == IK_Direct) ||
+          (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
+          (Kind == IK_Default && Constructor->isDefaultConstructor()))
+        AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+    }
+  } else if (CXXConstructorDecl *Constructor 
+               = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
     if ((Kind == IK_Direct) ||
         (Kind == IK_Copy && Constructor->isConvertingConstructor()) ||
         (Kind == IK_Default && Constructor->isDefaultConstructor()))
       AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
   }
 
+  // FIXME: When we decide not to synthesize the implicitly-declared
+  // constructors, we'll need to make them appear here.
+
   OverloadCandidateSet::iterator Best;
   switch (BestViableFunction(CandidateSet, Best)) {
   case OR_Success:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Dec 15 15:24:18 2008
@@ -953,11 +953,25 @@
     //   that class. The argument list is the expression-list within
     //   the parentheses of the initializer.
     CXXRecordDecl *ToRecordDecl = ToRecordType->getDecl();
-    const OverloadedFunctionDecl *Constructors = ToRecordDecl->getConstructors();
-    for (OverloadedFunctionDecl::function_const_iterator func 
-           = Constructors->function_begin();
-         func != Constructors->function_end(); ++func) {
-      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
+    DeclarationName ConstructorName 
+      = Context.DeclarationNames.getCXXConstructorName(
+                                             Context.getCanonicalType(ToType));
+    DeclContext::lookup_result Lookup 
+      = ToRecordDecl->lookup(Context, ConstructorName);
+    if (Lookup.first == Lookup.second)
+      /* No constructors. FIXME: Implicit copy constructor? */;
+    else if (OverloadedFunctionDecl *Constructors 
+               = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
+      for (OverloadedFunctionDecl::function_const_iterator func 
+             = Constructors->function_begin();
+           func != Constructors->function_end(); ++func) {
+        CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*func);
+        if (Constructor->isConvertingConstructor())
+          AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
+                               /*SuppressUserConversions=*/true);
+      }
+    } else if (CXXConstructorDecl *Constructor 
+                 = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
       if (Constructor->isConvertingConstructor())
         AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
                              /*SuppressUserConversions=*/true);

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

==============================================================================
--- cfe/trunk/test/SemaCXX/constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor.cpp Mon Dec 15 15:24:18 2008
@@ -21,3 +21,9 @@
 
 Foo::Foo(const Foo&) { }
 
+typedef struct {
+  int version;
+} Anon;
+extern const Anon anon;
+extern "C" const Anon anon2;
+

Modified: cfe/trunk/test/SemaCXX/overload-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-decl.cpp?rev=61048&r1=61047&r2=61048&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overload-decl.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-decl.cpp Mon Dec 15 15:24:18 2008
@@ -13,11 +13,15 @@
 void g(void); // expected-note {{previous declaration is here}}
 int g(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
 
+typedef int INT;
+
 class X {
   void f();
-  void f(int);
+  void f(int); // expected-note {{previous declaration is here}}
   void f() const;
 
+  void f(INT); // expected-error{{cannot be redeclared}}
+
   void g(int); // expected-note {{previous declaration is here}}
   void g(int, float); // expected-note {{previous declaration is here}}
   int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}}





More information about the cfe-commits mailing list