[cfe-commits] r39292 - in /cfe/cfe/trunk: AST/Sema.h AST/SemaDecl.cpp Parse/ParseDecl.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/Decl.h include/clang/Basic/DiagnosticKinds.def 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:35 PDT 2007


Author: sabre
Date: Wed Jul 11 11:42:35 2007
New Revision: 39292

URL: http://llvm.org/viewvc/llvm-project?rev=39292&view=rev
Log:
create field decl objects for the members of a struct/union.  Diagnose code
like:
struct S { struct S {} X; };

with:
t.c:2:19: error: nested redefinition of 'struct'
struct S { struct S {} X; };
                  ^
t.c:2:1: error: previous definition is here
struct S { struct S {} X; };
^

Modified:
    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/Basic/DiagnosticKinds.def
    cfe/cfe/trunk/include/clang/Parse/Action.h
    cfe/cfe/trunk/include/clang/Parse/Parser.h

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

==============================================================================
--- cfe/cfe/trunk/AST/Sema.h (original)
+++ cfe/cfe/trunk/AST/Sema.h Wed Jul 11 11:42:35 2007
@@ -86,7 +86,11 @@
   virtual DeclTy *ParseTag(Scope *S, unsigned TagType, TagKind TK,
                            SourceLocation KWLoc, IdentifierInfo *Name,
                            SourceLocation NameLoc);
-    
+  virtual DeclTy *ParseField(Scope *S, DeclTy *TagDecl,SourceLocation DeclStart,
+                             Declarator &D, ExprTy *BitfieldWidth);
+  virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
+                               DeclTy **Fields, unsigned NumFields);
+  
   //===--------------------------------------------------------------------===//
   // 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=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/AST/SemaDecl.cpp Wed Jul 11 11:42:35 2007
@@ -14,6 +14,7 @@
 #include "Sema.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Parse/Scope.h"
@@ -263,10 +264,10 @@
 }
 
 
-/// ParseStructUnionTag - This is invoked when we see 'struct foo' or
-/// 'struct {'.  In the former case, Name will be non-null.  In the later case,
-/// Name will be null.  TagType indicates what kind of tag this is. TK indicates
-/// whether this is a reference/declaration/definition of a tag.
+/// ParseTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
+/// former case, Name will be non-null.  In the later case, Name will be null.
+/// TagType indicates what kind of tag this is. TK indicates whether this is a
+/// reference/declaration/definition of a tag.
 Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
                              SourceLocation KWLoc, IdentifierInfo *Name,
                              SourceLocation NameLoc) {
@@ -315,7 +316,7 @@
         // 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);
+        //PrevDecl->setDefinition(true);
         return PrevDecl;
       }
     }
@@ -336,8 +337,8 @@
   else
     assert(0 && "Enum tags not implemented yet!");
   
-  if (TK == TK_Definition)
-    New->setDefinition(true);
+  //if (TK == TK_Definition)
+  //  New->setDefinition(true);
   
   // If this has an identifier, add it to the scope stack.
   if (Name) {
@@ -348,3 +349,50 @@
   
   return New;
 }
+
+/// ParseField - Each field of a struct/union/class is passed into this in order
+/// to create a FieldDecl object for it.
+Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
+                               SourceLocation DeclStart, 
+                               Declarator &D, ExprTy *BitfieldWidth) {
+  IdentifierInfo *II = D.getIdentifier();
+  Expr *BitWidth = (Expr*)BitfieldWidth;
+  
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+  
+  if (BitWidth) {
+    // TODO: Validate.
+    assert(0 && "bitfields unimp");
+    
+    // 6.7.2.1p3
+    // 6.7.2.1p4
+    
+  } else {
+    // Not a bitfield.
+
+    // validate II.
+    
+  }
+  
+  return new FieldDecl(Loc, II, GetTypeForDeclarator(D, S));
+}
+
+void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
+                           DeclTy **Fields, unsigned NumFields) {
+  TagDecl *Record = static_cast<TagDecl*>(RecDecl);
+  if (Record->isDefinition()) {
+    // Diagnose code like:
+    // struct S { struct S {} X; };
+    // We discover this when we complete the outer S.  Reject and ignore the
+    // outer S.
+    Diag(Record->getLocation(), diag::err_nested_redefinition,
+         Record->getKindName());
+    Diag(RecLoc, diag::err_previous_definition);
+    return;
+  }
+  
+  Record->setDefinition(true);
+}
+
+

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

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:42:35 2007
@@ -453,7 +453,7 @@
   
   // If there is a body, parse it and inform the actions module.
   if (Tok.getKind() == tok::l_brace)
