diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-06 06:30:47 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-06 06:30:47 +0000 |
commit | 3f0b5fd3a55baf1e3e768fe981bcc3ad5e209ec1 (patch) | |
tree | 0a77bb251f5c506471815a437eb9c5d4a0531252 /lib/Sema/SemaExpr.cpp | |
parent | 27591ff4fc64600fd67c5d81899e3efe5ef41a80 (diff) |
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
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f5bae072ef..031bbe77ac 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(); } |