mirror of
https://github.com/intel/llvm.git
synced 2026-02-02 10:08:59 +08:00
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
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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,15 +597,6 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
|
||||
/// '}' 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 @@ void Parser::ParseEnumSpecifier(DeclSpec &DS) {
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user