[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