From 9afaf793b36dc7d61797283799d77c1c5ca19c27 Mon Sep 17 00:00:00 2001 From: Kaelyn Uhrain Date: Wed, 25 Jan 2012 21:11:35 +0000 Subject: [PATCH] Allow typo correction to be disabled in BuildOverloadedCallExpr variant. This suppresses typo correction for auto-generated call expressions such as to 'begin' or 'end' within a C++0x for-range statement. llvm-svn: 148979 --- clang/include/clang/Sema/Sema.h | 3 ++- clang/lib/Sema/SemaOverload.cpp | 32 ++++++++++++++++++++++---- clang/lib/Sema/SemaStmt.cpp | 2 +- clang/test/SemaCXX/typo-correction.cpp | 8 +++++++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 77ae346e6791..12096f5fcb45 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1583,7 +1583,8 @@ public: SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, - Expr *ExecConfig); + Expr *ExecConfig, + bool AllowTypoCorrection=true); ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 3333b4eea922..36b6946a031d 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -9215,6 +9215,21 @@ class RecoveryCallCCC : public CorrectionCandidateCallback { unsigned NumArgs; bool HasExplicitTemplateArgs; }; + +// Callback that effectively disabled typo correction +class NoTypoCorrectionCCC : public CorrectionCandidateCallback { + public: + NoTypoCorrectionCCC() { + WantTypeSpecifiers = false; + WantExpressionKeywords = false; + WantCXXNamedCasts = false; + WantRemainingKeywords = false; + } + + virtual bool ValidateCandidate(const TypoCorrection &candidate) { + return false; + } +}; } /// Attempts to recover from a call where no functions were found. @@ -9226,7 +9241,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, - bool EmptyLookup) { + bool EmptyLookup, bool AllowTypoCorrection) { CXXScopeSpec SS; SS.Adopt(ULE->getQualifierLoc()); @@ -9241,10 +9256,14 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), Sema::LookupOrdinaryName); RecoveryCallCCC Validator(SemaRef, NumArgs, ExplicitTemplateArgs != 0); + NoTypoCorrectionCCC RejectAll; + CorrectionCandidateCallback *CCC = AllowTypoCorrection ? + (CorrectionCandidateCallback*)&Validator : + (CorrectionCandidateCallback*)&RejectAll; if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, ExplicitTemplateArgs, Args, NumArgs) && (!EmptyLookup || - SemaRef.DiagnoseEmptyLookup(S, SS, R, Validator, + SemaRef.DiagnoseEmptyLookup(S, SS, R, *CCC, ExplicitTemplateArgs, Args, NumArgs))) return ExprError(); @@ -9283,7 +9302,8 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, - Expr *ExecConfig) { + Expr *ExecConfig, + bool AllowTypoCorrection) { #ifndef NDEBUG if (ULE->requiresADL()) { // To do ADL, we must have found an unqualified name. @@ -9331,7 +9351,8 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, return Owned(CE); } return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, /*EmptyLookup=*/true); + RParenLoc, /*EmptyLookup=*/true, + AllowTypoCorrection); } UnbridgedCasts.restore(); @@ -9353,7 +9374,8 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // have meant to call. ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, RParenLoc, - /*EmptyLookup=*/false); + /*EmptyLookup=*/false, + AllowTypoCorrection); if (!Recovery.isInvalid()) return Recovery; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 86bb74040ae5..0eb8d2863cf9 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1286,7 +1286,7 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, FoundNames.begin(), FoundNames.end(), /*LookInStdNamespace=*/true); CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, - 0); + 0, /*AllowTypoCorrection=*/false); if (CallExpr.isInvalid()) { SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) << Range->getType(); diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index 6a3a2976a514..556e654a2d2c 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -149,3 +149,11 @@ void Test3() { Provoke("foo", true); // expected-error{{use of undeclared identifier 'Provoke'; did you mean 'provoke'?}} Provoke("foo", 7, 22); // expected-error{{use of undeclared identifier 'Provoke'}} } + +// PR 11737 - Don't try to typo-correct the implicit 'begin' and 'end' in a +// C++11 for-range statement. +struct R {}; +bool begun(R); +void RangeTest() { + for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}} +}