-    ParseStructUnionBody(TagType, TagDecl);
+    ParseStructUnionBody(StartLoc, TagType, TagDecl);
 
   const char *PrevSpec = 0;
   if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagDecl))
@@ -484,7 +484,8 @@
 ///         declarator[opt] ':' constant-expression
 /// [GNU]   declarator[opt] ':' constant-expression attributes[opt]
 ///
-void Parser::ParseStructUnionBody(unsigned TagType, DeclTy *TagDecl) {
+void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
+                                  unsigned TagType, DeclTy *TagDecl) {
   SourceLocation LBraceLoc = ConsumeBrace();
   
   // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
@@ -493,6 +494,8 @@
     Diag(Tok, diag::ext_empty_struct_union_enum, 
          DeclSpec::getSpecifierName((DeclSpec::TST)TagType));
 
+  SmallVector<DeclTy*, 32> FieldDecls;
+  
   // While we still have something to read, read the declarations in the struct.
   while (Tok.getKind() != tok::r_brace && 
          Tok.getKind() != tok::eof) {
@@ -537,7 +540,9 @@
         ParseAttributes();
       
       // Install the declarator into the current TagDecl.
-      Actions.ParseField(TagDecl, DeclaratorInfo, BitfieldSize);
+      DeclTy *Field = Actions.ParseField(CurScope, TagDecl, SpecQualLoc,
+                                         DeclaratorInfo, BitfieldSize);
+      FieldDecls.push_back(Field);
       
       // If we don't have a comma, it is either the end of the list (a ';')
       // or an error, bail out.
@@ -564,6 +569,8 @@
     }
   }
   
+  Actions.ParseRecordBody(RecordLoc, TagDecl, &FieldDecls[0],FieldDecls.size());
+  
   MatchRHSPunctuation(tok::r_brace, LBraceLoc);
   
   // If attributes exist after struct contents, parse them.

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

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:42:35 2007
@@ -86,7 +86,11 @@
   virtual DeclTy *ParseTag(Scope *S, unsigned TagType, TagKind TK,
                            SourceLocation KWLoc, IdentifierInfo *Name,
                            SourceLocation NameLoc);
-    
+  virtual DeclTy *ParseField(Scope *S, DeclTy *TagDecl,SourceLocation DeclStart,
+                             Declarator &D, ExprTy *BitfieldWidth);
+  virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
+                               DeclTy **Fields, unsigned NumFields);
+  
   //===--------------------------------------------------------------------===//
   // 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=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:42:35 2007
@@ -14,6 +14,7 @@
 #include "Sema.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Parse/Scope.h"
@@ -263,10 +264,10 @@
 }
 
 
-/// ParseStructUnionTag - This is invoked when we see 'struct foo' or
-/// 'struct {'.  In the former case, Name will be non-null.  In the later case,
-/// Name will be null.  TagType indicates what kind of tag this is. TK indicates
-/// whether this is a reference/declaration/definition of a tag.
+/// ParseTag - This is invoked when we see 'struct foo' or 'struct {'.  In the
+/// former case, Name will be non-null.  In the later case, Name will be null.
+/// TagType indicates what kind of tag this is. TK indicates whether this is a
+/// reference/declaration/definition of a tag.
 Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
                              SourceLocation KWLoc, IdentifierInfo *Name,
                              SourceLocation NameLoc) {
@@ -315,7 +316,7 @@
         // 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);
+        //PrevDecl->setDefinition(true);
         return PrevDecl;
       }
     }
