[cfe-commits] r39300 - in /cfe/cfe/trunk: AST/Decl.cpp AST/Sema.h AST/SemaDecl.cpp Parse/ParseDecl.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/Decl.h include/clang/Parse/Action.h include/clang/Parse/Parser.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:42:43 PDT 2007
Author: sabre
Date: Wed Jul 11 11:42:42 2007
New Revision: 39300
URL: http://llvm.org/viewvc/llvm-project?rev=39300&view=rev
Log:
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.
Modified:
cfe/cfe/trunk/AST/Decl.cpp
cfe/cfe/trunk/AST/Sema.h
cfe/cfe/trunk/AST/SemaDecl.cpp
cfe/cfe/trunk/Parse/ParseDecl.cpp
cfe/cfe/trunk/Sema/Sema.h
cfe/cfe/trunk/Sema/SemaDecl.cpp
cfe/cfe/trunk/include/clang/AST/Decl.h
cfe/cfe/trunk/include/clang/Parse/Action.h
cfe/cfe/trunk/include/clang/Parse/Parser.h
Modified: cfe/cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Decl.cpp?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Decl.cpp (original)
+++ cfe/cfe/trunk/AST/Decl.cpp Wed Jul 11 11:42:42 2007
@@ -47,6 +47,21 @@
}
+/// 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.
Modified: cfe/cfe/trunk/AST/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Sema.h?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:42:42 2007
@@ -90,6 +90,11 @@
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.
Modified: cfe/cfe/trunk/AST/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaDecl.cpp?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:42:42 2007
@@ -316,7 +316,6 @@
// 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 @@
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 @@
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 @@
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());
+}
Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:42:42 2007
@@ -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,6 +597,25 @@
/// '}' 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 @@
/// 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();
+ 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;
+ }
- if (Tok.getKind() == tok::r_brace)
- Diag(Tok, diag::ext_empty_struct_union_enum, "enum");
+ // Install the enumerator constant into EnumDecl.
+ DeclTy *ConstDecl = Actions.ParseEnumConstant(CurScope, EnumDecl,
+ IdentLoc, Ident,
+ EqualLoc, AssignedVal);
+ EnumConstantDecls.push_back(ConstDecl);
- // 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);
- }
+ if (Tok.getKind() != tok::comma)
+ break;
+ SourceLocation CommaLoc = ConsumeToken();
- // 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::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 {
Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:42:42 2007
@@ -90,6 +90,11 @@
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.
Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:42:42 2007
@@ -316,7 +316,6 @@
// 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 @@
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 @@
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 @@
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());
+}
Modified: cfe/cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Decl.h?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:42:42 2007
@@ -20,6 +20,7 @@
namespace llvm {
namespace clang {
class IdentifierInfo;
+class Expr;
class Stmt;
class FunctionDecl;
@@ -29,7 +30,7 @@
class Decl {
public:
enum Kind {
- Typedef, Function, Variable, Field,
+ Typedef, Function, Variable, Field, EnumConstant,
Struct, Union, Class, Enum
};
@@ -189,7 +190,6 @@
/// 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 @@
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 @@
/// 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;
Modified: cfe/cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Action.h?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:42:42 2007
@@ -160,7 +160,14 @@
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.
//===--------------------------------------------------------------------===//
Modified: cfe/cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Parse/Parser.h?rev=39300&r1=39299&r2=39300&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:42:42 2007
@@ -333,6 +333,7 @@
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);
More information about the cfe-commits
mailing list