Create EnumConstantDecl objects for each enum value, and fill them into
the EnumDecl when the enum type is complete. This allows us to detect
redefinitions of enums.
llvm-svn: 39300
diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp
index 7dbba29..781d09b 100644
--- a/clang/Parse/ParseDecl.cpp
+++ b/clang/Parse/ParseDecl.cpp
@@ -579,10 +579,10 @@
}
}
- Actions.ParseRecordBody(RecordLoc, TagDecl, &FieldDecls[0],FieldDecls.size());
-
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+ Actions.ParseRecordBody(RecordLoc, TagDecl, &FieldDecls[0],FieldDecls.size());
+
// If attributes exist after struct contents, parse them.
if (Tok.getKind() == tok::kw___attribute)
ParseAttributes();
@@ -597,15 +597,6 @@
/// '}' attributes[opt]
/// 'enum' identifier
/// [GNU] 'enum' attributes[opt] identifier
-/// enumerator-list:
-/// enumerator
-/// enumerator-list ',' enumerator
-/// enumerator:
-/// enumeration-constant
-/// enumeration-constant '=' constant-expression
-/// enumeration-constant:
-/// identifier
-///
void Parser::ParseEnumSpecifier(DeclSpec &DS) {
assert(Tok.getKind() == tok::kw_enum && "Not an enum specifier");
SourceLocation StartLoc = ConsumeToken();
@@ -615,45 +606,73 @@
if (ParseTag(TagDecl, DeclSpec::TST_enum, StartLoc))
return;
- if (Tok.getKind() == tok::l_brace) {
- SourceLocation LBraceLoc = ConsumeBrace();
-
- if (Tok.getKind() == tok::r_brace)
- Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
-
- // Parse the enumerator-list.
- while (Tok.getKind() == tok::identifier) {
- ConsumeToken();
-
- if (Tok.getKind() == tok::equal) {
- ConsumeToken();
- ExprResult Res = ParseConstantExpression();
- if (Res.isInvalid) SkipUntil(tok::comma, true, false);
- }
-
- if (Tok.getKind() != tok::comma)
- break;
- SourceLocation CommaLoc = ConsumeToken();
-
- if (Tok.getKind() != tok::identifier && !getLang().C99)
- Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
- }
-
- // Eat the }.
- MatchRHSPunctuation(tok::r_brace, LBraceLoc);
-
- // If attributes exist after the identifier list, parse them.
- if (Tok.getKind() == tok::kw___attribute)
- ParseAttributes();
- }
+ if (Tok.getKind() == tok::l_brace)
+ ParseEnumBody(StartLoc, TagDecl);
+
// TODO: semantic analysis on the declspec for enums.
-
-
const char *PrevSpec = 0;
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, TagDecl))
Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
}
+/// ParseEnumBody - Parse a {} enclosed enumerator-list.
+/// enumerator-list:
+/// enumerator
+/// enumerator-list ',' enumerator
+/// enumerator:
+/// enumeration-constant
+/// enumeration-constant '=' constant-expression
+/// enumeration-constant:
+/// identifier
+///
+void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
+ SourceLocation LBraceLoc = ConsumeBrace();
+
+ if (Tok.getKind() == tok::r_brace)
+ Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
+
+ SmallVector<DeclTy*, 32> EnumConstantDecls;
+
+ // Parse the enumerator-list.
+ while (Tok.getKind() == tok::identifier) {
+ IdentifierInfo *Ident = Tok.getIdentifierInfo();
+ SourceLocation IdentLoc = ConsumeToken();
+
+ SourceLocation EqualLoc;
+ ExprTy *AssignedVal = 0;
+ if (Tok.getKind() == tok::equal) {
+ EqualLoc = ConsumeToken();
+ ExprResult Res = ParseConstantExpression();
+ if (Res.isInvalid)
+ SkipUntil(tok::comma, true, false);
+ else
+ AssignedVal = Res.Val;
+ }
+
+ // Install the enumerator constant into EnumDecl.
+ DeclTy *ConstDecl = Actions.ParseEnumConstant(CurScope, EnumDecl,
+ IdentLoc, Ident,
+ EqualLoc, AssignedVal);
+ EnumConstantDecls.push_back(ConstDecl);
+
+ if (Tok.getKind() != tok::comma)
+ break;
+ SourceLocation CommaLoc = ConsumeToken();
+
+ if (Tok.getKind() != tok::identifier && !getLang().C99)
+ Diag(CommaLoc, diag::ext_c99_enumerator_list_comma);
+ }
+
+ // Eat the }.
+ MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+ Actions.ParseEnumBody(StartLoc, EnumDecl, &EnumConstantDecls[0],
+ EnumConstantDecls.size());
+
+ // If attributes exist after the identifier list, parse them.
+ if (Tok.getKind() == tok::kw___attribute)
+ ParseAttributes();
+}
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.