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 4b8ed44..fb80dcc 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -300,6 +300,7 @@
"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 807a314..f034aa1 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1115,7 +1115,7 @@
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 8a32f35..12c5b6c 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -738,7 +738,7 @@
// 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 @@
// enum-specifier:
case tok::kw_enum:
ConsumeToken();
- ParseEnumSpecifier(Loc, DS, AS);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
continue;
// cv-qualifier:
@@ -1572,7 +1572,7 @@
// enum-specifier:
case tok::kw_enum:
ConsumeToken();
- ParseEnumSpecifier(Loc, DS);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS_none);
return true;
// cv-qualifier:
@@ -1850,6 +1850,7 @@
/// [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 @@
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 d7cbb8f..ec1939e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -5757,12 +5757,13 @@
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 @@
}
}
- 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 a298c6d..eca0f58 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<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}}
+