diff options
| author | George Burgess IV <george.burgess.iv@gmail.com> | 2017-05-09 04:06:24 +0000 |
|---|---|---|
| committer | George Burgess IV <george.burgess.iv@gmail.com> | 2017-05-09 04:06:24 +0000 |
| commit | 1dbfa856b1172d045baecaeab6711b0d01377970 (patch) | |
| tree | d8a1ed1a754cc6a2fd02a45b4f70625882ec122e | |
| parent | b35ef2a599aa71b4aac027429e0c19d16dc274b7 (diff) | |
| download | bcm5719-llvm-1dbfa856b1172d045baecaeab6711b0d01377970.tar.gz bcm5719-llvm-1dbfa856b1172d045baecaeab6711b0d01377970.zip | |
[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.
llvm-svn: 302506
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 6 | ||||
| -rw-r--r-- | clang/test/Sema/overloadable.c | 15 | ||||
| -rw-r--r-- | clang/test/SemaCXX/enable_if.cpp | 14 |
5 files changed, 36 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e5961079f7c..b0cb34cf565 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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, diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 7e91709e67d..7d534263f46 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1871,7 +1871,8 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType, // No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization // preserves Result. Result = E; - if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate(Result)) + if (!Self.resolveAndFixAddressOfOnlyViableOverloadCandidate( + Result, /*DoFunctionPointerConversion=*/true)) return false; return Result.isUsable(); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 782c377e320..51794160278 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11210,12 +11210,12 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E, /// \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::resolveAndFixAddressOfOnlyViableOverloadCandidate( 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; diff --git a/clang/test/Sema/overloadable.c b/clang/test/Sema/overloadable.c index f5e17d21191..49d8085651d 100644 --- a/clang/test/Sema/overloadable.c +++ b/clang/test/Sema/overloadable.c @@ -151,3 +151,18 @@ void dropping_qualifiers_is_incompatible() { foo(ccharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}} foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@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); +} diff --git a/clang/test/SemaCXX/enable_if.cpp b/clang/test/SemaCXX/enable_if.cpp index 9a06d386611..93014f50d50 100644 --- a/clang/test/SemaCXX/enable_if.cpp +++ b/clang/test/SemaCXX/enable_if.cpp @@ -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, ""); +} |

