]> granicus.if.org Git - clang/commitdiff
[c++17] Refine resolution of constructor / conversion function disambiguation.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 1 Nov 2017 01:37:11 +0000 (01:37 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 1 Nov 2017 01:37:11 +0000 (01:37 +0000)
Given a choice between a constructor call and a conversion function in C++17,
we prefer the constructor for direct-initialization and the conversion function
for copy-initialization, matching the behavior in C++14 and before. The
guaranteed copy elision rules were not intended to change the meaning of such
code (other than by removing unnecessary copy constructor calls).

This tweak will be raised with CWG.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317066 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
test/SemaCXX/cxx1z-copy-omission.cpp

index 8efb7c69d30893d11fa67a68b58341b2e611edf6..56135288db9fbb714823c393c02199a72ac6f9e2 100644 (file)
@@ -8977,6 +8977,18 @@ bool clang::isBetterOverloadCandidate(
     // C++14 [over.match.best]p1 section 2 bullet 3.
   }
 
+  // FIXME: Work around a defect in the C++17 guaranteed copy elision wording,
+  // as combined with the resolution to CWG issue 243.
+  //
+  // When the context is initialization by constructor ([over.match.ctor] or
+  // either phase of [over.match.list]), a constructor is preferred over
+  // a conversion function.
+  if (Kind == OverloadCandidateSet::CSK_InitByConstructor && NumArgs == 1 &&
+      Cand1.Function && Cand2.Function &&
+      isa<CXXConstructorDecl>(Cand1.Function) !=
+          isa<CXXConstructorDecl>(Cand2.Function))
+    return isa<CXXConstructorDecl>(Cand1.Function);
+
   //    -- F1 is a non-template function and F2 is a function template
   //       specialization, or, if not that,
   bool Cand1IsSpecialization = Cand1.Function &&
@@ -9035,20 +9047,6 @@ bool clang::isBetterOverloadCandidate(
         return true;
     }
   }
-  
-
-
-  // FIXME: Work around a defect in the C++17 guaranteed copy elision wording,
-  // as combined with the resolution to CWG issue 243.
-  //
-  // When the context is initialization by constructor ([over.match.ctor] or
-  // either phase of [over.match.list]), a constructor is preferred over
-  // a conversion function.
-  if (Kind == OverloadCandidateSet::CSK_InitByConstructor && NumArgs == 1 &&
-      Cand1.Function && Cand2.Function &&
-      isa<CXXConstructorDecl>(Cand1.Function) !=
-          isa<CXXConstructorDecl>(Cand2.Function))
-    return isa<CXXConstructorDecl>(Cand1.Function);
 
   // Check for enable_if value-based overload resolution.
   if (Cand1.Function && Cand2.Function) {
index cba6bc3be307b90bf419e20ab788470860c2b847..a7133d79b463f0e1cc00f891a2aed993378a850a 100644 (file)
@@ -160,3 +160,12 @@ struct AsDelegating final {
   // classes?
   AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}}
 };
+
+namespace CtorTemplateBeatsNonTemplateConversionFn {
+  struct Foo { template <typename Derived> Foo(const Derived &); };
+  template <typename Derived> struct Base { operator Foo() const = delete; }; // expected-note {{deleted}}
+  struct Derived : Base<Derived> {};
+
+  Foo f(Derived d) { return d; } // expected-error {{invokes a deleted function}}
+  Foo g(Derived d) { return Foo(d); } // ok, calls constructor
+}