@@ -336,8 +337,8 @@
   else
     assert(0 && "Enum tags not implemented yet!");
   
-  if (TK == TK_Definition)
-    New->setDefinition(true);
+  //if (TK == TK_Definition)
+  //  New->setDefinition(true);
   
   // If this has an identifier, add it to the scope stack.
   if (Name) {
@@ -348,3 +349,50 @@
   
   return New;
 }
+
+/// ParseField - Each field of a struct/union/class is passed into this in order
+/// to create a FieldDecl object for it.
+Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl,
+                               SourceLocation DeclStart, 
+                               Declarator &D, ExprTy *BitfieldWidth) {
+  IdentifierInfo *II = D.getIdentifier();
+  Expr *BitWidth = (Expr*)BitfieldWidth;
+  
+  SourceLocation Loc = DeclStart;
+  if (II) Loc = D.getIdentifierLoc();
+  
+  if (BitWidth) {
+    // TODO: Validate.
+    assert(0 && "bitfields unimp");
+    
+    // 6.7.2.1p3
+    // 6.7.2.1p4
+    
+  } else {
+    // Not a bitfield.
+
+    // validate II.
+    
+  }
+  
+  return new FieldDecl(Loc, II, GetTypeForDeclarator(D, S));
+}
+
+void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
+                           DeclTy **Fields, unsigned NumFields) {
+  TagDecl *Record = static_cast<TagDecl*>(RecDecl);
+  if (Record->isDefinition()) {
+    // Diagnose code like:
+    // struct S { struct S {} X; };
+    // We discover this when we complete the outer S.  Reject and ignore the
+    // outer S.
+    Diag(Record->getLocation(), diag::err_nested_redefinition,
+         Record->getKindName());
+    Diag(RecLoc, diag::err_previous_definition);
+    return;
+  }
+  
+  Record->setDefinition(true);
+}
+
+

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=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:42:35 2007
@@ -29,7 +29,7 @@
 class Decl {
 public:
   enum Kind {
-    Typedef, Function, Variable,
+    Typedef, Function, Variable, Field,
     Struct, Union, Class, Enum
   };
 
@@ -185,6 +185,17 @@
   static bool classof(const FunctionDecl *D) { return true; }
 };
 
+
+/// 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) {}
+  
+};
+
 /// 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

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:42:35 2007
@@ -427,6 +427,8 @@
      "use of undeclared identifier '%s'")
 DIAG(err_redefinition, ERROR,
      "redefinition of '%s'")
+DIAG(err_nested_redefinition, ERROR,
+     "nested redefinition of '%s'")
 DIAG(err_use_with_wrong_tag, ERROR,
      "use of '%s' with tag type that does not match previous declaration")
 

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=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:42:35 2007
@@ -153,8 +153,13 @@
     return 0;
   }
   
-  virtual void ParseField(DeclTy *TagDecl, Declarator &D,
-                          ExprTy *BitfieldWidth) {}
+  virtual DeclTy *ParseField(Scope *S, DeclTy *TagDecl,SourceLocation DeclStart,
+                             Declarator &D, ExprTy *BitfieldWidth) {
+    return 0;
+  }
+  virtual void ParseRecordBody(SourceLocation RecLoc, DeclTy *TagDecl,
+                               DeclTy **Fields, unsigned NumFields) {}
+
   
   //===--------------------------------------------------------------------===//
   // 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=39292&r1=39291&r2=39292&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Parser.h Wed Jul 11 11:42:35 2007
@@ -333,7 +333,8 @@
 
   void ParseEnumSpecifier(DeclSpec &DS);
   void ParseStructUnionSpecifier(DeclSpec &DS);
-  void ParseStructUnionBody(unsigned TagType, DeclTy *TagDecl);
+  void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType,
+                            DeclTy *TagDecl);
 
   bool isDeclarationSpecifier() const;
   bool isTypeSpecifierQualifier() const;





More information about the cfe-commits mailing list