Diagnose the declaration of enum templates. Also, be a bit more

careful about value-dependent enumerators. Fixes PR5786.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97570 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2010-03-02 17:53:14 +00:00
Родитель be08ac7afb
Коммит 9b9edd619a
5 изменённых файлов: 24 добавлений и 7 удалений

Просмотреть файл

@ -300,6 +300,7 @@ def err_explicit_instantiation_with_definition : Error<
"explicit template instantiation cannot have a definition; if this " "explicit template instantiation cannot have a definition; if this "
"definition is meant to be an explicit specialization, add '<>' after the " "definition is meant to be an explicit specialization, add '<>' after the "
"'template' keyword">; "'template' keyword">;
def err_enum_template : Error<"enumeration cannot be a template">;
// Constructor template diagnostics. // Constructor template diagnostics.
def err_out_of_line_constructor_template_id : Error< def err_out_of_line_constructor_template_id : Error<

Просмотреть файл

@ -1115,7 +1115,7 @@ private:
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS); void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
AccessSpecifier AS = AS_none); const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclPtrTy TagDecl); DeclPtrTy TagDecl);

Просмотреть файл

@ -738,7 +738,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Parse this as a tag as if the missing tag were present. // Parse this as a tag as if the missing tag were present.
if (TagKind == tok::kw_enum) if (TagKind == tok::kw_enum)
ParseEnumSpecifier(Loc, DS, AS); ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
else else
ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS); ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
return true; return true;
@ -1306,7 +1306,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// enum-specifier: // enum-specifier:
case tok::kw_enum: case tok::kw_enum:
ConsumeToken(); ConsumeToken();
ParseEnumSpecifier(Loc, DS, AS); ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
continue; continue;
// cv-qualifier: // cv-qualifier:
@ -1572,7 +1572,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// enum-specifier: // enum-specifier:
case tok::kw_enum: case tok::kw_enum:
ConsumeToken(); ConsumeToken();
ParseEnumSpecifier(Loc, DS); ParseEnumSpecifier(Loc, DS, TemplateInfo, AS_none);
return true; return true;
// cv-qualifier: // cv-qualifier:
@ -1850,6 +1850,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
/// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier /// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier
/// ///
void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS) { AccessSpecifier AS) {
// Parse the tag portion of this. // Parse the tag portion of this.
if (Tok.is(tok::code_completion)) { if (Tok.is(tok::code_completion)) {
@ -1888,6 +1889,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return; return;
} }
// enums cannot be templates.
if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
Diag(Tok, diag::err_enum_template);
// Skip the rest of this declarator, up until the comma or semicolon.
SkipUntil(tok::comma, true);
return;
}
// If an identifier is present, consume and remember it. // If an identifier is present, consume and remember it.
IdentifierInfo *Name = 0; IdentifierInfo *Name = 0;
SourceLocation NameLoc; SourceLocation NameLoc;

Просмотреть файл

@ -5757,12 +5757,13 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
llvm::APSInt EnumVal(IntWidth); llvm::APSInt EnumVal(IntWidth);
QualType EltTy; QualType EltTy;
if (Val) { if (Val) {
if (Enum->isDependentType()) if (Enum->isDependentType() || Val->isTypeDependent())
EltTy = Context.DependentTy; EltTy = Context.DependentTy;
else { else {
// C99 6.7.2.2p2: Make sure we have an integer constant expression. // C99 6.7.2.2p2: Make sure we have an integer constant expression.
SourceLocation ExpLoc; SourceLocation ExpLoc;
if (VerifyIntegerConstantExpression(Val, &EnumVal)) { if (!Val->isValueDependent() &&
VerifyIntegerConstantExpression(Val, &EnumVal)) {
Val = 0; Val = 0;
} else { } else {
if (!getLangOptions().CPlusPlus) { if (!getLangOptions().CPlusPlus) {
@ -5864,7 +5865,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
} }
} }
if (!Enum->isDependentType()) { if (!EltTy->isDependentType()) {
// Make the enumerator value match the signedness and size of the // Make the enumerator value match the signedness and size of the
// enumerator's type. // enumerator's type.
EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); EnumVal.zextOrTrunc(Context.getTypeSize(EltTy));

Просмотреть файл

@ -1,3 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename T> typedef T X; // expected-error{{typedef cannot be a template}} template<typename T> typedef T X; // expected-error{{typedef cannot be a template}}
template<typename T>
enum t0 { A = T::x }; // expected-error{{enumeration cannot be a template}} \
// expected-error{{declaration does not declare anything}}