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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61048 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 1efb174..6f1683e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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: