]> granicus.if.org Git - clang/commitdiff
[Sema] Make type deduction work with some overloadable functions
authorGeorge Burgess IV <george.burgess.iv@gmail.com>
Sat, 19 Mar 2016 21:51:45 +0000 (21:51 +0000)
committerGeorge Burgess IV <george.burgess.iv@gmail.com>
Sat, 19 Mar 2016 21:51:45 +0000 (21:51 +0000)
Some functions can't have their address taken. If we encounter an
overload set where only one of the candidates can have its address
taken, we should automatically select that candidate's type in type
deduction.

Differential Revision: http://reviews.llvm.org/D15591

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

lib/Sema/SemaTemplateDeduction.cpp
test/SemaCXX/unaddressable-functions.cpp

index b101a16f5c828ecaecb46b34cc2a5b2853fc9e9e..aa824c37fe1adb7f1ec714b9eb62bcc10fc5e84f 100644 (file)
@@ -3016,6 +3016,11 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
         return GetTypeOfFunction(S, R, ExplicitSpec);
     }
 
+    DeclAccessPair DAP;
+    if (FunctionDecl *Viable =
+            S.resolveAddressOfOnlyViableOverloadCandidate(Arg, DAP))
+      return GetTypeOfFunction(S, R, Viable);
+
     return QualType();
   }
   
index a382ccfa6cd2b80b03067160d14940e9e60cd195..823f1be05f80c69e65066c3e57e7c83da1439e6a 100644 (file)
@@ -34,3 +34,69 @@ void foo(int) __attribute__((enable_if(false, "")));
 
 void *Ptr = reinterpret_cast<void*>(foo); // expected-error{{'foo' is unavailable: don't call this}} expected-note@-3{{explicitly marked unavailable here}}
 }
+
+namespace template_deduction {
+void foo() __attribute__((enable_if(false, "")));
+
+void bar() __attribute__((enable_if(true, "")));
+void bar() __attribute__((enable_if(false, "")));
+
+void baz(int a) __attribute__((enable_if(true, "")));
+void baz(int a) __attribute__((enable_if(a, "")));
+void baz(int a) __attribute__((enable_if(false, "")));
+
+void qux(int a) __attribute__((enable_if(1, "")));
+void qux(int a) __attribute__((enable_if(true, "")));
+void qux(int a) __attribute__((enable_if(a, "")));
+void qux(int a) __attribute__((enable_if(false, "")));
+
+template <typename Fn, typename... Args> void call(Fn F, Args... As) {
+  F(As...);
+}
+
+void test() {
+  call(foo); // expected-error{{cannot take address of function 'foo'}}
+  call(bar);
+  call(baz, 0);
+  call(qux, 0); // expected-error{{no matching function for call to 'call'}} expected-note@53{{candidate template ignored: couldn't infer template argument 'Fn'}}
+
+  auto Ptr1 = foo; // expected-error{{cannot take address of function 'foo'}}
+  auto Ptr2 = bar;
+  auto Ptr3 = baz;
+  auto Ptr4 = qux; // expected-error{{variable 'Ptr4' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
+}
+
+template <typename Fn, typename T, typename... Args>
+void callMem(Fn F, T t, Args... As) {
+  (t.*F)(As...);
+}
+
+class Foo {
+  void bar() __attribute__((enable_if(true, "")));
+  void bar() __attribute__((enable_if(false, "")));
+
+  static void staticBar() __attribute__((enable_if(true, "")));
+  static void staticBar() __attribute__((enable_if(false, "")));
+};
+
+void testAccess() {
+  callMem(&Foo::bar, Foo()); // expected-error{{'bar' is a private member of 'template_deduction::Foo'}} expected-note@-8{{implicitly declared private here}}
+  call(&Foo::staticBar); // expected-error{{'staticBar' is a private member of 'template_deduction::Foo'}} expected-note@-6{{implicitly declared private here}}
+}
+}
+
+namespace template_template_deduction {
+void foo() __attribute__((enable_if(false, "")));
+template <typename T>
+T foo() __attribute__((enable_if(true, "")));
+
+template <typename Fn, typename... Args> auto call(Fn F, Args... As) {
+  return F(As...);
+}
+
+auto Ok = call(&foo<int>);
+auto Fail = call(&foo); // expected-error{{no matching function for call to 'call'}} expected-note@-5{{candidate template ignored: couldn't infer template argument 'Fn'}}
+
+auto PtrOk = &foo<int>;
+auto PtrFail = &foo; // expected-error{{variable 'PtrFail' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
+}