From: Douglas Gregor Date: Tue, 2 Mar 2010 17:53:14 +0000 (+0000) Subject: Diagnose the declaration of enum templates. Also, be a bit more X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9b9edd619a7e616d3287435cb5a3f9b1aea648e8;p=clang 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 --- diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 4b8ed44783..fb80dccc6f 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -300,6 +300,7 @@ def err_explicit_instantiation_with_definition : Error< "explicit template instantiation cannot have a definition; if this " "definition is meant to be an explicit specialization, add '<>' after the " "'template' keyword">; +def err_enum_template : Error<"enumeration cannot be a template">; // Constructor template diagnostics. def err_out_of_line_constructor_template_id : Error< diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 807a3148ea..f034aa10ce 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1115,7 +1115,7 @@ private: void ParseObjCTypeQualifierList(ObjCDeclSpec &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 ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, DeclPtrTy TagDecl); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 8a32f35b64..12c5b6c704 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -738,7 +738,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) - ParseEnumSpecifier(Loc, DS, AS); + ParseEnumSpecifier(Loc, DS, TemplateInfo, AS); else ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS); return true; @@ -1306,7 +1306,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // enum-specifier: case tok::kw_enum: ConsumeToken(); - ParseEnumSpecifier(Loc, DS, AS); + ParseEnumSpecifier(Loc, DS, TemplateInfo, AS); continue; // cv-qualifier: @@ -1572,7 +1572,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, // enum-specifier: case tok::kw_enum: ConsumeToken(); - ParseEnumSpecifier(Loc, DS); + ParseEnumSpecifier(Loc, DS, TemplateInfo, AS_none); return true; // cv-qualifier: @@ -1850,6 +1850,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, /// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier /// void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS) { // Parse the tag portion of this. if (Tok.is(tok::code_completion)) { @@ -1888,6 +1889,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, 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. IdentifierInfo *Name = 0; SourceLocation NameLoc; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d7cbb8fd59..ec1939e5ec 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5757,12 +5757,13 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, llvm::APSInt EnumVal(IntWidth); QualType EltTy; if (Val) { - if (Enum->isDependentType()) + if (Enum->isDependentType() || Val->isTypeDependent()) EltTy = Context.DependentTy; else { // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; - if (VerifyIntegerConstantExpression(Val, &EnumVal)) { + if (!Val->isValueDependent() && + VerifyIntegerConstantExpression(Val, &EnumVal)) { Val = 0; } else { 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 // enumerator's type. EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); diff --git a/test/SemaTemplate/template-decl-fail.cpp b/test/SemaTemplate/template-decl-fail.cpp index a298c6d5a4..eca0f58831 100644 --- a/test/SemaTemplate/template-decl-fail.cpp +++ b/test/SemaTemplate/template-decl-fail.cpp @@ -1,3 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s template typedef T X; // expected-error{{typedef cannot be a template}} + +template +enum t0 { A = T::x }; // expected-error{{enumeration cannot be a template}} \ + // expected-error{{declaration does not declare anything}} +