[cfe-commits] r93257 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/Action.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/SemaTemplate/dependent-base-classes.cpp
Douglas Gregor
dgregor at apple.com
Tue Jan 12 13:28:44 PST 2010
Author: dgregor
Date: Tue Jan 12 15:28:44 2010
New Revision: 93257
URL: http://llvm.org/viewvc/llvm-project?rev=93257&view=rev
Log:
Improve recovery for template-ids whose template-name doesn't actually
name a template, when they occur in a base-specifier. This is one of
the (few) places where we know for sure that an identifier followed by
a '<' must be a template name, so we can diagnose and recover well:
test/SemaTemplate/dependent-base-classes.cpp:9:16: error: missing
'template'
keyword prior to dependent template name 'T::apply'
struct X1 : T::apply<U> { }; // expected-error{{missing 'template' ...
^
template
test/SemaTemplate/dependent-base-classes.cpp:12:13: error: unknown
template name
'vector'
struct X2 : vector<T> { }; // expected-error{{unknown template name
'vector'}}
^
2 diagnostics generated.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Jan 12 15:28:44 2010
@@ -261,6 +261,8 @@
/// C++ Templates
def err_expected_template : Error<"expected template">;
+def err_unknown_template_name : Error<
+ "unknown template name %0">;
def err_expected_comma_greater : Error<
"expected ',' or '>' in template-parameter-list">;
def err_expected_type_id_after : Error<"expected type-id after '%0'">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jan 12 15:28:44 2010
@@ -1309,6 +1309,8 @@
"'%0%1' instantiated to a class template, not a function template">;
def note_referenced_class_template : Error<
"class template declared here">;
+def err_template_kw_missing : Error<
+ "missing 'template' keyword prior to dependent template name '%0%1'">;
// C++0x Variadic Templates
def err_template_param_pack_default_arg : Error<
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Jan 12 15:28:44 2010
@@ -291,6 +291,42 @@
bool EnteringContext,
TemplateTy &Template) = 0;
+ /// \brief Action called as part of error recovery when the parser has
+ /// determined that the given name must refer to a template, but
+ /// \c isTemplateName() did not return a result.
+ ///
+ /// This callback permits the action to give a detailed diagnostic when an
+ /// unknown template name is encountered and, potentially, to try to recover
+ /// by producing a new template in \p SuggestedTemplate.
+ ///
+ /// \param II the name that should be a template.
+ ///
+ /// \param IILoc the location of the name in the source.
+ ///
+ /// \param S the scope in which name lookup was performed.
+ ///
+ /// \param SS the C++ scope specifier that preceded the name.
+ ///
+ /// \param SuggestedTemplate if the action sets this template to a non-NULL,
+ /// template, the parser will recover by consuming the template name token
+ /// and the template argument list that follows.
+ ///
+ /// \param SuggestedTemplateKind as input, the kind of template that we
+ /// expect (e.g., \c TNK_Type_template or \c TNK_Function_template). If the
+ /// action provides a suggested template, this should be set to the kind of
+ /// template.
+ ///
+ /// \returns true if a diagnostic was emitted, false otherwise. When false,
+ /// the parser itself will emit a generic "unknown template name" diagnostic.
+ virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind) {
+ return false;
+ }
+
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Jan 12 15:28:44 2010
@@ -490,18 +490,57 @@
return true;
}
+ IdentifierInfo *Id = Tok.getIdentifierInfo();
+ SourceLocation IdLoc = ConsumeToken();
+
+ if (Tok.is(tok::less)) {
+ // It looks the user intended to write a template-id here, but the
+ // template-name was wrong. Try to fix that.
+ TemplateNameKind TNK = TNK_Type_template;
+ TemplateTy Template;
+ if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope,
+ SS, Template, TNK)) {
+ Diag(IdLoc, diag::err_unknown_template_name)
+ << Id;
+ }
+
+ if (!Template)
+ return true;
+
+ // Form the template name
+ UnqualifiedId TemplateName;
+ TemplateName.setIdentifier(Id, IdLoc);
+
+ // Parse the full template-id, then turn it into a type.
+ if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
+ SourceLocation(), true))
+ return true;
+ if (TNK == TNK_Dependent_template_name)
+ AnnotateTemplateIdTokenAsType(SS);
+
+ // If we didn't end up with a typename token, there's nothing more we
+ // can do.
+ if (Tok.isNot(tok::annot_typename))
+ return true;
+
+ // Retrieve the type from the annotation token, consume that token, and
+ // return.
+ EndLocation = Tok.getAnnotationEndLoc();
+ TypeTy *Type = Tok.getAnnotationValue();
+ ConsumeToken();
+ return Type;
+ }
+
// We have an identifier; check whether it is actually a type.
- TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope, SS,
- true);
- if (!Type) {
- Diag(Tok, DestrExpected ? diag::err_destructor_class_name
+ TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
+ if (!Type) {
+ Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
: diag::err_expected_class_name);
return true;
}
// Consume the identifier.
- EndLocation = ConsumeToken();
+ EndLocation = IdLoc;
return Type;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jan 12 15:28:44 2010
@@ -2367,6 +2367,14 @@
TypeTy *ObjectType,
bool EnteringContext,
TemplateTy &Template);
+
+ virtual bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind);
+
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jan 12 15:28:44 2010
@@ -143,6 +143,30 @@
return TemplateKind;
}
+bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+ SourceLocation IILoc,
+ Scope *S,
+ const CXXScopeSpec *SS,
+ TemplateTy &SuggestedTemplate,
+ TemplateNameKind &SuggestedKind) {
+ // We can't recover unless there's a dependent scope specifier preceding the
+ // template name.
+ if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) ||
+ computeDeclContext(*SS))
+ return false;
+
+ // The code is missing a 'template' keyword prior to the dependent template
+ // name.
+ NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep();
+ Diag(IILoc, diag::err_template_kw_missing)
+ << Qualifier << II.getName()
+ << CodeModificationHint::CreateInsertion(IILoc, "template ");
+ SuggestedTemplate
+ = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II));
+ SuggestedKind = TNK_Dependent_template_name;
+ return true;
+}
+
void Sema::LookupTemplateName(LookupResult &Found,
Scope *S, const CXXScopeSpec &SS,
QualType ObjectType,
Modified: cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp?rev=93257&r1=93256&r2=93257&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp (original)
+++ cfe/trunk/test/SemaTemplate/dependent-base-classes.cpp Tue Jan 12 15:28:44 2010
@@ -4,3 +4,9 @@
struct X0 : T::template apply<U> {
X0(U u) : T::template apply<U>(u) { }
};
+
+template<typename T, typename U>
+struct X1 : T::apply<U> { }; // expected-error{{missing 'template' keyword prior to dependent template name 'T::apply'}}
+
+template<typename T>
+struct X2 : vector<T> { }; // expected-error{{unknown template name 'vector'}}
More information about the cfe-commits
mailing list