forked from OSchip/llvm-project
In Parser::ParseClassSpecifier, don't conflate a NULL declaration with
failure to perform a declaration. Instead, explicitly note semantic failures that occur during template parsing with a DeclResult. Fixes PR3872. llvm-svn: 67659
This commit is contained in:
parent
1e7602a20e
commit
c08f489d38
|
@ -85,6 +85,7 @@ public:
|
|||
typedef ActionResult<2> TypeResult;
|
||||
typedef ActionResult<3> BaseResult;
|
||||
typedef ActionResult<4> MemInitResult;
|
||||
typedef ActionResult<5> DeclResult;
|
||||
|
||||
/// Same, but with ownership.
|
||||
typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult;
|
||||
|
@ -1169,7 +1170,7 @@ public:
|
|||
|
||||
/// \brief Process the declaration or definition of a class template
|
||||
/// with the given template parameter lists.
|
||||
virtual DeclTy *
|
||||
virtual DeclResult
|
||||
ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc, const CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
|
@ -1247,7 +1248,7 @@ public:
|
|||
/// common for users to provide the wrong number of template
|
||||
/// parameter lists (such as a missing \c template<> prior to a
|
||||
/// specialization); the parser does not check this condition.
|
||||
virtual DeclTy *
|
||||
virtual DeclResult
|
||||
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
|
|
|
@ -431,7 +431,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
|
|||
}
|
||||
|
||||
// Create the tag portion of the class or class template.
|
||||
DeclTy *TagOrTempDecl;
|
||||
Action::DeclResult TagOrTempResult;
|
||||
if (TemplateId && TK != Action::TK_Reference) {
|
||||
// Explicit specialization or class template partial
|
||||
// specialization. Let semantic analysis decide.
|
||||
|
@ -439,7 +439,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
|
|||
TemplateId->getTemplateArgs(),
|
||||
TemplateId->getTemplateArgIsType(),
|
||||
TemplateId->NumArgs);
|
||||
TagOrTempDecl
|
||||
TagOrTempResult
|
||||
= Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
|
||||
StartLoc, SS,
|
||||
TemplateId->Template,
|
||||
|
@ -454,25 +454,26 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
|
|||
TemplateParams? TemplateParams->size() : 0));
|
||||
TemplateId->Destroy();
|
||||
} else if (TemplateParams && TK != Action::TK_Reference)
|
||||
TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc,
|
||||
SS, Name, NameLoc, Attr,
|
||||
TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK,
|
||||
StartLoc, SS, Name, NameLoc,
|
||||
Attr,
|
||||
Action::MultiTemplateParamsArg(Actions,
|
||||
&(*TemplateParams)[0],
|
||||
TemplateParams->size()));
|
||||
else
|
||||
TagOrTempDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
|
||||
TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
|
||||
NameLoc, Attr);
|
||||
|
||||
// Parse the optional base clause (C++ only).
|
||||
if (getLang().CPlusPlus && Tok.is(tok::colon))
|
||||
ParseBaseClause(TagOrTempDecl);
|
||||
ParseBaseClause(TagOrTempResult.get());
|
||||
|
||||
// If there is a body, parse it and inform the actions module.
|
||||
if (Tok.is(tok::l_brace))
|
||||
if (getLang().CPlusPlus)
|
||||
ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempDecl);
|
||||
ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
|
||||
else
|
||||
ParseStructUnionBody(StartLoc, TagType, TagOrTempDecl);
|
||||
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
|
||||
else if (TK == Action::TK_Definition) {
|
||||
// FIXME: Complain that we have a base-specifier list but no
|
||||
// definition.
|
||||
|
@ -480,9 +481,10 @@ void Parser::ParseClassSpecifier(DeclSpec &DS,
|
|||
}
|
||||
|
||||
const char *PrevSpec = 0;
|
||||
if (!TagOrTempDecl)
|
||||
if (TagOrTempResult.isInvalid())
|
||||
DS.SetTypeSpecError();
|
||||
else if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl))
|
||||
else if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec,
|
||||
TagOrTempResult.get()))
|
||||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||
}
|
||||
|
||||
|
|
|
@ -1704,7 +1704,7 @@ public:
|
|||
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
|
||||
TemplateParameterList *OldParams);
|
||||
|
||||
virtual DeclTy *
|
||||
virtual DeclResult
|
||||
ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc, const CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
|
@ -1731,7 +1731,7 @@ public:
|
|||
SourceLocation TemplateNameLoc,
|
||||
SourceRange ScopeSpecifierRange);
|
||||
|
||||
virtual DeclTy *
|
||||
virtual DeclResult
|
||||
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
|
|
|
@ -361,7 +361,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
|
|||
(Decl**)Params, NumParams, RAngleLoc);
|
||||
}
|
||||
|
||||
Sema::DeclTy *
|
||||
Sema::DeclResult
|
||||
Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc, const CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
|
@ -373,7 +373,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
|
||||
// Check that we can declare a template here.
|
||||
if (CheckTemplateDeclScope(S, TemplateParameterLists))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
TagDecl::TagKind Kind;
|
||||
switch (TagSpec) {
|
||||
|
@ -386,7 +386,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
// There is no such thing as an unnamed class template.
|
||||
if (!Name) {
|
||||
Diag(KWLoc, diag::err_template_unnamed_class);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find any previous declaration with this name.
|
||||
|
@ -418,7 +418,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
if (!TemplateParameterListsAreEqual(TemplateParams,
|
||||
PrevClassTemplate->getTemplateParameters(),
|
||||
/*Complain=*/true))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
// C++ [temp.class]p4:
|
||||
// In a redeclaration, partial specialization, explicit
|
||||
|
@ -429,7 +429,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
if (PrevRecordDecl->getTagKind() != Kind) {
|
||||
Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
|
||||
Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -440,7 +440,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
Diag(Def->getLocation(), diag::note_previous_definition);
|
||||
// FIXME: Would it make sense to try to "forget" the previous
|
||||
// definition, as part of error recovery?
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (PrevDecl && PrevDecl->isTemplateParameter()) {
|
||||
|
@ -456,7 +456,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
// in (14.5.4).
|
||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the template parameter list of this declaration, possibly
|
||||
|
@ -1767,7 +1767,7 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
|
|||
return false;
|
||||
}
|
||||
|
||||
Sema::DeclTy *
|
||||
Sema::DeclResult
|
||||
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
||||
SourceLocation KWLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
|
@ -1783,7 +1783,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
ClassTemplateDecl *ClassTemplate
|
||||
= dyn_cast_or_null<ClassTemplateDecl>(static_cast<Decl *>(TemplateD));
|
||||
if (!ClassTemplate)
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
// Check the validity of the template headers that introduce this
|
||||
// template.
|
||||
|
@ -1796,18 +1796,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
else {
|
||||
TemplateParameterList *TemplateParams
|
||||
= static_cast<TemplateParameterList*>(*TemplateParameterLists.get());
|
||||
if (TemplateParameterLists.size() > 1) {
|
||||
Diag(TemplateParams->getTemplateLoc(),
|
||||
diag::err_template_spec_extra_headers);
|
||||
return 0;
|
||||
}
|
||||
if (TemplateParameterLists.size() > 1)
|
||||
return Diag(TemplateParams->getTemplateLoc(),
|
||||
diag::err_template_spec_extra_headers);
|
||||
|
||||
if (TemplateParams->size() > 0) {
|
||||
if (TemplateParams->size() > 0)
|
||||
// FIXME: No support for class template partial specialization.
|
||||
Diag(TemplateParams->getTemplateLoc(),
|
||||
diag::unsup_template_partial_spec);
|
||||
return 0;
|
||||
}
|
||||
return Diag(TemplateParams->getTemplateLoc(),
|
||||
diag::unsup_template_partial_spec);
|
||||
}
|
||||
|
||||
// Check that the specialization uses the same tag kind as the
|
||||
|
@ -1836,7 +1832,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
|
||||
&TemplateArgs[0], TemplateArgs.size(),
|
||||
RAngleLoc, ConvertedTemplateArgs))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
assert((ConvertedTemplateArgs.size() ==
|
||||
ClassTemplate->getTemplateParameters()->size()) &&
|
||||
|
@ -1858,7 +1854,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl,
|
||||
TemplateNameLoc,
|
||||
SS.getRange()))
|
||||
return 0;
|
||||
return true;
|
||||
|
||||
if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) {
|
||||
// Since the only prior class template specialization with these
|
||||
|
@ -1902,7 +1898,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
<< Specialization << Range;
|
||||
Diag(Def->getLocation(), diag::note_previous_definition);
|
||||
Specialization->setInvalidDecl();
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue