r196333 - Fix several crash-on-invalids when using template-ids that aren't
Richard Smith
richard-llvm at metafoo.co.uk
Tue Dec 3 16:28:23 PST 2013
Author: rsmith
Date: Tue Dec 3 18:28:23 2013
New Revision: 196333
URL: http://llvm.org/viewvc/llvm-project?rev=196333&view=rev
Log:
Fix several crash-on-invalids when using template-ids that aren't
simple-template-ids (eg, 'operator+<int>') in weird places.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/TemplateKinds.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/drs/dr3xx.cpp
cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Dec 3 18:28:23 2013
@@ -578,8 +578,8 @@ def err_class_on_template_template_param
"template template parameter requires 'class' after the parameter list">;
def err_template_spec_syntax_non_template : Error<
"identifier followed by '<' indicates a class template specialization but "
- "%0 %select{does not refer to a template|refers to a function "
- "template|<unused>|refers to a template template parameter}1">;
+ "%0 %select{does not refer to a template|refers to a function template|"
+ "<unused>|refers to a variable template|<unused>}1">;
def err_id_after_template_in_nested_name_spec : Error<
"expected template name after 'template' keyword in nested name specifier">;
def err_two_right_angle_brackets_need_space : Error<
@@ -643,7 +643,7 @@ def err_expected_semi_after_tagdecl : Er
"expected ';' after %0">;
def err_typename_refers_to_non_type_template : Error<
- "typename specifier refers to a non-template">;
+ "typename specifier refers to a non-type template">;
def err_expected_type_name_after_typename : Error<
"expected an identifier or template-id after '::'">;
def err_explicit_spec_non_template : Error<
Modified: cfe/trunk/include/clang/Basic/TemplateKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TemplateKinds.h?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TemplateKinds.h (original)
+++ cfe/trunk/include/clang/Basic/TemplateKinds.h Tue Dec 3 18:28:23 2013
@@ -17,6 +17,7 @@
namespace clang {
/// \brief Specifies the kind of template name that an identifier refers to.
+/// Be careful when changing this: this enumeration is used in diagnostics.
enum TemplateNameKind {
/// The name does not refer to a template.
TNK_Non_template = 0,
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Dec 3 18:28:23 2013
@@ -1287,6 +1287,7 @@ void Parser::ParseClassSpecifier(tok::To
if (SS.isNotEmpty())
Range.setBegin(SS.getBeginLoc());
+ // FIXME: Name may be null here.
Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
<< TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Dec 3 18:28:23 2013
@@ -341,10 +341,10 @@ bool Parser::ParseOptionalCXXScopeSpecif
if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
// We have
//
- // simple-template-id '::'
+ // template-id '::'
//
- // So we need to check whether the simple-template-id is of the
- // right kind (it should name a type or be dependent), and then
+ // So we need to check whether the template-id is a simple-template-id of
+ // the right kind (it should name a type or be dependent), and then
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
@@ -1882,6 +1882,7 @@ bool Parser::ParseUnqualifiedIdTemplateI
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
+ // FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
TemplateId->Operator = OO_None;
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Dec 3 18:28:23 2013
@@ -1615,7 +1615,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
- if (TemplateId->Kind == TNK_Function_template) {
+ if (TemplateId->Kind != TNK_Type_template &&
+ TemplateId->Kind != TNK_Dependent_template_name) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
<< Tok.getAnnotationRange();
return true;
@@ -1740,6 +1741,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
AnnotateTemplateIdTokenAsType();
return false;
} else if (TemplateId->Kind == TNK_Var_template)
+ // FIXME: This looks suspicious. Why are we not annotating the scope token
+ // in this case?
return false;
}
Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Tue Dec 3 18:28:23 2013
@@ -747,7 +747,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(S
TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
translateTemplateArguments(TemplateArgsIn, TemplateArgs);
- if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){
+ DependentTemplateName *DTN = Template.get().getAsDependentTemplateName();
+ if (DTN && DTN->isIdentifier()) {
// Handle a dependent template specialization for which we cannot resolve
// the template name.
assert(DTN->getQualifier() == SS.getScopeRep());
@@ -773,20 +774,20 @@ bool Sema::ActOnCXXNestedNameSpecifier(S
CCLoc);
return false;
}
-
-
- if (Template.get().getAsOverloadedTemplate() ||
+
+ // FIXME: Variable templates
+ if (Template.get().getAsOverloadedTemplate() || DTN ||
isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
SourceRange R(TemplateNameLoc, RAngleLoc);
if (SS.getRange().isValid())
R.setBegin(SS.getRange().getBegin());
-
+
Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
<< Template.get() << R;
NoteAllFoundTemplates(Template.get());
return true;
}
-
+
// We were able to resolve the template name to an actual template.
// Build an appropriate nested-name-specifier.
QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc,
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Dec 3 18:28:23 2013
@@ -2910,7 +2910,7 @@ TemplateNameKind Sema::ActOnDependentTem
case UnqualifiedId::IK_OperatorFunctionId:
Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier,
Name.OperatorFunctionId.Operator));
- return TNK_Dependent_template_name;
+ return TNK_Function_template;
case UnqualifiedId::IK_LiteralOperatorId:
llvm_unreachable(
Modified: cfe/trunk/test/CXX/drs/dr3xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr3xx.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr3xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr3xx.cpp Tue Dec 3 18:28:23 2013
@@ -8,4 +8,29 @@ namespace dr300 { // dr300: yes
void h() { f(g); }
}
-// expected-no-diagnostics
+namespace dr301 { // dr301 WIP
+ // see also dr38
+ struct S;
+ template<typename T> void operator+(T, T);
+ void operator-(S, S);
+
+ void f() {
+ bool a = (void(*)(S, S))operator+<S> <
+ (void(*)(S, S))operator+<S>;
+ bool b = (void(*)(S, S))operator- <
+ (void(*)(S, S))operator-;
+ bool c = (void(*)(S, S))operator+ <
+ (void(*)(S, S))operator-; // expected-error {{expected '>'}}
+ }
+
+ template<typename T> void f() {
+ typename T::template operator+<int> a; // expected-error {{typename specifier refers to a non-type template}} expected-error +{{}}
+ // FIXME: This shouldn't say (null).
+ class T::template operator+<int> b; // expected-error {{identifier followed by '<' indicates a class template specialization but (null) refers to a function template}}
+ enum T::template operator+<int> c; // expected-error {{expected identifier}} expected-error {{does not declare anything}}
+ enum T::template operator+<int>::E d; // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}} expected-error {{forward reference}}
+ enum T::template X<int>::E e;
+ T::template operator+<int>::foobar(); // expected-error {{qualified name refers into a specialization of function template 'T::template operator +'}}
+ T::template operator+<int>(0); // ok
+ }
+}
Modified: cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp?rev=196333&r1=196332&r2=196333&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-variable-templates_top_level.cpp Tue Dec 3 18:28:23 2013
@@ -432,3 +432,11 @@ namespace nested {
}
}
+namespace nested_name {
+ template<typename T> int a;
+ // FIXME: This triggers a crash.
+ //a<int>::b c;
+
+ class a<int> {}; // expected-error {{identifier followed by '<' indicates a class template specialization but 'a' refers to a variable template}}
+ enum a<int> {}; // expected-error {{expected identifier or '{'}} expected-warning {{does not declare anything}}
+}
More information about the cfe-commits
mailing list