diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | clang/test/SemaTemplate/template-decl-fail.cpp | 5 |
5 files changed, 24 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 4b8ed447831..fb80dccc6fb 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/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/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 807a3148ea1..f034aa10ce3 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 8a32f35b64b..12c5b6c7048 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d7cbb8fd59d..ec1939e5ece 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/test/SemaTemplate/template-decl-fail.cpp b/clang/test/SemaTemplate/template-decl-fail.cpp index a298c6d5a4b..eca0f58831a 100644 --- a/clang/test/SemaTemplate/template-decl-fail.cpp +++ b/clang/test/SemaTemplate/template-decl-fail.cpp @@ -1,3 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s 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}} + |