r248595 - Make incomplete type errors better with enable_if
George Burgess IV via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 10:53:16 PDT 2015
Author: gbiv
Date: Fri Sep 25 12:53:16 2015
New Revision: 248595
URL: http://llvm.org/viewvc/llvm-project?rev=248595&view=rev
Log:
Make incomplete type errors better with enable_if
This patch fixes the order in which we evaluate the different ways that
a function call could be disallowed. Now, if you call a non-overloaded
function with an incomplete type and failing enable_if, we'll prioritize
reporting the more obvious error (use of incomplete type) over reporting
the failing enable_if.
Thanks to Ettore Speziale for the patch!
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/SemaCXX/enable_if.cpp
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=248595&r1=248594&r2=248595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Sep 25 12:53:16 2015
@@ -11664,16 +11664,6 @@ Sema::BuildCallToMemberFunction(Scope *S
FoundDecl = MemExpr->getFoundDecl();
Qualifier = MemExpr->getQualifier();
UnbridgedCasts.restore();
-
- if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
- Diag(MemExprE->getLocStart(),
- diag::err_ovl_no_viable_member_function_in_call)
- << Method << Method->getSourceRange();
- Diag(Method->getLocation(),
- diag::note_ovl_candidate_disabled_by_enable_if_attr)
- << Attr->getCond()->getSourceRange() << Attr->getMessage();
- return ExprError();
- }
} else {
UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
Qualifier = UnresExpr->getQualifier();
@@ -11837,6 +11827,21 @@ Sema::BuildCallToMemberFunction(Scope *S
if (CheckFunctionCall(Method, TheCall, Proto))
return ExprError();
+ // In the case the method to call was not selected by the overloading
+ // resolution process, we still need to handle the enable_if attribute. Do
+ // that here, so it will not hide previous -- and more relevant -- errors
+ if (isa<MemberExpr>(NakedMemExpr)) {
+ if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
+ Diag(MemExprE->getLocStart(),
+ diag::err_ovl_no_viable_member_function_in_call)
+ << Method << Method->getSourceRange();
+ Diag(Method->getLocation(),
+ diag::note_ovl_candidate_disabled_by_enable_if_attr)
+ << Attr->getCond()->getSourceRange() << Attr->getMessage();
+ return ExprError();
+ }
+ }
+
if ((isa<CXXConstructorDecl>(CurContext) ||
isa<CXXDestructorDecl>(CurContext)) &&
TheCall->getMethodDecl()->isPure()) {
Modified: cfe/trunk/test/SemaCXX/enable_if.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enable_if.cpp?rev=248595&r1=248594&r2=248595&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enable_if.cpp (original)
+++ cfe/trunk/test/SemaCXX/enable_if.cpp Fri Sep 25 12:53:16 2015
@@ -2,6 +2,8 @@
typedef int (*fp)(int);
int surrogate(int);
+struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}} \
+ // expected-note {{forward declaration of 'Incomplete'}}
struct X {
X() = default; // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
@@ -13,13 +15,16 @@ struct X {
void g(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note{{candidate disabled: chosen when 'n' is zero}}
- void h(int n, int m = 0) __attribute((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}}
+ void h(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero"))); // expected-note{{candidate disabled: chosen when 'm' is zero}}
static void s(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero"))); // expected-note2{{candidate disabled: chosen when 'n' is zero}}
void conflict(int n) __attribute__((enable_if(n+n == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}}
void conflict(int n) __attribute__((enable_if(n*2 == 10, "chosen when 'n' is five"))); // expected-note{{candidate function}}
+ void hidden_by_argument_conversion(Incomplete n, int m = 0) __attribute__((enable_if(m == 10, "chosen when 'm' is ten")));
+ Incomplete hidden_by_incomplete_return_value(int n = 0) __attribute__((enable_if(n == 10, "chosen when 'n' is ten"))); // expected-note{{'hidden_by_incomplete_return_value' declared here}}
+
operator long() __attribute__((enable_if(true, "chosen on your platform")));
operator int() __attribute__((enable_if(false, "chosen on other platform")));
@@ -85,6 +90,9 @@ void test() {
x.conflict(5); // expected-error{{call to member function 'conflict' is ambiguous}}
+ x.hidden_by_argument_conversion(10); // expected-error{{argument type 'Incomplete' is incomplete}}
+ x.hidden_by_incomplete_return_value(10); // expected-error{{calling 'hidden_by_incomplete_return_value' with incomplete return type 'Incomplete'}}
+
deprec2(0);
overloaded(x);
More information about the cfe-commits
mailing list