r302506 - [Sema] Make typeof(OverloadedFunctionName) not a pointer.

George Burgess IV via cfe-commits cfe-commits at lists.llvm.org
Mon May 8 21:06:24 PDT 2017


Author: gbiv
Date: Mon May  8 23:06:24 2017
New Revision: 302506

URL: http://llvm.org/viewvc/llvm-project?rev=302506&view=rev
Log:
[Sema] Make typeof(OverloadedFunctionName) not a pointer.

We were sometimes doing a function->pointer conversion in
Sema::CheckPlaceholderExpr, which isn't the job of CheckPlaceholderExpr.

So, when we saw typeof(OverloadedFunctionName), where
OverloadedFunctionName referenced a name with only one function that
could have its address taken, we'd give back a function pointer type
instead of a function type. This is incorrect.

I kept the logic for doing the function pointer conversion in
resolveAndFixAddressOfOnlyViableOverloadCandidate because it was more
consistent with existing ResolveAndFix* methods.

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/Sema/overloadable.c
    cfe/trunk/test/SemaCXX/enable_if.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=302506&r1=302505&r2=302506&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon May  8 23:06:24 2017
@@ -2726,7 +2726,8 @@ public:
   resolveAddressOfOnlyViableOverloadCandidate(Expr *E,
                                               DeclAccessPair &FoundResult);
 
-  bool resolveAndFixAddressOfOnlyViableOverloadCandidate(ExprResult &SrcExpr);
+  bool resolveAndFixAddressOfOnlyViableOverloadCandidate(
+      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
 
   FunctionDecl *
   ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=302506&r1=302505&r2=302506&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Mon May  8 23:06:24 2017
@@ -1871,7 +1871,8 @@ static bool fixOverloadedReinterpretCast
   // No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization
   // preserves Result.
   Result = E;
-  if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate(Result))
+  if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate(
+          Result, /*DoFunctionPointerConversion=*/true))
     return false;
   return Result.isUsable();
 }

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=302506&r1=302505&r2=302506&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon May  8 23:06:24 2017
@@ -11210,12 +11210,12 @@ Sema::resolveAddressOfOnlyViableOverload
 /// \brief Given an overloaded function, tries to turn it into a non-overloaded
 /// function reference using resolveAddressOfOnlyViableOverloadCandidate. This
 /// will perform access checks, diagnose the use of the resultant decl, and, if
-/// necessary, perform a function-to-pointer decay.
+/// requested, potentially perform a function-to-pointer decay.
 ///
 /// Returns false if resolveAddressOfOnlyViableOverloadCandidate fails.
 /// Otherwise, returns true. This may emit diagnostics and return true.
 bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate(
-    ExprResult &SrcExpr) {
+    ExprResult &SrcExpr, bool DoFunctionPointerConverion) {
   Expr *E = SrcExpr.get();
   assert(E->getType() == Context.OverloadTy && "SrcExpr must be an overload");
 
@@ -11230,7 +11230,7 @@ bool Sema::resolveAndFixAddressOfOnlyVia
   DiagnoseUseOfDecl(Found, E->getExprLoc());
   CheckAddressOfMemberAccess(E, DAP);
   Expr *Fixed = FixOverloadedFunctionReference(E, DAP, Found);
-  if (Fixed->getType()->isFunctionType())
+  if (DoFunctionPointerConverion && Fixed->getType()->isFunctionType())
     SrcExpr = DefaultFunctionArrayConversion(Fixed, /*Diagnose=*/false);
   else
     SrcExpr = Fixed;

Modified: cfe/trunk/test/Sema/overloadable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=302506&r1=302505&r2=302506&view=diff
==============================================================================
--- cfe/trunk/test/Sema/overloadable.c (original)
+++ cfe/trunk/test/Sema/overloadable.c Mon May  8 23:06:24 2017
@@ -151,3 +151,18 @@ void dropping_qualifiers_is_incompatible
   foo(ccharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note at 148{{candidate function}} expected-note at 149{{candidate function}}
   foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note at 148{{candidate function}} expected-note at 149{{candidate function}}
 }
+
+// Bug: we used to treat `__typeof__(foo)` as though it was `__typeof__(&foo)`
+// if `foo` was overloaded with only one function that could have its address
+// taken.
+void typeof_function_is_not_a_pointer() {
+  void not_a_pointer(void *) __attribute__((overloadable));
+  void not_a_pointer(char *__attribute__((pass_object_size(1))))
+    __attribute__((overloadable));
+
+  __typeof__(not_a_pointer) *fn;
+
+  void take_fn(void (*)(void *));
+  // if take_fn is passed a void (**)(void *), we'll get a warning.
+  take_fn(fn);
+}

Modified: cfe/trunk/test/SemaCXX/enable_if.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enable_if.cpp?rev=302506&r1=302505&r2=302506&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enable_if.cpp (original)
+++ cfe/trunk/test/SemaCXX/enable_if.cpp Mon May  8 23:06:24 2017
@@ -499,3 +499,17 @@ void run() {
   }
 }
 }
+
+namespace TypeOfFn {
+  template <typename T, typename U>
+  struct is_same;
+
+  template <typename T> struct is_same<T, T> {
+    enum { value = 1 };
+  };
+
+  void foo(int a) __attribute__((enable_if(a, "")));
+  void foo(float a) __attribute__((enable_if(1, "")));
+
+  static_assert(is_same<__typeof__(foo)*, decltype(&foo)>::value, "");
+}




More information about the cfe-commits mailing list