From: Kaelyn Uhrain Date: Thu, 13 Feb 2014 20:14:07 +0000 (+0000) Subject: Enable correcting a member declaration where the type is class template, X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bf5be516bea7d72540dbb7eed525c72b6e3ca561;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201360 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index df3cc596f4..d32507a06d 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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(). diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 0950ab09b7..20ac4df544 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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 diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 17e0f38e07..72210757f3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(ND) || isa(ND)) && - (AllowInvalidDecl || !ND->isInvalidDecl()); - else - return !WantClassName && candidate.isKeyword(); + if (NamedDecl *ND = candidate.getCorrectionDecl()) { + bool IsType = isa(ND) || isa(ND); + bool AllowedTemplate = AllowClassTemplates && isa(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)) { diff --git a/test/SemaCXX/typo-correction-pt2.cpp b/test/SemaCXX/typo-correction-pt2.cpp index 1738bb41b9..e08bef0741 100644 --- a/test/SemaCXX/typo-correction-pt2.cpp +++ b/test/SemaCXX/typo-correction-pt2.cpp @@ -223,3 +223,14 @@ SmallSetVector fooSet; } PR18685::BitVector Map; // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}} + +namespace shadowed_template { +template 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 qux; // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \ + // expected-error {{expected member name or ';' after declaration specifiers}} +}; +}