def err_unknown_typename_suggest : Error<
"unknown type name %0; did you mean %1?">;
def err_unknown_nested_typename_suggest : Error<
- "no type named %0 in %1; did you mean %2?">;
-def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
+ "no type named %0 in %1; did you mean %select{|simply }2%3?">;
+def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %select{|simply }2%3?">;
def err_undeclared_use_suggest : Error<
"use of undeclared %0; did you mean %1?">;
def err_undeclared_var_use_suggest : Error<
"use of undeclared identifier %0; did you mean %1?">;
def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
def err_no_member_template_suggest : Error<
- "no template named %0 in %1; did you mean %2?">;
+ "no template named %0 in %1; did you mean %select{|simply }2%3?">;
def err_mem_init_not_member_or_class_suggest : Error<
"initializer %0 does not name a non-static data member or base "
"class; did you mean the %select{base class|member}1 %2?">;
def err_using_directive_suggest : Error<
"no namespace named %0; did you mean %1?">;
def err_using_directive_member_suggest : Error<
- "no namespace named %0 in %1; did you mean %2?">;
+ "no namespace named %0 in %1; did you mean %select{|simply }2%3?">;
def note_namespace_defined_here : Note<"namespace %0 defined here">;
def err_sizeof_pack_no_pack_name_suggest : Error<
"%0 does not refer to the name of a parameter pack; did you mean %1?">;
static const unsigned CallbackDistanceWeight = 150U;
TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,
- NestedNameSpecifier *NNS=0, unsigned CharDistance=0,
- unsigned QualifierDistance=0)
+ NestedNameSpecifier *NNS = 0, unsigned CharDistance = 0,
+ unsigned QualifierDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(QualifierDistance),
- CallbackDistance(0) {
+ CharDistance(CharDistance), QualifierDistance(QualifierDistance),
+ CallbackDistance(0), ForceSpecifierReplacement(false) {
if (NameDecl)
CorrectionDecls.push_back(NameDecl);
}
- TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=0,
- unsigned CharDistance=0)
+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = 0,
+ unsigned CharDistance = 0)
: CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) {
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false) {
if (Name)
CorrectionDecls.push_back(Name);
}
- TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=0,
- unsigned CharDistance=0)
+ TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = 0,
+ unsigned CharDistance = 0)
: CorrectionName(Name), CorrectionNameSpec(NNS),
- CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0) {}
+ CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
+ ForceSpecifierReplacement(false) {}
TypoCorrection()
: CorrectionNameSpec(0), CharDistance(0), QualifierDistance(0),
- CallbackDistance(0) {}
+ CallbackDistance(0), ForceSpecifierReplacement(false) {}
/// \brief Gets the DeclarationName of the typo correction
DeclarationName getCorrection() const { return CorrectionName; }
}
void setCorrectionSpecifier(NestedNameSpecifier* NNS) {
CorrectionNameSpec = NNS;
+ ForceSpecifierReplacement = (NNS != 0);
+ }
+
+ void WillReplaceSpecifier(bool ForceReplacement) {
+ ForceSpecifierReplacement = ForceReplacement;
+ }
+
+ bool WillReplaceSpecifier() const {
+ return ForceSpecifierReplacement;
}
void setQualifierDistance(unsigned ED) {
void makeKeyword() {
CorrectionDecls.clear();
CorrectionDecls.push_back(0);
+ ForceSpecifierReplacement = true;
}
// Check if this TypoCorrection is a keyword by checking if the first
void setCorrectionRange(CXXScopeSpec* SS,
const DeclarationNameInfo &TypoName) {
- CorrectionRange.setBegin(CorrectionNameSpec && SS ? SS->getBeginLoc()
- : TypoName.getLoc());
+ CorrectionRange.setBegin(ForceSpecifierReplacement && SS
+ ? SS->getBeginLoc()
+ : TypoName.getLoc());
CorrectionRange.setEnd(TypoName.getLoc());
}
unsigned QualifierDistance;
unsigned CallbackDistance;
SourceRange CorrectionRange;
+ bool ForceSpecifierReplacement;
};
/// @brief Base class for callback objects used by Sema::CorrectTypo to check
LookupCtx, EnteringContext))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name.getAsString() == CorrectedStr;
if (LookupCtx)
Diag(Found.getNameLoc(), diag::err_no_member_suggest)
- << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
+ << Name << LookupCtx << droppedSpecifier << CorrectedQuotedStr
+ << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
else
Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)
<< Name << CorrectedQuotedStr
- << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
-
+ << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+ CorrectedStr);
+
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;
Found.addDecl(ND);
CorrectedQuotedStr = "the keyword " + CorrectedQuotedStr;
Diag(IILoc, diag::err_unknown_typename_suggest)
<< II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
+ << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+ CorrectedStr);
II = NewII;
} else {
NamedDecl *Result = Corrected.getCorrectionDecl();
// We found a similarly-named type or interface; suggest that.
- if (!SS || !SS->isSet())
+ if (!SS || !SS->isSet()) {
Diag(IILoc, diag::err_unknown_typename_suggest)
<< II << CorrectedQuotedStr
- << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);
- else if (DeclContext *DC = computeDeclContext(*SS, false))
- Diag(IILoc, diag::err_unknown_nested_typename_suggest)
- << II << DC << CorrectedQuotedStr << SS->getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
- else
+ } else if (DeclContext *DC = computeDeclContext(*SS, false)) {
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ II->getName().equals(CorrectedStr);
+ Diag(IILoc, diag::err_unknown_nested_typename_suggest)
+ << II << DC << droppedSpecifier << CorrectedQuotedStr
+ << SS->getRange()
+ << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
+ CorrectedStr);
+ }
+ else {
llvm_unreachable("could not have corrected a typo here");
+ }
Diag(Result->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
QualifiedDiag = diag::err_unknown_nested_typename_suggest;
}
- if (SS.isEmpty())
+ if (SS.isEmpty()) {
Diag(NameLoc, UnqualifiedDiag)
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(NameLoc, CorrectedStr);
- else // FIXME: is this even reachable? Test it.
+ } else {// FIXME: is this even reachable? Test it.
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name->getName().equals(CorrectedStr);
Diag(NameLoc, QualifiedDiag)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
+ << Name << computeDeclContext(SS, false) << droppedSpecifier
+ << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
+ }
// Update the name, so that the caller has the new name.
Name = Corrected.getCorrectionAsIdentifierInfo();
Validator)) {
std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOpts()));
- if (DeclContext *DC = S.computeDeclContext(SS, false))
+ if (DeclContext *DC = S.computeDeclContext(SS, false)) {
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Ident->getName().equals(CorrectedStr);
S.Diag(IdentLoc, diag::err_using_directive_member_suggest)
- << Ident << DC << CorrectedQuotedStr << SS.getRange()
- << FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
- CorrectedStr);
- else
+ << Ident << DC << droppedSpecifier << CorrectedQuotedStr
+ << SS.getRange() << FixItHint::CreateReplacement(
+ Corrected.getCorrectionRange(), CorrectedStr);
+ } else {
S.Diag(IdentLoc, diag::err_using_directive_suggest)
<< Ident << CorrectedQuotedStr
<< FixItHint::CreateReplacement(IdentLoc, CorrectedStr);
+ }
S.Diag(Corrected.getCorrectionDecl()->getLocation(),
diag::note_namespace_defined_here) << CorrectedQuotedStr;
S, &SS, CCC))) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
+ bool droppedSpecifier =
+ Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
if (NamedDecl *ND = Corrected.getCorrectionDecl()) {
<< FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange()
+ << Name << computeDeclContext(SS, false) << droppedSpecifier
+ << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
<< Name << CorrectedQuotedStr;
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
+ << Name << computeDeclContext(SS, false) << droppedSpecifier
+ << CorrectedQuotedStr << SS.getRange();
// Don't try to recover; it won't work.
return true;
Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;
else
Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << computeDeclContext(SS, false) << CorrectedQuotedStr
- << SS.getRange();
+ << Name << computeDeclContext(SS, false) << droppedSpecifier
+ << CorrectedQuotedStr << SS.getRange();
return true;
}
}
Corrected.getAsString(SemaRef.getLangOpts()));
std::string CorrectedQuotedStr(
Corrected.getQuoted(SemaRef.getLangOpts()));
+ bool droppedSpecifier =
+ Corrected.WillReplaceSpecifier() && Name.getAsString() == CorrectedStr;
R.setLookupName(Corrected.getCorrection());
for (TypoCorrection::decl_iterator DI = Corrected.begin(),
R.resolveKind();
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
- << Name << DC << CorrectedQuotedStr << SS.getRange()
+ << Name << DC << droppedSpecifier << CorrectedQuotedStr << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
// Perform name lookup on this name.
TypoCorrection &Candidate = I->second.front();
IdentifierInfo *Name = Candidate.getCorrectionAsIdentifierInfo();
- LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,
- EnteringContext, CCC.IsObjCIvarLookup);
+ DeclContext *TempMemberContext = MemberContext;
+ CXXScopeSpec *TempSS = SS;
+retry_lookup:
+ LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS,
+ TempMemberContext, EnteringContext,
+ CCC.IsObjCIvarLookup);
switch (TmpRes.getResultKind()) {
case LookupResult::NotFound:
case LookupResult::NotFoundInCurrentInstantiation:
case LookupResult::FoundUnresolvedValue:
+ if (TempSS) {
+ // Immediately retry the lookup without the given CXXScopeSpec
+ TempSS = NULL;
+ Candidate.WillReplaceSpecifier(true);
+ goto retry_lookup;
+ }
+ if (TempMemberContext) {
+ if (SS && !TempSS)
+ TempSS = SS;
+ TempMemberContext = NULL;
+ goto retry_lookup;
+ }
QualifiedResults.push_back(Candidate);
// We didn't find this name in our scope, or didn't like what we found;
// ignore it.
if (!Found.empty()) {
std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts()));
- if (LookupCtx)
+ if (LookupCtx) {
+ bool droppedSpecifier = Corrected.WillReplaceSpecifier() &&
+ Name.getAsString() == CorrectedStr;
Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)
- << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()
+ << Name << LookupCtx << droppedSpecifier << CorrectedQuotedStr
+ << SS.getRange()
<< FixItHint::CreateReplacement(Corrected.getCorrectionRange(),
CorrectedStr);
- else
+ } else {
Diag(Found.getNameLoc(), diag::err_no_template_suggest)
<< Name << CorrectedQuotedStr
<< FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);
+ }
if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())
Diag(Template->getLocation(), diag::note_previous_decl)
<< CorrectedQuotedStr;
// Fun things you can do with inline namespaces:
inline namespace X {
- void f1(); // expected-note {{'::f1' declared here}}
+ void f1(); // expected-note {{'f1' declared here}}
inline namespace Y {
void f2();
f1();
::f1();
X::f1();
- Y::f1(); // expected-error {{no member named 'f1' in namespace 'X::Y'; did you mean '::f1'?}}
+ Y::f1(); // expected-error {{no member named 'f1' in namespace 'X::Y'; did you mean simply 'f1'?}}
f2();
::f2();
// RUN: grep test_string %t
namespace std {
- template<typename T> class basic_string { // expected-note 2{{'basic_string' declared here}} \
- // expected-note {{'::basic_string' declared here}}
+ template<typename T> class basic_string { // expected-note 3{{'basic_string' declared here}}
public:
int find(const char *substr); // expected-note{{'find' declared here}}
static const int npos = -1; // expected-note{{'npos' declared here}}
template<typename T> class wide_string {}; // expected-note {{'another::wide_string' declared here}}
}
int poit() {
- nonstd::basic_string<char> str; // expected-error{{no template named 'basic_string' in namespace 'nonstd'; did you mean '::basic_string'?}}
+ nonstd::basic_string<char> str; // expected-error{{no template named 'basic_string' in namespace 'nonstd'; did you mean simply 'basic_string'?}}
nonstd::wide_string<char> str2; // expected-error{{no template named 'wide_string' in namespace 'nonstd'; did you mean 'another::wide_string'?}}
return wibble::narf; // expected-error{{no member named 'narf' in namespace 'otherstd'; did you mean 'nonstd::narf'?}}
}
using namespace A ;
}
-namespace C {} // expected-note{{namespace '::C' defined here}}
+namespace C {} // expected-note{{namespace 'C' defined here}}
namespace D {
using namespace B::A ; // expected-error{{no namespace named 'A' in namespace 'D::B'; did you mean '::B::A'?}}
using namespace ::B::A ;
using namespace ::D::F ; // expected-error{{expected namespace name}}
- using namespace ::D::C ; // expected-error{{no namespace named 'C' in namespace 'D'; did you mean '::C'?}}
+ using namespace ::D::C ; // expected-error{{no namespace named 'C' in namespace 'D'; did you mean simply 'C'?}}
}
using namespace ! ; // expected-error{{expected namespace name}}
}
namespace gatekeeper_v1 {
namespace gatekeeper_factory_v1 {
- struct closure_t { // expected-note {{'::gatekeeper_v1::gatekeeper_factory_v1::closure_t' declared here}}
- // FIXME: Just remove the original 'gatekeeper_v1::' name specifier
- // instead of adding a fully-qualified name specifier to 'closure_t'
- gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean '::gatekeeper_v1::gatekeeper_factory_v1::closure_t'?}}
+ struct closure_t { // expected-note {{'closure_t' declared here}}
+ gatekeeper_v1::closure_t* create(); // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1'; did you mean simply 'closure_t'?}}
};
}
- gatekeeper_v1::closure_t *x; // expected-error {{no type named 'closure_t' in namespace 'gatekeeper_v1}}
+ // FIXME: Typo correction should remove the 'gatekeeper_v1::' name specifier
+ gatekeeper_v1::closure_t *x; // expected-error-re {{no type named 'closure_t' in namespace 'gatekeeper_v1'$}}
}