forked from OSchip/llvm-project
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!
llvm-svn: 211551
This commit is contained in:
parent
4377656e12
commit
9ea8efaf92
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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'?}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue