forked from OSchip/llvm-project
If the user is trying to apply the -> or . member reference operator
to a function or function pointer, it's probably because the user forgot to put in parentheses () to call the function. llvm-svn: 67826
This commit is contained in:
parent
17e28b7a54
commit
0b08ba44a1
|
@ -872,6 +872,9 @@ def err_typecheck_member_reference_type : Error<
|
||||||
"cannot refer to type member %0 with '%select{.|->}1'">;
|
"cannot refer to type member %0 with '%select{.|->}1'">;
|
||||||
def err_typecheck_member_reference_unknown : Error<
|
def err_typecheck_member_reference_unknown : Error<
|
||||||
"cannot refer to member %0 with '%select{.|->}1'">;
|
"cannot refer to member %0 with '%select{.|->}1'">;
|
||||||
|
def note_member_reference_needs_call : Note<
|
||||||
|
"perhaps you meant to call this function with '()'?">;
|
||||||
|
|
||||||
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
|
||||||
def err_typecheck_no_member : Error<"no member named %0">;
|
def err_typecheck_no_member : Error<"no member named %0">;
|
||||||
def err_member_redeclared : Error<"class member cannot be redeclared">;
|
def err_member_redeclared : Error<"class member cannot be redeclared">;
|
||||||
|
|
|
@ -2101,9 +2101,22 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
||||||
MemberLoc));
|
MemberLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExprError(Diag(MemberLoc,
|
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
|
||||||
diag::err_typecheck_member_reference_struct_union)
|
<< BaseType << BaseExpr->getSourceRange();
|
||||||
<< BaseType << BaseExpr->getSourceRange());
|
|
||||||
|
// If the user is trying to apply -> or . to a function or function
|
||||||
|
// pointer, it's probably because they forgot parentheses to call
|
||||||
|
// the function. Suggest the addition of those parentheses.
|
||||||
|
if (BaseType == Context.OverloadTy ||
|
||||||
|
BaseType->isFunctionType() ||
|
||||||
|
(BaseType->isPointerType() &&
|
||||||
|
BaseType->getAsPointerType()->isFunctionType())) {
|
||||||
|
SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
|
||||||
|
Diag(Loc, diag::note_member_reference_needs_call)
|
||||||
|
<< CodeModificationHint::CreateInsertion(Loc, "()");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExprError();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ConvertArgumentsForCall - Converts the arguments specified in
|
/// ConvertArgumentsForCall - Converts the arguments specified in
|
||||||
|
|
|
@ -20,3 +20,14 @@ void test(X* xp, X x) {
|
||||||
float f1 = x.g();
|
float f1 = x.g();
|
||||||
float f2 = xp->g();
|
float f2 = xp->g();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
int f0;
|
||||||
|
};
|
||||||
|
struct B {
|
||||||
|
A *f0();
|
||||||
|
};
|
||||||
|
int f0(B *b) {
|
||||||
|
return b->f0->f0; // expected-error{{member reference base type 'struct A *(void)' is not a structure or union}} \
|
||||||
|
// expected-note{{perhaps you meant to call this function}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue