george.burgess.iv created this revision.
george.burgess.iv added a reviewer: rsmith.
george.burgess.iv added a subscriber: cfe-commits.

Given:

```
void foo(int i) __attribute__((enable_if(i < 0, "")));
void foo(double d);

auto fooToCall = foo;
```

...We currently can't determine the type of `fooToCall`, so this fails to 
compile. This patch lets us infer `fooToCall` to be `void (*)(double);

http://reviews.llvm.org/D15591

Files:
  lib/Sema/SemaTemplateDeduction.cpp
  test/CodeGenCXX/pass-object-size.cpp
  test/SemaCXX/pass-object-size.cpp

Index: test/SemaCXX/pass-object-size.cpp
===================================================================
--- test/SemaCXX/pass-object-size.cpp
+++ test/SemaCXX/pass-object-size.cpp
@@ -120,3 +120,11 @@
   (void)+[](void *const p __attribute__((pass_object_size(0)))) {}; 
//expected-error-re{{invalid argument type '(lambda at {{.*}})' to unary 
expression}}
 }
 }
+
+namespace deduction {
+void MultiOvl(void *__attribute__((pass_object_size(0))));
+void MultiOvl(void *);
+void MultiOvl(int *);
+
+auto Ptr = MultiOvl; // expected-error{{variable 'Ptr' with type 'auto' has 
incompatible initializer of type '<overloaded function type>'}}
+}
Index: test/CodeGenCXX/pass-object-size.cpp
===================================================================
--- test/CodeGenCXX/pass-object-size.cpp
+++ test/CodeGenCXX/pass-object-size.cpp
@@ -25,3 +25,17 @@
 // CHECK-DAG: define internal i64 
@"_ZZN7lambdas7LambdasEPcENK3$_1clEPvU17pass_object_size0"
 // CHECK-NOT: call i64 @llvm.objectsize
 }
+
+// This is here instead of in Sema/ because we need to check to make sure the
+// proper function is called. If it's not, we'll end up with assertion errors.
+namespace addrof {
+void OvlFoo(void *const __attribute__((pass_object_size(0)))) {}
+void OvlFoo(int *const) {}
+
+void WithTypeDeduction() {
+  // CHECK: @_ZN6addrof6OvlFooEPi
+  auto P = OvlFoo;
+  // CHECK: @_ZN6addrof6OvlFooEPi
+  auto P2 = &OvlFoo;
+}
+}
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -3031,6 +3031,28 @@
         return GetTypeOfFunction(S, R, ExplicitSpec);
     }
 
+    // If only one of the candidates are addressable, we can use that type.
+    FunctionDecl *OnlyAddressable = nullptr;
+    for (Decl *D : Ovl->decls()) {
+      auto *FD = dyn_cast<FunctionDecl>(D);
+      // Not a function decl, so there's a chance of template magic going on.
+      // Give up.
+      if (!FD) {
+        OnlyAddressable = nullptr;
+        break;
+      }
+      if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/false))
+        continue;
+      // Multiple addressable. Give up.
+      if (OnlyAddressable) {
+        OnlyAddressable = nullptr;
+        break;
+      }
+      OnlyAddressable = FD;
+    }
+
+    if (OnlyAddressable)
+      return GetTypeOfFunction(S, R, OnlyAddressable);
     return QualType();
   }
   


Index: test/SemaCXX/pass-object-size.cpp
===================================================================
--- test/SemaCXX/pass-object-size.cpp
+++ test/SemaCXX/pass-object-size.cpp
@@ -120,3 +120,11 @@
   (void)+[](void *const p __attribute__((pass_object_size(0)))) {}; //expected-error-re{{invalid argument type '(lambda at {{.*}})' to unary expression}}
 }
 }
+
+namespace deduction {
+void MultiOvl(void *__attribute__((pass_object_size(0))));
+void MultiOvl(void *);
+void MultiOvl(int *);
+
+auto Ptr = MultiOvl; // expected-error{{variable 'Ptr' with type 'auto' has incompatible initializer of type '<overloaded function type>'}}
+}
Index: test/CodeGenCXX/pass-object-size.cpp
===================================================================
--- test/CodeGenCXX/pass-object-size.cpp
+++ test/CodeGenCXX/pass-object-size.cpp
@@ -25,3 +25,17 @@
 // CHECK-DAG: define internal i64 @"_ZZN7lambdas7LambdasEPcENK3$_1clEPvU17pass_object_size0"
 // CHECK-NOT: call i64 @llvm.objectsize
 }
+
+// This is here instead of in Sema/ because we need to check to make sure the
+// proper function is called. If it's not, we'll end up with assertion errors.
+namespace addrof {
+void OvlFoo(void *const __attribute__((pass_object_size(0)))) {}
+void OvlFoo(int *const) {}
+
+void WithTypeDeduction() {
+  // CHECK: @_ZN6addrof6OvlFooEPi
+  auto P = OvlFoo;
+  // CHECK: @_ZN6addrof6OvlFooEPi
+  auto P2 = &OvlFoo;
+}
+}
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -3031,6 +3031,28 @@
         return GetTypeOfFunction(S, R, ExplicitSpec);
     }
 
+    // If only one of the candidates are addressable, we can use that type.
+    FunctionDecl *OnlyAddressable = nullptr;
+    for (Decl *D : Ovl->decls()) {
+      auto *FD = dyn_cast<FunctionDecl>(D);
+      // Not a function decl, so there's a chance of template magic going on.
+      // Give up.
+      if (!FD) {
+        OnlyAddressable = nullptr;
+        break;
+      }
+      if (!S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/false))
+        continue;
+      // Multiple addressable. Give up.
+      if (OnlyAddressable) {
+        OnlyAddressable = nullptr;
+        break;
+      }
+      OnlyAddressable = FD;
+    }
+
+    if (OnlyAddressable)
+      return GetTypeOfFunction(S, R, OnlyAddressable);
     return QualType();
   }
   
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to