summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-01-25 07:29:02 +0000
committerChris Lattner <sabre@nondot.org>2007-01-25 07:29:02 +0000
commitc1915e2052f5874d030953e01adbf565cbf74b26 (patch)
tree4c913da5a185ff47579cdb5a32cfbd328ab4cb9c /clang
parent5f521506aa4689aceb62d425806821e184a39fbe (diff)
downloadbcm5719-llvm-c1915e2052f5874d030953e01adbf565cbf74b26.tar.gz
bcm5719-llvm-c1915e2052f5874d030953e01adbf565cbf74b26.zip
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
Diffstat (limited to 'clang')
-rw-r--r--clang/AST/Decl.cpp15
-rw-r--r--clang/AST/Sema.h5
-rw-r--r--clang/AST/SemaDecl.cpp31
-rw-r--r--clang/Parse/ParseDecl.cpp101
-rw-r--r--clang/Sema/Sema.h5
-rw-r--r--clang/Sema/SemaDecl.cpp31
-rw-r--r--clang/include/clang/AST/Decl.h41
-rw-r--r--clang/include/clang/Parse/Action.h9
-rw-r--r--clang/include/clang/Parse/Parser.h1
9 files changed, 179 insertions, 60 deletions
diff --git a/clang/AST/Decl.cpp b/clang/AST/Decl.cpp
index 11d92055c11..7e8cea9ae07 100644
--- a/clang/AST/Decl.cpp
+++ b/clang/AST/Decl.cpp
@@ -47,6 +47,21 @@ void FunctionDecl::setParams(VarDecl **NewParamInfo, unsigned NumParams) {
}
+/// defineElements - When created, EnumDecl correspond to a forward declared
+/// enum. This method is used to mark the decl as being defined, with the
+/// specified contents.
+void EnumDecl::defineElements(EnumConstantDecl **Elts, unsigned NumElts) {
+ assert(!isDefinition() && "Cannot redefine enums!");
+ setDefinition(true);
+ NumElements = NumElts;
+ if (NumElts) {
+ Elements = new EnumConstantDecl*[NumElts];
+ memcpy(Elements, Elts, NumElts*sizeof(Decl*));
+ }
+}
+
+
+
/// defineBody - When created, RecordDecl's correspond to a forward declared
/// record. This method is used to mark the decl as being defined, with the
/// specified contents.
diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h
index cc13aa8f467..b7642efc64d 100644
--- a/clang/AST/Sema.h
+++ b/clang/AST/Sema.h
@@ -90,6 +90,11 @@ public:
Declarator &D, ExprTy *BitfieldWidth);
virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
DeclTy **Fields, unsigned NumFields);
+ virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val);
+ virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
+ DeclTy **Elements, unsigned NumElements);
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp
index b0f80c84390..14558bb3eae 100644
--- a/clang/AST/SemaDecl.cpp
+++ b/clang/AST/SemaDecl.cpp
@@ -316,7 +316,6 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
// Okay, this is definition of a previously declared or referenced tag.
// Move the location of the decl to be the definition site.
PrevDecl->setLocation(NameLoc);
- //PrevDecl->setDefinition(true);
return PrevDecl;
}
}
@@ -337,8 +336,7 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
case Decl::Enum:
New = new EnumDecl(Loc, Name);
// If this is an undefined enum, warn.
- if (TK != TK_Definition)
- Diag(Loc, diag::ext_forward_ref_enum);
+ if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
break;
case Decl::Union:
case Decl::Struct:
@@ -387,7 +385,7 @@ Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
DeclTy **Fields, unsigned NumFields) {
- RecordDecl *Record = cast<RecordDecl>(static_cast<TagDecl*>(RecDecl));
+ RecordDecl *Record = cast<RecordDecl>(static_cast<Decl*>(RecDecl));
if (Record->isDefinition()) {
// Diagnose code like:
// struct S { struct S {} X; };
@@ -478,4 +476,29 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
Record->defineBody(&RecFields[0], RecFields.size());
}
+Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val) {
+ EnumDecl *TheEnumDecl = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+ TypeRef Ty = Context.getTagDeclType(TheEnumDecl);
+ return new EnumConstantDecl(IdLoc, Id, Ty);
+}
+
+void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
+ DeclTy **Elements, unsigned NumElements) {
+ EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+ assert(!Enum->isDefinition() && "Enum redefinitions can't reach here");
+
+ // Verify that all the values are okay.
+ SmallVector<EnumConstantDecl*, 32> Values;
+ for (unsigned i = 0; i != NumElements; ++i) {
+ EnumConstantDecl *ECD =
+ cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ Values.push_back(ECD);
+ }
+
+ Enum->defineElements(&Values[0], Values.size());
+}
diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp
index 7dbba29575c..781d09b7bc0 100644
--- a/clang/Parse/ParseDecl.cpp
+++ b/clang/Parse/ParseDecl.cpp
@@ -579,10 +579,10 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
}
}
- 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,6 +597,25 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
/// '}' attributes[opt]
/// 'enum' identifier
/// [GNU] 'enum' attributes[opt] identifier
+void Parser::ParseEnumSpecifier(DeclSpec &DS) {
+ assert(Tok.getKind() == tok::kw_enum && "Not an enum specifier");
+ SourceLocation StartLoc = ConsumeToken();
+
+ // Parse the tag portion of this.
+ DeclTy *TagDecl;
+ if (ParseTag(TagDecl, DeclSpec::TST_enum, StartLoc))
+ return;
+
+ 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
@@ -606,55 +625,55 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
/// enumeration-constant:
/// identifier
///
-void Parser::ParseEnumSpecifier(DeclSpec &DS) {
- assert(Tok.getKind() == tok::kw_enum && "Not an enum specifier");
- SourceLocation StartLoc = ConsumeToken();
+void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
+ SourceLocation LBraceLoc = ConsumeBrace();
- // Parse the tag portion of this.
- DeclTy *TagDecl;
- if (ParseTag(TagDecl, DeclSpec::TST_enum, StartLoc))
- return;
+ if (Tok.getKind() == tok::r_brace)
+ Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
- if (Tok.getKind() == tok::l_brace) {
- 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();
- // 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);
+ 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;
}
- // Eat the }.
- MatchRHSPunctuation(tok::r_brace, LBraceLoc);
-
- // If attributes exist after the identifier list, parse them.
- if (Tok.getKind() == tok::kw___attribute)
- ParseAttributes();
+ // 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);
}
- // TODO: semantic analysis on the declspec for enums.
+ // Eat the }.
+ MatchRHSPunctuation(tok::r_brace, LBraceLoc);
+
+ Actions.ParseEnumBody(StartLoc, EnumDecl, &EnumConstantDecls[0],
+ EnumConstantDecls.size());
- const char *PrevSpec = 0;
- if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, TagDecl))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination, PrevSpec);
+ // 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.
bool Parser::isTypeSpecifierQualifier() const {
diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h
index cc13aa8f467..b7642efc64d 100644
--- a/clang/Sema/Sema.h
+++ b/clang/Sema/Sema.h
@@ -90,6 +90,11 @@ public:
Declarator &D, ExprTy *BitfieldWidth);
virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
DeclTy **Fields, unsigned NumFields);
+ virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val);
+ virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
+ DeclTy **Elements, unsigned NumElements);
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks: SemaStmt.cpp.
diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp
index b0f80c84390..14558bb3eae 100644
--- a/clang/Sema/SemaDecl.cpp
+++ b/clang/Sema/SemaDecl.cpp
@@ -316,7 +316,6 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
// Okay, this is definition of a previously declared or referenced tag.
// Move the location of the decl to be the definition site.
PrevDecl->setLocation(NameLoc);
- //PrevDecl->setDefinition(true);
return PrevDecl;
}
}
@@ -337,8 +336,7 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
case Decl::Enum:
New = new EnumDecl(Loc, Name);
// If this is an undefined enum, warn.
- if (TK != TK_Definition)
- Diag(Loc, diag::ext_forward_ref_enum);
+ if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
break;
case Decl::Union:
case Decl::Struct:
@@ -387,7 +385,7 @@ Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
DeclTy **Fields, unsigned NumFields) {
- RecordDecl *Record = cast<RecordDecl>(static_cast<TagDecl*>(RecDecl));
+ RecordDecl *Record = cast<RecordDecl>(static_cast<Decl*>(RecDecl));
if (Record->isDefinition()) {
// Diagnose code like:
// struct S { struct S {} X; };
@@ -478,4 +476,29 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
Record->defineBody(&RecFields[0], RecFields.size());
}
+Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val) {
+ EnumDecl *TheEnumDecl = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+ TypeRef Ty = Context.getTagDeclType(TheEnumDecl);
+ return new EnumConstantDecl(IdLoc, Id, Ty);
+}
+
+void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
+ DeclTy **Elements, unsigned NumElements) {
+ EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
+ assert(!Enum->isDefinition() && "Enum redefinitions can't reach here");
+
+ // Verify that all the values are okay.
+ SmallVector<EnumConstantDecl*, 32> Values;
+ for (unsigned i = 0; i != NumElements; ++i) {
+ EnumConstantDecl *ECD =
+ cast_or_null<EnumConstantDecl>(static_cast<Decl*>(Elements[i]));
+ if (!ECD) continue; // Already issued a diagnostic.
+
+ Values.push_back(ECD);
+ }
+
+ Enum->defineElements(&Values[0], Values.size());
+}
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 1f12c62a1db..6b6be92d227 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -20,6 +20,7 @@
namespace llvm {
namespace clang {
class IdentifierInfo;
+class Expr;
class Stmt;
class FunctionDecl;
@@ -29,7 +30,7 @@ class FunctionDecl;
class Decl {
public:
enum Kind {
- Typedef, Function, Variable, Field,
+ Typedef, Function, Variable, Field, EnumConstant,
Struct, Union, Class, Enum
};
@@ -189,7 +190,6 @@ public:
/// FunctionDecl - An instance of this class is created to represent a function
/// declaration or definition.
class FieldDecl : public ObjectDecl {
-
public:
FieldDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
: ObjectDecl(Field, L, Id, T) {}
@@ -201,6 +201,26 @@ public:
static bool classof(const FieldDecl *D) { return true; }
};
+/// EnumConstantDecl - An instance of this object exists for each enum constant
+/// that is defined. For example, in "enum X {a,b}", each of a/b are
+/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
+/// TaggedType for the X EnumDecl.
+class EnumConstantDecl : public ObjectDecl {
+public:
+ // FIXME: Capture value info.
+ EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, TypeRef T)
+ : ObjectDecl(EnumConstant, L, Id, T) {}
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == EnumConstant;
+ }
+ static bool classof(const EnumConstantDecl *D) { return true; }
+
+};
+
+
+
/// TagDecl - Represents the declaration of a struct/union/class/enum.
class TagDecl : public Decl {
/// IsDefinition - True if this is a definition ("struct foo {};"), false if
@@ -240,19 +260,20 @@ protected:
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
/// enums.
class EnumDecl : public TagDecl {
- /// Fields/NumFields - This is a new[]'d array of pointers to Decls.
- //Decl **Fields; // Null if not defined.
- //int NumFields; // -1 if not defined.
+ /// Elements/NumElements - This is a new[]'d array of pointers to
+ /// EnumConstantDecls.
+ EnumConstantDecl **Elements; // Null if not defined.
+ int NumElements; // -1 if not defined.
public:
EnumDecl(SourceLocation L, IdentifierInfo *Id) : TagDecl(Enum, L, Id) {
- //Fields = 0;
- //NumFields = -1;
+ Elements = 0;
+ NumElements = -1;
}
- /// defineBody - When created, RecordDecl's correspond to a forward declared
- /// record. This method is used to mark the decl as being defined, with the
+ /// defineElements - When created, EnumDecl correspond to a forward declared
+ /// enum. This method is used to mark the decl as being defined, with the
/// specified contents.
- //void defineBody(Decl **fields, unsigned numFields);
+ void defineElements(EnumConstantDecl **Elements, unsigned NumElements);
static bool classof(const Decl *D) {
return D->getKind() == Enum;
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index ebc31c04d95..13a49efbb80 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -160,7 +160,14 @@ public:
virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
DeclTy **Fields, unsigned NumFields) {}
-
+ virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
+ SourceLocation IdLoc, IdentifierInfo *Id,
+ SourceLocation EqualLoc, ExprTy *Val) {
+ return 0;
+ }
+ virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
+ DeclTy **Elements, unsigned NumElements) {}
+
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks.
//===--------------------------------------------------------------------===//
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 21499228423..6368a651425 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -333,6 +333,7 @@ private:
bool ParseTag(DeclTy *&Decl, unsigned TagType, SourceLocation StartLoc);
void ParseEnumSpecifier(DeclSpec &DS);
+ void ParseEnumBody(SourceLocation StartLoc, DeclTy *TagDecl);
void ParseStructUnionSpecifier(DeclSpec &DS);
void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
DeclTy *TagDecl);
OpenPOWER on IntegriCloud