[cfe-commits] r118418 - in /cfe/trunk: include/clang/AST/DeclCXX.h lib/AST/DeclCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp test/SemaTemplate/constructor-template.cpp

Douglas Gregor dgregor at apple.com
Mon Nov 8 09:17:00 PST 2010


Author: dgregor
Date: Mon Nov  8 11:16:59 2010
New Revision: 118418

URL: http://llvm.org/viewvc/llvm-project?rev=118418&view=rev
Log:
Improve our handling of C++ [class.copy]p3, which specifies that a
constructor template will not be used to copy a class object to a
value of its own type. We were eliminating all constructor templates
whose specializations look like a copy constructor, which eliminated
important candidates. Fixes PR8182.

Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaTemplate/constructor-template.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=118418&r1=118417&r2=118418&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Nov  8 11:16:59 2010
@@ -1469,9 +1469,9 @@
   bool isConvertingConstructor(bool AllowExplicit) const;
 
   /// \brief Determine whether this is a member template specialization that
-  /// looks like a copy constructor. Such constructors are never used to copy
+  /// would copy the object to itself. Such constructors are never used to copy
   /// an object.
-  bool isCopyConstructorLikeSpecialization() const;
+  bool isSpecializationCopyingObject() const;
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=118418&r1=118417&r2=118418&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Nov  8 11:16:59 2010
@@ -1176,7 +1176,7 @@
          (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg());
 }
 
-bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const {
+bool CXXConstructorDecl::isSpecializationCopyingObject() const {
   if ((getNumParams() < 1) ||
       (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
       (getPrimaryTemplate() == 0) ||
@@ -1188,12 +1188,6 @@
   ASTContext &Context = getASTContext();
   CanQualType ParamType = Context.getCanonicalType(Param->getType());
   
-  // Strip off the lvalue reference, if any.
-  if (CanQual<LValueReferenceType> ParamRefType
-                                    = ParamType->getAs<LValueReferenceType>())
-    ParamType = ParamRefType->getPointeeType();
-
-  
   // Is it the same as our our class type?
   CanQualType ClassTy 
     = Context.getCanonicalType(Context.getTagDeclType(getParent()));

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=118418&r1=118417&r2=118418&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Nov  8 11:16:59 2010
@@ -3391,17 +3391,39 @@
   OverloadCandidateSet CandidateSet(Loc);
   for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
        Con != ConEnd; ++Con) {
-    // Only consider copy constructors.
-    CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con);
-    if (!Constructor || Constructor->isInvalidDecl() ||
-        !Constructor->isCopyConstructor() ||
-        !Constructor->isConvertingConstructor(/*AllowExplicit=*/false))
+    // Only consider copy constructors and constructor templates.
+    CXXConstructorDecl *Constructor = 0;
+
+    if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
+      // Handle copy constructors, only.
+      if (!Constructor || Constructor->isInvalidDecl() ||
+          !Constructor->isCopyConstructor() ||
+          !Constructor->isConvertingConstructor(/*AllowExplicit=*/false))
+        continue;
+
+      DeclAccessPair FoundDecl
+        = DeclAccessPair::make(Constructor, Constructor->getAccess());
+      S.AddOverloadCandidate(Constructor, FoundDecl,
+                             &CurInitExpr, 1, CandidateSet);
+      continue;
+    } 
+
+    // Handle constructor templates.
+    FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
+    if (ConstructorTmpl->isInvalidDecl())
+      continue;
+
+    Constructor = cast<CXXConstructorDecl>(
+                                         ConstructorTmpl->getTemplatedDecl());
+    if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/false))
       continue;
 
+    // FIXME: Do we need to limit this to copy-constructor-like
+    // candidates?
     DeclAccessPair FoundDecl
-      = DeclAccessPair::make(Constructor, Constructor->getAccess());
-    S.AddOverloadCandidate(Constructor, FoundDecl,
-                           &CurInitExpr, 1, CandidateSet);
+      = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
+    S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0,
+                                   &CurInitExpr, 1, CandidateSet, true);
   }
   
   OverloadCandidateSet::iterator Best;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=118418&r1=118417&r2=118418&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Nov  8 11:16:59 2010
@@ -3457,7 +3457,7 @@
     //   of a class object to an object of its class type.
     QualType ClassType = Context.getTypeDeclType(Constructor->getParent());
     if (NumArgs == 1 && 
-        Constructor->isCopyConstructorLikeSpecialization() &&
+        Constructor->isSpecializationCopyingObject() &&
         (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) ||
          IsDerivedFrom(Args[0]->getType(), ClassType)))
       return;

Modified: cfe/trunk/test/SemaTemplate/constructor-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/constructor-template.cpp?rev=118418&r1=118417&r2=118418&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/constructor-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/constructor-template.cpp Mon Nov  8 11:16:59 2010
@@ -71,16 +71,16 @@
 template<> X3::X3(X3); // expected-error{{must pass its first argument by reference}}
 
 struct X4 {
-  X4(); // expected-note{{candidate constructor}}
+  X4();
   ~X4();
-  X4(X4&);	// expected-note {{candidate constructor}}
+  X4(X4&);
   template<typename T> X4(const T&, int = 17);
 };
 
 X4 test_X4(bool Cond, X4 x4) {
   X4 a(x4, 17); // okay, constructor template
   X4 b(x4); // okay, copy constructor
-  return X4(); // expected-error{{no matching constructor}}
+  return X4();
 }
 
 // Instantiation of a non-dependent use of a constructor
@@ -109,3 +109,20 @@
   X5<X6> tf;
   X5<X6> tf2(tf);
 }
+
+namespace PR8182 {
+  struct foo {
+    foo();
+    template<class T> foo(T&);
+
+  private:
+    foo(const foo&);
+  };
+
+  void test_foo() {
+    foo f1;
+    foo f2(f1);
+    foo f3 = f1;
+  }
+
+}





More information about the cfe-commits mailing list