зеркало из https://github.com/microsoft/clang.git
Rework the fix-it hint for code like
get_origin->x where get_origin is actually a function and the user has forgotten the parentheses. Instead of giving a lame note for the fix-it, give a full-fledge error, early, then build the call expression to try to recover. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86238 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
27591ff4fc
Коммит
3f0b5fd3a5
|
@ -1447,8 +1447,9 @@ def err_typecheck_member_reference_type : Error<
|
|||
"cannot refer to type member %0 with '%select{.|->}1'">;
|
||||
def err_typecheck_member_reference_unknown : Error<
|
||||
"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_member_reference_needs_call : 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'">,
|
||||
InGroup<CharSubscript>, DefaultIgnore;
|
||||
|
||||
|
|
|
@ -1882,6 +1882,38 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
DefaultFunctionArrayConversion(BaseExpr);
|
||||
|
||||
QualType BaseType = BaseExpr->getType();
|
||||
|
||||
// If the user is trying to apply -> or . to a function pointer
|
||||
// type, it's probably because the forgot parentheses to call that
|
||||
// function. Suggest the addition of those parentheses, build the
|
||||
// call, and continue on.
|
||||
if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
|
||||
if (const FunctionProtoType *Fun
|
||||
= Ptr->getPointeeType()->getAs<FunctionProtoType>()) {
|
||||
QualType ResultTy = Fun->getResultType();
|
||||
if (Fun->getNumArgs() == 0 &&
|
||||
((OpKind == tok::period && ResultTy->isRecordType()) ||
|
||||
(OpKind == tok::arrow && ResultTy->isPointerType() &&
|
||||
ResultTy->getAs<PointerType>()->getPointeeType()
|
||||
->isRecordType()))) {
|
||||
SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
|
||||
Diag(Loc, diag::err_member_reference_needs_call)
|
||||
<< QualType(Fun, 0)
|
||||
<< CodeModificationHint::CreateInsertion(Loc, "()");
|
||||
|
||||
OwningExprResult NewBase
|
||||
= ActOnCallExpr(S, ExprArg(*this, BaseExpr), Loc,
|
||||
MultiExprArg(*this, 0, 0), 0, Loc);
|
||||
if (NewBase.isInvalid())
|
||||
return move(NewBase);
|
||||
|
||||
BaseExpr = NewBase.takeAs<Expr>();
|
||||
DefaultFunctionArrayConversion(BaseExpr);
|
||||
BaseType = BaseExpr->getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is an Objective-C pseudo-builtin and a definition is provided then
|
||||
// use that.
|
||||
if (BaseType->isObjCIdType()) {
|
||||
|
@ -2437,18 +2469,6 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
|
|||
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
|
||||
<< 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->getAs<PointerType>()->isFunctionType())) {
|
||||
SourceLocation Loc = PP.getLocForEndOfToken(BaseExpr->getLocEnd());
|
||||
Diag(Loc, diag::note_member_reference_needs_call)
|
||||
<< CodeModificationHint::CreateInsertion(Loc, "()");
|
||||
}
|
||||
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,3 +8,13 @@
|
|||
struct s; // expected-note{{previous use is here}}
|
||||
|
||||
union s *s1; // expected-error{{use of 's' with tag type that does not match previous declaration}}
|
||||
|
||||
struct Point {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct Point *get_origin();
|
||||
|
||||
void test_point() {
|
||||
(void)get_origin->x;
|
||||
}
|
||||
|
|
|
@ -28,8 +28,7 @@ struct B {
|
|||
A *f0();
|
||||
};
|
||||
int f0(B *b) {
|
||||
return b->f0->f0; // expected-error{{member reference base type 'struct A *()' is not a structure or union}} \
|
||||
// expected-note{{perhaps you meant to call this function}}
|
||||
return b->f0->f0; // expected-error{{perhaps you meant to call this function}}
|
||||
}
|
||||
|
||||
int i;
|
||||
|
|
Загрузка…
Ссылка в новой задаче