[cfe-commits] r39644 - in /cfe/cfe/trunk: AST/Decl.cpp AST/Expr.cpp Parse/ParseDecl.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/Decl.h include/clang/Parse/Action.h

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:46:35 PDT 2007


Author: clattner
Date: Wed Jul 11 11:46:35 2007
New Revision: 39644

URL: http://llvm.org/viewvc/llvm-project?rev=39644&view=rev
Log:
Implement capturing of enum values and chaining of enums together.

Modified:
    cfe/cfe/trunk/AST/Decl.cpp
    cfe/cfe/trunk/AST/Expr.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

Modified: cfe/cfe/trunk/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Decl.cpp?rev=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Decl.cpp (original)
+++ cfe/cfe/trunk/AST/Decl.cpp Wed Jul 11 11:46:35 2007
@@ -136,21 +136,6 @@
 }
 
 
-/// 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/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:46:35 2007
@@ -206,6 +206,9 @@
 
 /// 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()) {

Modified: cfe/cfe/trunk/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Parse/ParseDecl.cpp?rev=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:46:35 2007
@@ -770,6 +770,8 @@
   
   SmallVector<DeclTy*, 32> EnumConstantDecls;
 
+  DeclTy *LastEnumConstDecl = 0;
+  
   // Parse the enumerator-list.
   while (Tok.getKind() == tok::identifier) {
     IdentifierInfo *Ident = Tok.getIdentifierInfo();
@@ -787,10 +789,12 @@
     }
     
     // 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;

Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:46:35 2007
@@ -116,6 +116,7 @@
   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,

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:46:35 2007
@@ -849,10 +849,14 @@
   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 @@
       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 @@
   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) {

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=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:46:35 2007
@@ -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 @@
 /// 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 @@
 /// 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;

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=39644&r1=39643&r2=39644&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:46:35 2007
@@ -169,6 +169,7 @@
                                DeclTy **Fields, unsigned NumFields) {}
 
   virtual DeclTy *ParseEnumConstant(Scope *S, DeclTy *EnumDecl,
+                                    DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
                                     SourceLocation EqualLoc, ExprTy *Val) {
     return 0;





More information about the cfe-commits mailing list