mirror of
https://github.com/intel/llvm.git
synced 2026-02-02 10:08:59 +08:00
Implement capturing of enum values and chaining of enums together.
llvm-svn: 39644
This commit is contained in:
@@ -136,21 +136,6 @@ 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.
|
||||
|
||||
@@ -206,6 +206,9 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue() {
|
||||
|
||||
/// FIXME: Pass up a reason why! Invalid operation in i-c-e, division by zero,
|
||||
/// comma, etc
|
||||
///
|
||||
/// FIXME: This should ext-warn on overflow during evaluation! ISO C does not
|
||||
/// permit this.
|
||||
bool Expr::isIntegerConstantExpr(APSInt &Result, SourceLocation *Loc,
|
||||
bool isEvaluated) const {
|
||||
switch (getStmtClass()) {
|
||||
|
||||
@@ -770,6 +770,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
|
||||
|
||||
SmallVector<DeclTy*, 32> EnumConstantDecls;
|
||||
|
||||
DeclTy *LastEnumConstDecl = 0;
|
||||
|
||||
// Parse the enumerator-list.
|
||||
while (Tok.getKind() == tok::identifier) {
|
||||
IdentifierInfo *Ident = Tok.getIdentifierInfo();
|
||||
@@ -787,10 +789,12 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
|
||||
}
|
||||
|
||||
// Install the enumerator constant into EnumDecl.
|
||||
DeclTy *ConstDecl = Actions.ParseEnumConstant(CurScope, EnumDecl,
|
||||
IdentLoc, Ident,
|
||||
EqualLoc, AssignedVal);
|
||||
EnumConstantDecls.push_back(ConstDecl);
|
||||
DeclTy *EnumConstDecl = Actions.ParseEnumConstant(CurScope, EnumDecl,
|
||||
LastEnumConstDecl,
|
||||
IdentLoc, Ident,
|
||||
EqualLoc, AssignedVal);
|
||||
EnumConstantDecls.push_back(EnumConstDecl);
|
||||
LastEnumConstDecl = EnumConstDecl;
|
||||
|
||||
if (Tok.getKind() != tok::comma)
|
||||
break;
|
||||
|
||||
@@ -116,6 +116,7 @@ private:
|
||||
virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
|
||||
DeclTy **Fields, unsigned NumFields);
|
||||
virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
|
||||
DeclTy *LastEnumConstant,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
SourceLocation EqualLoc, ExprTy *Val);
|
||||
virtual void ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
|
||||
|
||||
@@ -849,10 +849,14 @@ void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
|
||||
Record->defineBody(&RecFields[0], RecFields.size());
|
||||
}
|
||||
|
||||
Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
|
||||
Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl,
|
||||
DeclTy *lastEnumConst,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
SourceLocation EqualLoc, ExprTy *Val) {
|
||||
EnumDecl *TheEnumDecl = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX));
|
||||
SourceLocation EqualLoc, ExprTy *val) {
|
||||
theEnumDecl = theEnumDecl; // silence unused warning.
|
||||
EnumConstantDecl *LastEnumConst =
|
||||
cast_or_null<EnumConstantDecl>(static_cast<Decl*>(lastEnumConst));
|
||||
Expr *Val = static_cast<Expr*>(val);
|
||||
|
||||
// Verify that there isn't already something declared with this name in this
|
||||
// scope.
|
||||
@@ -863,19 +867,43 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX,
|
||||
else
|
||||
Diag(IdLoc, diag::err_redefinition, Id->getName());
|
||||
Diag(PrevDecl->getLocation(), diag::err_previous_definition);
|
||||
// FIXME: Don't leak memory: delete Val;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SourceLocation expLoc;
|
||||
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
|
||||
// FIXME: Capture this value in the enumconstantdecl.
|
||||
if (Val && !((Expr *)Val)->isIntegerConstantExpr(&expLoc)) {
|
||||
Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
|
||||
return 0;
|
||||
|
||||
APSInt EnumVal(32);
|
||||
QualType EltTy;
|
||||
if (Val) {
|
||||
// C99 6.7.2.2p2: Make sure we have an integer constant expression.
|
||||
SourceLocation ExpLoc;
|
||||
if (!Val->isIntegerConstantExpr(EnumVal, &ExpLoc)) {
|
||||
Diag(ExpLoc, diag::err_enum_value_not_integer_constant_expr,
|
||||
Id->getName());
|
||||
// FIXME: Don't leak memory: delete Val;
|
||||
return 0;
|
||||
}
|
||||
EltTy = Val->getType();
|
||||
} else if (LastEnumConst) {
|
||||
// Assign the last value + 1.
|
||||
EnumVal = LastEnumConst->getInitVal();
|
||||
++EnumVal;
|
||||
// FIXME: detect overflow!
|
||||
EltTy = LastEnumConst->getType();
|
||||
} else {
|
||||
// First value, set to zero.
|
||||
EltTy = Context.IntTy;
|
||||
// FIXME: Resize EnumVal to the size of int.
|
||||
}
|
||||
QualType Ty = Context.getTagDeclType(TheEnumDecl);
|
||||
// FIXME: Chain EnumConstantDecl's together.
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val, 0);
|
||||
|
||||
// TODO: Default promotions to int/uint.
|
||||
|
||||
// TODO: If the result value doesn't fit in an int, it must be a long or long
|
||||
// long value. ISO C does not support this, but GCC does as an extension,
|
||||
// emit a warning.
|
||||
|
||||
EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, EltTy, Val, EnumVal,
|
||||
LastEnumConst);
|
||||
|
||||
// Register this decl in the current scope stack.
|
||||
New->setNext(Id->getFETokenInfo<Decl>());
|
||||
@@ -889,17 +917,18 @@ void Sema::ParseEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
||||
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;
|
||||
// Verify that all the values are okay, and reverse the list.
|
||||
EnumConstantDecl *EltList = 0;
|
||||
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);
|
||||
|
||||
ECD->setNextDeclarator(EltList);
|
||||
EltList = ECD;
|
||||
}
|
||||
|
||||
Enum->defineElements(&Values[0], Values.size());
|
||||
Enum->defineElements(EltList);
|
||||
}
|
||||
|
||||
void Sema::AddTopLevelDecl(Decl *current, Decl *last) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace clang {
|
||||
@@ -274,11 +275,16 @@ public:
|
||||
/// TagType for the X EnumDecl.
|
||||
class EnumConstantDecl : public ValueDecl {
|
||||
Expr *Init; // an integer constant expression
|
||||
APSInt Val; // The value.
|
||||
public:
|
||||
EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E,
|
||||
Decl *PrevDecl)
|
||||
: ValueDecl(EnumConstant, L, Id, T, PrevDecl), Init(E) {}
|
||||
const APSInt &V, Decl *PrevDecl)
|
||||
: ValueDecl(EnumConstant, L, Id, T, PrevDecl), Init(E), Val(V) {}
|
||||
|
||||
const Expr *getInitExpr() const { return Init; }
|
||||
Expr *getInitExpr() { return Init; }
|
||||
const APSInt &getInitVal() const { return Val; }
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == EnumConstant;
|
||||
@@ -363,21 +369,23 @@ protected:
|
||||
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
|
||||
/// enums.
|
||||
class EnumDecl : public TagDecl {
|
||||
/// Elements/NumElements - This is a new[]'d array of pointers to
|
||||
/// EnumConstantDecls.
|
||||
EnumConstantDecl **Elements; // Null if not defined.
|
||||
int NumElements; // -1 if not defined.
|
||||
/// ElementList - this is a linked list of EnumConstantDecl's which are linked
|
||||
/// together through their getNextDeclarator pointers.
|
||||
EnumConstantDecl *ElementList;
|
||||
public:
|
||||
EnumDecl(SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
|
||||
: TagDecl(Enum, L, Id, PrevDecl) {
|
||||
Elements = 0;
|
||||
NumElements = -1;
|
||||
ElementList = 0;
|
||||
}
|
||||
|
||||
/// 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 defineElements(EnumConstantDecl **Elements, unsigned NumElements);
|
||||
/// specified list of enums.
|
||||
void defineElements(EnumConstantDecl *ListHead) {
|
||||
assert(!isDefinition() && "Cannot redefine enums!");
|
||||
ElementList = ListHead;
|
||||
setDefinition(true);
|
||||
}
|
||||
|
||||
static bool classof(const Decl *D) {
|
||||
return D->getKind() == Enum;
|
||||
|
||||
@@ -169,6 +169,7 @@ public:
|
||||
DeclTy **Fields, unsigned NumFields) {}
|
||||
|
||||
virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
|
||||
DeclTy *LastEnumConstant,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
SourceLocation EqualLoc, ExprTy *Val) {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user