summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2014-06-23 22:57:51 +0000
committerNick Lewycky <nicholas@mxc.ca>2014-06-23 22:57:51 +0000
commitee28b09421d031c938fe1526bcbbabdf0bf96c59 (patch)
tree2da435cd16920bf2f8273fee29cbd414cd98b7a8
parent42988461bb266eb0359f136417498b44a9f786b6 (diff)
downloadclang-ee28b09421d031c938fe1526bcbbabdf0bf96c59.tar.gz
clang-ee28b09421d031c938fe1526bcbbabdf0bf96c59.tar.bz2
clang-ee28b09421d031c938fe1526bcbbabdf0bf96c59.tar.xz
Propagate isAddressOfMember into typo correction so that we don't correct &qualified-id into &unqualified-id. Also make sure to set the naming class when we find the qualified-id in a different class than the nested name specifier specified so far. Fixes PR19681!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@211551 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/TypoCorrection.h5
-rw-r--r--lib/Parse/ParseExpr.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp14
-rw-r--r--lib/Sema/SemaLookup.cpp25
-rw-r--r--test/SemaCXX/typo-correction-pt2.cpp13
5 files changed, 52 insertions, 9 deletions
diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h
index e5f8f4dfa2..6cab59c93e 100644
--- a/include/clang/Sema/TypoCorrection.h
+++ b/include/clang/Sema/TypoCorrection.h
@@ -250,8 +250,8 @@ public:
CorrectionCandidateCallback()
: WantTypeSpecifiers(true), WantExpressionKeywords(true),
WantCXXNamedCasts(true), WantRemainingKeywords(true),
- WantObjCSuper(false),
- IsObjCIvarLookup(false) {}
+ WantObjCSuper(false), IsObjCIvarLookup(false),
+ IsAddressOfOperand(false) {}
virtual ~CorrectionCandidateCallback() {}
@@ -287,6 +287,7 @@ public:
// Temporary hack for the one case where a CorrectTypoContext enum is used
// when looking up results.
bool IsObjCIvarLookup;
+ bool IsAddressOfOperand;
};
/// @brief Simple template class for restricting typo correction candidates
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b2381576a2..3fea464c68 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -435,7 +435,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback {
if (isa<TypeDecl>(ND))
return WantTypeSpecifiers;
- return AllowNonTypes;
+ return AllowNonTypes &&
+ CorrectionCandidateCallback::ValidateCandidate(candidate);
}
private:
@@ -813,6 +814,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation TemplateKWLoc;
CastExpressionIdValidator Validator(isTypeCast != NotTypeCast,
isTypeCast != IsTypeCast);
+ Validator.IsAddressOfOperand = isAddressOfOperand;
Name.setIdentifier(&II, ILoc);
Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
Name, Tok.is(tok::l_paren),
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index bda80cd205..c7ea55219a 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1883,6 +1883,17 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
}
}
R.addDecl(ND);
+ if (getLangOpts().CPlusPlus && ND->isCXXClassMember()) {
+ CXXRecordDecl *Record = nullptr;
+ if (Corrected.getCorrectionSpecifier()) {
+ const Type *Ty = Corrected.getCorrectionSpecifier()->getAsType();
+ Record = Ty->getAsCXXRecordDecl();
+ }
+ if (!Record)
+ Record = cast<CXXRecordDecl>(
+ ND->getDeclContext()->getRedeclContext());
+ R.setNamingClass(Record);
+ }
AcceptableWithRecovery =
isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND);
@@ -2100,6 +2111,9 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
CorrectionCandidateCallback DefaultValidator;
+ DefaultValidator.IsAddressOfOperand = IsAddressOfOperand;
+ assert((!CCC || CCC->IsAddressOfOperand == IsAddressOfOperand) &&
+ "Typo correction callback misconfigured");
if (DiagnoseEmptyLookup(S, SS, R, CCC ? *CCC : DefaultValidator))
return ExprError();
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 9abff2c45d..c7be6c9315 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -4454,14 +4454,27 @@ bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candid
return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts ||
WantRemainingKeywords || WantObjCSuper;
- for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(),
- CDeclEnd = candidate.end();
- CDecl != CDeclEnd; ++CDecl) {
- if (!isa<TypeDecl>(*CDecl))
- return true;
+ bool HasNonType = false;
+ bool HasStaticMethod = false;
+ bool HasNonStaticMethod = false;
+ for (Decl *D : candidate) {
+ if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ D = FTD->getTemplatedDecl();
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ if (Method->isStatic())
+ HasStaticMethod = true;
+ else
+ HasNonStaticMethod = true;
+ }
+ if (!isa<TypeDecl>(D))
+ HasNonType = true;
}
- return WantTypeSpecifiers;
+ if (IsAddressOfOperand && HasNonStaticMethod && !HasStaticMethod &&
+ !candidate.getCorrectionSpecifier())
+ return false;
+
+ return WantTypeSpecifiers || HasNonType;
}
FunctionCallFilterCCC::FunctionCallFilterCCC(Sema &SemaRef, unsigned NumArgs,
diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp
index cdef7e7500..88a7073f99 100644
--- a/test/SemaCXX/typo-correction-pt2.cpp
+++ b/test/SemaCXX/typo-correction-pt2.cpp
@@ -287,3 +287,16 @@ void test() {
if (p) // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
return;
}
+
+namespace PR19681 {
+ struct TypoA {};
+ struct TypoB {
+ void test();
+ private:
+ template<typename T> void private_memfn(T); // expected-note{{declared here}}
+ };
+ void TypoB::test() {
+ // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
+ (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn); // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
+ }
+}