Enable correcting a member declaration where the type is class template,

and the class name is shadowed by another member. Recovery still needs
to be figured out, which is non-trivial since the parser has already gone
down a much different path than if it had recognized the class template
as type instead of seeing the member that shadowed the class template.

llvm-svn: 201360
This commit is contained in:
Kaelyn Uhrain 2014-02-13 20:14:07 +00:00
parent b1b5007c52
commit 67b44c9871
4 changed files with 31 additions and 11 deletions

View File

@ -1354,7 +1354,8 @@ public:
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
ParsedType &SuggestedType);
ParsedType &SuggestedType,
bool AllowClassTemplates = false);
/// \brief Describes the result of the name lookup and resolution performed
/// by \c ClassifyName().

View File

@ -2192,7 +2192,9 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// diagnostic and attempt to recover.
ParsedType T;
IdentifierInfo *II = Tok.getIdentifierInfo();
if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T)) {
if (Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,
getLangOpts().CPlusPlus &&
NextToken().is(tok::less))) {
// The action emitted a diagnostic, so we don't have to.
if (T) {
// The action has suggested that the type T could be used. Set that as

View File

@ -62,24 +62,29 @@ namespace {
class TypeNameValidatorCCC : public CorrectionCandidateCallback {
public:
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false)
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass) {
TypeNameValidatorCCC(bool AllowInvalid, bool WantClass=false,
bool AllowTemplates=false)
: AllowInvalidDecl(AllowInvalid), WantClassName(WantClass),
AllowClassTemplates(AllowTemplates) {
WantExpressionKeywords = false;
WantCXXNamedCasts = false;
WantRemainingKeywords = false;
}
virtual bool ValidateCandidate(const TypoCorrection &candidate) {
if (NamedDecl *ND = candidate.getCorrectionDecl())
return (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
(AllowInvalidDecl || !ND->isInvalidDecl());
else
return !WantClassName && candidate.isKeyword();
if (NamedDecl *ND = candidate.getCorrectionDecl()) {
bool IsType = isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
bool AllowedTemplate = AllowClassTemplates && isa<ClassTemplateDecl>(ND);
return (IsType || AllowedTemplate) &&
(AllowInvalidDecl || !ND->isInvalidDecl());
}
return !WantClassName && candidate.isKeyword();
}
private:
bool AllowInvalidDecl;
bool WantClassName;
bool AllowClassTemplates;
};
}
@ -394,13 +399,14 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
SourceLocation IILoc,
Scope *S,
CXXScopeSpec *SS,
ParsedType &SuggestedType) {
ParsedType &SuggestedType,
bool AllowClassTemplates) {
// We don't have anything to suggest (yet).
SuggestedType = ParsedType();
// There may have been a typo in the name of the type. Look up typo
// results, in case we have something that we can suggest.
TypeNameValidatorCCC Validator(false);
TypeNameValidatorCCC Validator(false, false, AllowClassTemplates);
if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(II, IILoc),
LookupOrdinaryName, S, SS,
Validator)) {

View File

@ -223,3 +223,14 @@ SmallSetVector<foo*, 2> fooSet;
}
PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}
namespace shadowed_template {
template <typename T> class Fizbin {}; // expected-note {{'::shadowed_template::Fizbin' declared here}}
class Baz {
int Fizbin();
// TODO: Teach the parser to recover from the typo correction instead of
// continuing to treat the template name as an implicit-int declaration.
Fizbin<int> qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
// expected-error {{expected member name or ';' after declaration specifiers}}
};
}