[cfe-commits] r125714 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaExpr.cpp test/SemaCXX/member-expr.cpp
Matt Beaumont-Gay
matthewbg at google.com
Wed Feb 16 18:54:17 PST 2011
Author: matthewbg
Date: Wed Feb 16 20:54:17 2011
New Revision: 125714
URL: http://llvm.org/viewvc/llvm-project?rev=125714&view=rev
Log:
Fix PR9025 and add a diagnostic (and sometimes a fixit) for an overloaded
function name used as the base of a member expression. Early feedback from
Chandler Carruth, and code review from Nick Lewycky.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/SemaCXX/member-expr.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=125714&r1=125713&r2=125714&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 16 20:54:17 2011
@@ -2364,6 +2364,11 @@
def err_typecheck_member_reference_unknown : Error<
"cannot refer to member %0 in %1 with '%select{.|->}2'">;
def err_member_reference_needs_call : Error<
+ "base of member reference is an overloaded function; perhaps you meant "
+ "to call %select{it|the 0-argument overload}0?">;
+def note_member_ref_possible_intended_overload : Note<
+ "possibly valid overload here">;
+def err_member_reference_needs_call_zero_arg : Error<
"base of member reference has function type %0; perhaps you meant to call "
"this function with '()'?">;
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=125714&r1=125713&r2=125714&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 16 20:54:17 2011
@@ -3995,6 +3995,8 @@
// There's a possible road to recovery for function types.
const FunctionType *Fun = 0;
+ SourceLocation ParenInsertionLoc =
+ PP.getLocForEndOfToken(BaseExpr->getLocEnd());
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
if ((Fun = Ptr->getPointeeType()->getAs<FunctionType>())) {
@@ -4029,7 +4031,53 @@
if (Fun || BaseType == Context.OverloadTy) {
bool TryCall;
if (BaseType == Context.OverloadTy) {
- TryCall = true;
+ // Plunder the overload set for something that would make the member
+ // expression valid.
+ const OverloadExpr *Overloads = cast<OverloadExpr>(BaseExpr);
+ UnresolvedSet<4> CandidateOverloads;
+ bool HasZeroArgCandidateOverload = false;
+ for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
+ DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
+ const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*it);
+ QualType ResultTy = OverloadDecl->getResultType();
+ if ((!IsArrow && ResultTy->isRecordType()) ||
+ (IsArrow && ResultTy->isPointerType() &&
+ ResultTy->getPointeeType()->isRecordType())) {
+ CandidateOverloads.addDecl(*it);
+ if (OverloadDecl->getNumParams() == 0) {
+ HasZeroArgCandidateOverload = true;
+ }
+ }
+ }
+ if (HasZeroArgCandidateOverload && CandidateOverloads.size() == 1) {
+ // We have one reasonable overload, and there's only one way to call it,
+ // so emit a fixit and try to recover
+ Diag(ParenInsertionLoc, diag::err_member_reference_needs_call)
+ << 1
+ << BaseExpr->getSourceRange()
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ TryCall = true;
+ } else {
+ Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
+ << 0
+ << BaseExpr->getSourceRange();
+ int CandidateOverloadCount = CandidateOverloads.size();
+ int I;
+ for (I = 0; I < CandidateOverloadCount; ++I) {
+ // FIXME: Magic number for max shown overloads stolen from
+ // OverloadCandidateSet::NoteCandidates.
+ if (I >= 4 && Diags.getShowOverloads() == Diagnostic::Ovl_Best) {
+ break;
+ }
+ Diag(CandidateOverloads[I].getDecl()->getSourceRange().getBegin(),
+ diag::note_member_ref_possible_intended_overload);
+ }
+ if (I != CandidateOverloadCount) {
+ Diag(BaseExpr->getExprLoc(), diag::note_ovl_too_many_candidates)
+ << int(CandidateOverloadCount - I);
+ }
+ return ExprError();
+ }
} else {
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Fun)) {
TryCall = (FPT->getNumArgs() == 0);
@@ -4047,13 +4095,16 @@
if (TryCall) {
- SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
- Diag(BaseExpr->getExprLoc(), diag::err_member_reference_needs_call)
- << QualType(Fun, 0)
- << FixItHint::CreateInsertion(Loc, "()");
+ if (Fun) {
+ Diag(BaseExpr->getExprLoc(),
+ diag::err_member_reference_needs_call_zero_arg)
+ << QualType(Fun, 0)
+ << FixItHint::CreateInsertion(ParenInsertionLoc, "()");
+ }
ExprResult NewBase
- = ActOnCallExpr(0, BaseExpr, Loc, MultiExprArg(*this, 0, 0), Loc);
+ = ActOnCallExpr(0, BaseExpr, ParenInsertionLoc,
+ MultiExprArg(*this, 0, 0), ParenInsertionLoc);
if (NewBase.isInvalid())
return ExprError();
BaseExpr = NewBase.takeAs<Expr>();
Modified: cfe/trunk/test/SemaCXX/member-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-expr.cpp?rev=125714&r1=125713&r2=125714&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/member-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-expr.cpp Wed Feb 16 20:54:17 2011
@@ -115,3 +115,18 @@
y->N::X1<int>; // expected-error{{'rdar8231724::N::X1' is not a member of class 'rdar8231724::Y'}}
}
}
+
+namespace PR9025 {
+ struct S { int x; };
+ S fun();
+ int fun(int i);
+ int g() {
+ return fun.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call the 0-argument overload?}}
+ }
+
+ S fun2(); // expected-note{{possibly valid overload here}}
+ S fun2(int i); // expected-note{{possibly valid overload here}}
+ int g2() {
+ return fun2.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it?}}
+ }
+}
More information about the cfe-commits
mailing list