[cfe-commits] r102269 - in /cfe/trunk: lib/Sema/SemaInit.cpp test/SemaCXX/conditional-expr.cpp test/SemaCXX/conversion-function.cpp test/SemaCXX/overload-call.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 24 13:54:38 PDT 2010


Author: dgregor
Date: Sat Apr 24 15:54:38 2010
New Revision: 102269

URL: http://llvm.org/viewvc/llvm-project?rev=102269&view=rev
Log:
When we are performing copy initialization of a class type via its
copy constructor, suppress user-defined conversions on the
argument. Otherwise, we can end up in a recursion loop where the
bind the argument of the copy constructor to another copy constructor call,
whose argument is then a copy constructor call...

Found by Boost.Regex which, alas, still isn't building.

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/SemaCXX/conditional-expr.cpp
    cfe/trunk/test/SemaCXX/conversion-function.cpp
    cfe/trunk/test/SemaCXX/overload-call.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=102269&r1=102268&r2=102269&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Apr 24 15:54:38 2010
@@ -2636,25 +2636,36 @@
        Con != ConEnd; ++Con) {
     NamedDecl *D = *Con;
     DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
+    bool SuppressUserConversions = false;
+    
     // Find the constructor (which may be a template).
     CXXConstructorDecl *Constructor = 0;
     FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
     if (ConstructorTmpl)
       Constructor = cast<CXXConstructorDecl>(
                                            ConstructorTmpl->getTemplatedDecl());
-    else
+    else {
       Constructor = cast<CXXConstructorDecl>(D);
+
+      // If we're performing copy initialization using a copy constructor, we 
+      // suppress user-defined conversions on the arguments.
+      // FIXME: Move constructors?
+      if (Kind.getKind() == InitializationKind::IK_Copy &&
+          Constructor->isCopyConstructor())
+        SuppressUserConversions = true;
+    }
     
     if (!Constructor->isInvalidDecl() &&
         (AllowExplicit || !Constructor->isExplicit())) {
       if (ConstructorTmpl)
         S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                        /*ExplicitArgs*/ 0,
-                                       Args, NumArgs, CandidateSet);
+                                       Args, NumArgs, CandidateSet,
+                                       SuppressUserConversions);
       else
         S.AddOverloadCandidate(Constructor, FoundDecl,
-                               Args, NumArgs, CandidateSet);
+                               Args, NumArgs, CandidateSet,
+                               SuppressUserConversions);
     }
   }    
     
@@ -2803,7 +2814,8 @@
          Con != ConEnd; ++Con) {
       NamedDecl *D = *Con;
       DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-
+      bool SuppressUserConversions = false;
+      
       // Find the constructor (which may be a template).
       CXXConstructorDecl *Constructor = 0;
       FunctionTemplateDecl *ConstructorTmpl
@@ -2811,18 +2823,29 @@
       if (ConstructorTmpl)
         Constructor = cast<CXXConstructorDecl>(
                                            ConstructorTmpl->getTemplatedDecl());
-      else
+      else {
         Constructor = cast<CXXConstructorDecl>(D);
+        
+        // If we're performing copy initialization using a copy constructor, we 
+        // suppress user-defined conversions on the arguments.
+        // FIXME: Move constructors?
+        if (Kind.getKind() == InitializationKind::IK_Copy &&
+            Constructor->isCopyConstructor())
+          SuppressUserConversions = true;
+        
+      }
       
       if (!Constructor->isInvalidDecl() &&
           Constructor->isConvertingConstructor(AllowExplicit)) {
         if (ConstructorTmpl)
           S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                          /*ExplicitArgs*/ 0,
-                                         &Initializer, 1, CandidateSet);
+                                         &Initializer, 1, CandidateSet,
+                                         SuppressUserConversions);
         else
           S.AddOverloadCandidate(Constructor, FoundDecl,
-                                 &Initializer, 1, CandidateSet);
+                                 &Initializer, 1, CandidateSet,
+                                 SuppressUserConversions);
       }
     }    
   }

Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=102269&r1=102268&r2=102269&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Sat Apr 24 15:54:38 2010
@@ -7,8 +7,7 @@
 struct ToBool { explicit operator bool(); };
 
 struct B;
-struct A { A(); A(const B&); }; // expected-note 2 {{candidate constructor}} \
-               // expected-note 2 {{candidate is the implicit copy constructor}}
+struct A { A(); A(const B&); }; // expected-note 2 {{candidate constructor}}
 struct B { operator A() const; }; // expected-note 2 {{candidate function}}
 struct I { operator int(); };
 struct J { operator I(); };

Modified: cfe/trunk/test/SemaCXX/conversion-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conversion-function.cpp?rev=102269&r1=102268&r2=102269&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conversion-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/conversion-function.cpp Sat Apr 24 15:54:38 2010
@@ -56,7 +56,7 @@
 
 // This used to crash Clang.
 struct Flip;
-struct Flop { // expected-note{{candidate is the implicit copy constructor}}
+struct Flop {
   Flop();
   Flop(const Flip&); // expected-note{{candidate constructor}}
 };
@@ -202,3 +202,16 @@
     return X(Y());
   }
 }
+
+struct Any {
+  Any(...);
+};
+
+struct Other {
+  Other(const Other &); 
+  Other();
+};
+
+void test_any() {
+  Any any = Other(); // expected-error{{cannot pass object of non-POD type 'Other' through variadic constructor; call will abort at runtime}}
+}

Modified: cfe/trunk/test/SemaCXX/overload-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=102269&r1=102268&r2=102269&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call.cpp Sat Apr 24 15:54:38 2010
@@ -408,7 +408,7 @@
 }
 
 namespace PR6078 {
-  struct A { // expected-note{{candidate is the implicit copy constructor}}
+  struct A {
     A(short); // expected-note{{candidate constructor}}
     A(long); // expected-note{{candidate constructor}}
   };





More information about the cfe-commits mailing list