if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType))
return ExprError();
+ // We don't check for e.g. function pointers here, since address
+ // availability checks should only occur when the function first decays
+ // into a pointer or reference.
+ if (CurInit.get()->getType()->isFunctionProtoType()) {
+ if (auto *DRE = dyn_cast<DeclRefExpr>(CurInit.get()->IgnoreParens())) {
+ if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+ if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+ DRE->getLocStart()))
+ return ExprError();
+ }
+ }
+ }
+
// Even though we didn't materialize a temporary, the binding may still
// extend the lifetime of a temporary. This happens if we bind a reference
// to the result of a cast to reference type.
};
void g() { X<int>().f(); }
}
+
+namespace PR31934 {
+int foo(int a) __attribute__((enable_if(a, "")));
+int runFn(int (&)(int));
+
+void run() {
+ {
+ int (&bar)(int) = foo; // expected-error{{cannot take address of function 'foo'}}
+ int baz = runFn(foo); // expected-error{{cannot take address of function 'foo'}}
+ }
+
+ {
+ int (&bar)(int) = (foo); // expected-error{{cannot take address of function 'foo'}}
+ int baz = runFn((foo)); // expected-error{{cannot take address of function 'foo'}}
+ }
+
+ {
+ int (&bar)(int) = static_cast<int (&)(int)>(foo); // expected-error{{cannot take address of function 'foo'}}
+ int baz = runFn(static_cast<int (&)(int)>(foo)); // expected-error{{cannot take address of function 'foo'}}
+ }
+
+ {
+ int (&bar)(int) = static_cast<int (&)(int)>((foo)); // expected-error{{cannot take address of function 'foo'}}
+ int baz = runFn(static_cast<int (&)(int)>((foo))); // expected-error{{cannot take address of function 'foo'}}
+ }
+}
+}