Semantic checking of constructor declarations and classification of default/copy constructors

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58538 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 41e61ed..fb47904 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -59,6 +59,22 @@
     this->Bases[i] = *Bases[i];
 }
 
+void 
+CXXRecordDecl::addConstructor(ASTContext &Context, 
+                              CXXConstructorDecl *ConDecl) {
+  if (!ConDecl->isImplicitlyDeclared()) {
+    // Note that we have a user-declared constructor.
+    UserDeclaredConstructor = true;
+
+    // Note when we have a user-declared copy constructor, which will
+    // suppress the implicit declaration of a copy constructor.
+    if (ConDecl->isCopyConstructor(Context))
+      UserDeclaredCopyConstructor = true;
+  }
+
+  Constructors.addOverload(ConDecl);
+}
+
 CXXMethodDecl *
 CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                       SourceLocation L, IdentifierInfo *Id,
@@ -76,8 +92,7 @@
   // the type of this is const volatile X*.
 
   assert(isInstance() && "No 'this' for static methods!");
-  QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(
-                                            cast<CXXRecordDecl>(getParent())));
+  QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
   ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
   return C.getPointerType(ClassTy).withConst();
 }
@@ -92,6 +107,47 @@
                                       isImplicitlyDeclared);
 }
 
+bool CXXConstructorDecl::isDefaultConstructor() const {
+  // C++ [class.ctor]p5:
+  //
+  //     A default constructor for a class X is a constructor of class
+  //     X that can be called without an argument.
+  return (getNumParams() == 0) ||
+         (getNumParams() > 0 & getParamDecl(1)->getDefaultArg() != 0);
+}
+
+bool 
+CXXConstructorDecl::isCopyConstructor(ASTContext &Context, 
+                                      unsigned &TypeQuals) const {
+  // C++ [class.copy]p2:
+  //     A non-template constructor for class X is a copy constructor
+  //     if its first parameter is of type X&, const X&, volatile X& or
+  //     const volatile X&, and either there are no other parameters
+  //     or else all other parameters have default arguments (8.3.6).
+  if ((getNumParams() < 1) ||
+      (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
+    return false;
+
+  const ParmVarDecl *Param = getParamDecl(0);
+
+  // Do we have a reference type?
+  const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
+  if (!ParamRefType)
+    return false;
+
+  // Is it a reference to our class type?
+  QualType PointeeType 
+    = Context.getCanonicalType(ParamRefType->getPointeeType());
+  QualType ClassTy 
+    = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
+  if (PointeeType.getUnqualifiedType() != ClassTy)
+    return false;
+
+  // We have a copy constructor.
+  TypeQuals = PointeeType.getCVRQualifiers();
+  return true;
+}
+
 bool CXXConstructorDecl::isConvertingConstructor() const {
   // C++ [class.conv.ctor]p1:
   //   A constructor declared without the function-specifier explicit