forked from OSchip/llvm-project
[Sema] Make type deduction work with some overloadable functions
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 llvm-svn: 263888
This commit is contained in:
parent
3cde9bf9d5
commit
cc2f355f71
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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>'}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue