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
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index df3cc59..d32507a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1354,7 +1354,8 @@
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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 0950ab0..20ac4df 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2192,7 +2192,9 @@
// 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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 17e0f38..7221075 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -62,24 +62,29 @@
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 @@
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/clang/test/SemaCXX/typo-correction-pt2.cpp b/clang/test/SemaCXX/typo-correction-pt2.cpp
index 1738bb4..e08bef0 100644
--- a/clang/test/SemaCXX/typo-correction-pt2.cpp
+++ b/clang/test/SemaCXX/typo-correction-pt2.cpp
@@ -223,3 +223,14 @@
}
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}}
+};
+}