]> granicus.if.org Git - clang/commitdiff
Fix PR31934: forming refs to functions with enable_if attrs.
authorGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 13 Apr 2017 23:47:08 +0000 (23:47 +0000)
committerGeorge Burgess IV <george.burgess.iv@gmail.com>
Thu, 13 Apr 2017 23:47:08 +0000 (23:47 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300283 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/SemaCXX/enable_if.cpp

index b6f799b62119349a9bd87270a9e680247f5dcb54..0d96304f4a247a09a3753531bb2c116f7c5efb32 100644 (file)
@@ -6684,6 +6684,19 @@ InitializationSequence::Perform(Sema &S,
       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.
index 01b6f8fd3ab23666174eaf9232b8dc38c87aa066..9a06d386611024b011d98dcaf440f9fa2730bdea 100644 (file)
@@ -472,3 +472,30 @@ namespace instantiate_constexpr_in_enable_if {
   };
   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'}}
+  }
+}
+}