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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits