"too few %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"at least argument %1 must be specified">;
+def err_typecheck_call_too_few_args_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_few_args_at_least_suggest : Error<
+ "too few %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at least %1, have %2; did you mean %3?">;
def err_typecheck_call_too_many_args : Error<
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"too many %select{|||execution configuration }0arguments to "
"%select{function|block|method|kernel function}0 call, "
"expected at most single argument %1, have %2 arguments">;
+def err_typecheck_call_too_many_args_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected %1, have %2; did you mean %3?">;
+def err_typecheck_call_too_many_args_at_most_suggest : Error<
+ "too many %select{|||execution configuration }0arguments to "
+ "%select{function|block|method|kernel function}0 call, "
+ "expected at most %1, have %2; did you mean %3?">;
def note_callee_decl : Note<
"%0 declared here">;
def note_defined_here : Note<"%0 defined here">;
return VariadicDoesNotApply;
}
+namespace {
+class FunctionCallCCC : public FunctionCallFilterCCC {
+public:
+ FunctionCallCCC(Sema &SemaRef, const IdentifierInfo *FuncName,
+ unsigned NumArgs, bool HasExplicitTemplateArgs)
+ : FunctionCallFilterCCC(SemaRef, NumArgs, HasExplicitTemplateArgs),
+ FunctionName(FuncName) {}
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ if (!candidate.getCorrectionSpecifier() ||
+ candidate.getCorrectionAsIdentifierInfo() != FunctionName) {
+ return false;
+ }
+
+ return FunctionCallFilterCCC::ValidateCandidate(candidate);
+ }
+
+private:
+ const IdentifierInfo *const FunctionName;
+};
+}
+
+static TypoCorrection TryTypoCorrectionForCall(Sema &S,
+ DeclarationNameInfo FuncName,
+ ArrayRef<Expr *> Args) {
+ FunctionCallCCC CCC(S, FuncName.getName().getAsIdentifierInfo(),
+ Args.size(), false);
+ if (TypoCorrection Corrected =
+ S.CorrectTypo(FuncName, Sema::LookupOrdinaryName,
+ S.getScopeForContext(S.CurContext), NULL, CCC)) {
+ if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
+ if (Corrected.isOverloaded()) {
+ OverloadCandidateSet OCS(FuncName.getLoc());
+ OverloadCandidateSet::iterator Best;
+ for (TypoCorrection::decl_iterator CD = Corrected.begin(),
+ CDEnd = Corrected.end();
+ CD != CDEnd; ++CD) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*CD))
+ S.AddOverloadCandidate(FD, DeclAccessPair::make(FD, AS_none), Args,
+ OCS);
+ }
+ switch (OCS.BestViableFunction(S, FuncName.getLoc(), Best)) {
+ case OR_Success:
+ ND = Best->Function;
+ Corrected.setCorrectionDecl(ND);
+ break;
+ default:
+ break;
+ }
+ }
+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
+ return Corrected;
+ }
+ }
+ }
+ return TypoCorrection();
+}
+
/// ConvertArgumentsForCall - Converts the arguments specified in
/// Args/NumArgs to the parameter types of the function FDecl with
/// function prototype Proto. Call is the call expression itself, and
// arguments for the remaining parameters), don't make the call.
if (Args.size() < NumArgsInProto) {
if (Args.size() < MinArgs) {
- if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ Fn->getLocStart()),
+ Args))) {
+ std::string CorrectedStr(TC.getAsString(getLangOpts()));
+ std::string CorrectedQuotedStr(TC.getQuoted(getLangOpts()));
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_few_args_suggest
+ : diag::err_typecheck_call_too_few_args_at_least_suggest;
+ Diag(RParenLoc, diag_id)
+ << FnKind << MinArgs << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(TC.getCorrectionRange(),
+ CorrectedStr);
+ Diag(TC.getCorrectionDeclAs<FunctionDecl>()->getLocStart(),
+ diag::note_previous_decl) << CorrectedQuotedStr;
+ } else if (MinArgs == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
Diag(RParenLoc, MinArgs == NumArgsInProto && !Proto->isVariadic()
? diag::err_typecheck_call_too_few_args_one
: diag::err_typecheck_call_too_few_args_at_least_one)
<< Fn->getSourceRange();
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;
// them.
if (Args.size() > NumArgsInProto) {
if (!Proto->isVariadic()) {
- if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
+ TypoCorrection TC;
+ if (FDecl && (TC = TryTypoCorrectionForCall(
+ *this, DeclarationNameInfo(FDecl->getDeclName(),
+ Fn->getLocStart()),
+ Args))) {
+ std::string CorrectedStr(TC.getAsString(getLangOpts()));
+ std::string CorrectedQuotedStr(TC.getQuoted(getLangOpts()));
+ unsigned diag_id =
+ MinArgs == NumArgsInProto && !Proto->isVariadic()
+ ? diag::err_typecheck_call_too_many_args_suggest
+ : diag::err_typecheck_call_too_many_args_at_most_suggest;
+ Diag(Args[NumArgsInProto]->getLocStart(), diag_id)
+ << FnKind << NumArgsInProto << static_cast<unsigned>(Args.size())
+ << Fn->getSourceRange() << CorrectedQuotedStr
+ << FixItHint::CreateReplacement(TC.getCorrectionRange(),
+ CorrectedStr);
+ Diag(TC.getCorrectionDeclAs<FunctionDecl>()->getLocStart(),
+ diag::note_previous_decl) << CorrectedQuotedStr;
+ } else if (NumArgsInProto == 1 && FDecl && FDecl->getParamDecl(0)->getDeclName())
Diag(Args[NumArgsInProto]->getLocStart(),
MinArgs == NumArgsInProto
? diag::err_typecheck_call_too_many_args_one
Args.back()->getLocEnd());
// Emit the location of the prototype.
- if (FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
+ if (!TC && FDecl && !FDecl->getBuiltinID() && !IsExecConfig)
Diag(FDecl->getLocStart(), diag::note_callee_decl)
<< FDecl;