forked from OSchip/llvm-project
Fix several crash-on-invalids when using template-ids that aren't
simple-template-ids (eg, 'operator+<int>') in weird places. llvm-svn: 196333
This commit is contained in:
parent
f389e5c093
commit
72bfbd8615
|
@ -578,8 +578,8 @@ def err_class_on_template_template_param : Error<
|
|||
"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 : Error<
|
|||
"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<
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1287,6 +1287,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
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;
|
||||
|
||||
|
|
|
@ -341,10 +341,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
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::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
|
|||
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;
|
||||
|
|
|
@ -1615,7 +1615,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) {
|
|||
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::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -747,7 +747,8 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *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(Scope *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,
|
||||
|
|
|
@ -2910,7 +2910,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S,
|
|||
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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue