[cfe-commits] r39623 - in /cfe/cfe/trunk: AST/StmtPrinter.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:21 PDT 2007


Author: clattner
Date: Wed Jul 11 11:46:21 2007
New Revision: 39623

URL: http://llvm.org/viewvc/llvm-project?rev=39623&view=rev
Log:
Finally break down and chain together decls that are defined with common declspecs,
like: int X, Y, Z;

This is required for the code gen to get to all of the declarations in a
DeclStmt, and should simplify some other code.

Modified:
    cfe/cfe/trunk/AST/StmtPrinter.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/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/StmtPrinter.cpp?rev=39623&r1=39622&r2=39623&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/StmtPrinter.cpp (original)
+++ cfe/cfe/trunk/AST/StmtPrinter.cpp Wed Jul 11 11:46:21 2007
@@ -124,9 +124,11 @@
 }
 
 void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
-  Indent();
-  PrintRawDecl(Node->getDecl());
-  OS << ";\n";
+  for (Decl *D = Node->getDecl(); D; D = D->getNextDeclarator()) {
+    Indent();
+    PrintRawDecl(D);
+    OS << ";\n";
+  }
 }
 
 void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {

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

==============================================================================
--- cfe/cfe/trunk/Parse/ParseDecl.cpp (original)
+++ cfe/cfe/trunk/Parse/ParseDecl.cpp Wed Jul 11 11:46:21 2007
@@ -279,15 +279,15 @@
   
   if (Tok.getKind() == tok::semi) {
     ConsumeToken();
-    return LastDeclInGroup;
-  } else {
-    Diag(Tok, diag::err_parse_error);
-    // Skip to end of block or statement
-    SkipUntil(tok::r_brace, true);
-    if (Tok.getKind() == tok::semi)
-      ConsumeToken();
-    return 0;
+    return Actions.FinalizeDeclaratorGroup(CurScope, LastDeclInGroup);
   }
+  
+  Diag(Tok, diag::err_parse_error);
+  // Skip to end of block or statement
+  SkipUntil(tok::r_brace, true);
+  if (Tok.getKind() == tok::semi)
+    ConsumeToken();
+  return 0;
 }
 
 /// ParseSpecifierQualifierList

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

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:46:21 2007
@@ -98,6 +98,8 @@
   virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
   virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
                                   DeclTy *LastInGroup);
+  virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group);
+
   virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
   virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
   virtual void PopScope(SourceLocation Loc, Scope *S);
@@ -120,7 +122,7 @@
                              DeclTy **Elements, unsigned NumElements);
 private:
   /// Subroutines of ParseDeclarator()...
-  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D);
+  TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, Decl *LastDeclarator);
   TypedefDecl *MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
   FunctionDecl *MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   VarDecl *MergeVarDecl(VarDecl *New, Decl *Old);

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:46:21 2007
@@ -155,7 +155,8 @@
   Builtin::ID BID = (Builtin::ID)bid;
 
   QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
-  FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R);
+  FunctionDecl *New = new FunctionDecl(SourceLocation(), II, R,
+                                       FunctionDecl::Extern, 0);
   
   // Find translation-unit scope to insert this function into.
   while (S->getParent())
@@ -270,20 +271,21 @@
   return 0;
 }
 
-Action::DeclTy *
+Sema::DeclTy *
 Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 
-                      DeclTy *LastInGroup) {
+                      DeclTy *lastDeclarator) {
+  Decl *LastDeclarator = (Decl*)lastDeclarator;
   IdentifierInfo *II = D.getIdentifier();
   
   // See if this is a redefinition of a variable in the same scope.
   Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
                                     D.getIdentifierLoc(), S);
-  if (!S->isDeclScope(PrevDecl))
+  if (PrevDecl && !S->isDeclScope(PrevDecl))
     PrevDecl = 0;   // If in outer scope, it isn't the same thing.
 
   Decl *New;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
-    TypedefDecl *NewTD = ParseTypedefDecl(S, D);
+    TypedefDecl *NewTD = ParseTypedefDecl(S, D, LastDeclarator);
     if (!NewTD) return 0;
     
     // Merge the decl with the existing one if appropriate.
@@ -317,7 +319,8 @@
       case DeclSpec::SCS_static:      SC = FunctionDecl::Static; break;
     }
 
-    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC);
+    FunctionDecl *NewFD = new FunctionDecl(D.getIdentifierLoc(), II, R, SC,
+                                           LastDeclarator);
     
     // Merge the decl with the existing one if appropriate.
     if (PrevDecl) {
@@ -368,7 +371,7 @@
         if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
           return 0;
       }
-      NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC);
+      NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
     } else { 
       // Block scope. C99 6.7p7: If an identifier for an object is declared with
       // no linkage (C99 6.2.2p6), the type for the object shall be complete...
@@ -387,7 +390,7 @@
             return 0;
         }
       }
-      NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC);
+      NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
     }    
     // Merge the decl with the existing one if appropriate.
     if (PrevDecl) {
@@ -406,11 +409,27 @@
   }
   
   if (S->getParent() == 0)
-    AddTopLevelDecl(New, (Decl *)LastInGroup);
+    AddTopLevelDecl(New, LastDeclarator);
   
   return New;
 }
 
+/// The declarators are chained together backwards, reverse the list.
+Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
+  // Often we have single declarators, handle them quickly.
+  Decl *Group = static_cast<Decl*>(group);
+  if (Group->getNextDeclarator() == 0) return Group;
+  
+  Decl *NewGroup = 0;
+  while (Group) {
+    Decl *Next = Group->getNextDeclarator();
+    Group->setNextDeclarator(NewGroup);
+    NewGroup = Group;
+    Group = Next;
+  }
+  return NewGroup;
+}
+  
 VarDecl *
 Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
                            Scope *FnScope) {
@@ -426,9 +445,10 @@
   }
   
   // FIXME: Handle storage class (auto, register). No declarator?
+  // TODO: Chain to previous parameter with the prevdeclarator chain?
   VarDecl *New = new ParmVarDecl(PI.IdentLoc, II, 
                                  QualType::getFromOpaquePtr(PI.TypeInfo), 
-                                 VarDecl::None);
+                                 VarDecl::None, 0);
 
   // If this has an identifier, add it to the scope stack.
   if (II) {
@@ -556,14 +576,16 @@
 }
 
 
-TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) {
-  assert(D.getIdentifier() && "Wrong callback for declspec withotu declarator");
+TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D,
+                                    Decl *LastDeclarator) {
+  assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
   
   QualType T = GetTypeForDeclarator(D, S);
   if (T.isNull()) return 0;
   
   // Scope manipulation handled by caller.
-  return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T);
+  return new TypedefDecl(D.getIdentifierLoc(), D.getIdentifier(), T,
+                         LastDeclarator);
 }
 
 
@@ -638,14 +660,18 @@
   switch (Kind) {
   default: assert(0 && "Unknown tag kind!");
   case Decl::Enum:
-    New = new EnumDecl(Loc, Name);
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // enum X { A, B, C } D;    D should chain to X.
+    New = new EnumDecl(Loc, Name, 0);
     // If this is an undefined enum, warn.
     if (TK != TK_Definition) Diag(Loc, diag::ext_forward_ref_enum);
     break;
   case Decl::Union:
   case Decl::Struct:
   case Decl::Class:
-    New = new RecordDecl(Kind, Loc, Name);
+    // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.:
+    // struct X { int A; } D;    D should chain to X.
+    New = new RecordDecl(Kind, Loc, Name, 0);
     break;
   }    
   
@@ -697,7 +723,9 @@
     if (VerifyConstantArrayType(ary, Loc))
       return 0;
   }
-  return new FieldDecl(Loc, II, T);
+  
+  // FIXME: Chain fielddecls together.
+  return new FieldDecl(Loc, II, T, 0);
 }
 
 void Sema::ParseRecordBody(SourceLocation RecLoc, DeclTy *RecDecl,
@@ -837,7 +865,8 @@
     return 0;
   }
   QualType Ty = Context.getTagDeclType(TheEnumDecl);
-  EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val);
+  // FIXME: Chain EnumConstantDecl's together.
+  EnumConstantDecl *New = new EnumConstantDecl(IdLoc, Id, Ty, (Expr *)Val, 0);
   
   // Register this decl in the current scope stack.
   New->setNext(Id->getFETokenInfo<Decl>());
@@ -869,9 +898,8 @@
 
   // If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
   // remember this in the LastInGroupList list.
-  if (last) {
+  if (last)
     LastInGroupList.push_back((Decl*)last);
-  }
 }
 
 /// ParseAttribute GCC __attribute__

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=39623&r1=39622&r2=39623&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:46:21 2007
@@ -64,9 +64,13 @@
   ///
   Decl *Next;
 
+  /// NextDeclarator - If this decl was part of a multi-declarator declaration,
+  /// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
+  Decl *NextDeclarator;
+  
 protected:
-  Decl(Kind DK, SourceLocation L, IdentifierInfo *Id)
-    : DeclKind(DK), Loc(L), Identifier(Id), Next(0) {
+  Decl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *NextDecl)
+    : DeclKind(DK), Loc(L), Identifier(Id), Next(0), NextDeclarator(NextDecl) {
     if (Decl::CollectingStats()) addDeclKind(DK);
   }
   virtual ~Decl();
@@ -81,6 +85,13 @@
   Decl *getNext() const { return Next; }
   void setNext(Decl *N) { Next = N; }
   
+  /// getNextDeclarator - If this decl was part of a multi-declarator
+  /// declaration, such as "int X, Y, *Z;" this returns the decl for the next
+  /// declarator.  Otherwise it returns null.
+  Decl *getNextDeclarator() { return NextDeclarator; }
+  const Decl *getNextDeclarator() const { return NextDeclarator; }
+  void setNextDeclarator(Decl *N) { NextDeclarator = N; }
+  
   IdentifierNamespace getIdentifierNamespace() const {
     switch (DeclKind) {
     default: assert(0 && "Unknown decl kind!");
@@ -113,8 +124,8 @@
 class ValueDecl : public Decl {
   QualType DeclType;
 protected:
-  ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T): 
-             Decl(DK, L, Id), DeclType(T) {}
+  ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
+            Decl *PrevDecl) : Decl(DK, L, Id, PrevDecl), DeclType(T) {}
 public:
   QualType getType() const { return DeclType; }
   QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
@@ -142,8 +153,8 @@
   static bool classof(const VarDecl *D) { return true; }
 protected:
   VarDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
-          StorageClass SC)
-    : ValueDecl(DK, L, Id, T) { SClass = SC; }
+          StorageClass SC, Decl *PrevDecl)
+    : ValueDecl(DK, L, Id, T, PrevDecl) { SClass = SC; }
 private:
   StorageClass SClass;
   // TODO: Initializer.
@@ -152,8 +163,9 @@
 /// BlockVarDecl - Represent a local variable declaration.
 class BlockVarDecl : public VarDecl {
 public:
-  BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S)
-    : VarDecl(BlockVariable, L, Id, T, S) {}
+  BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
+               Decl *PrevDecl)
+    : VarDecl(BlockVariable, L, Id, T, S, PrevDecl) {}
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == BlockVariable; }
@@ -166,8 +178,9 @@
 /// pointer to the decl's scope, which is transient).
 class FileVarDecl : public VarDecl {
 public:
-  FileVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S)
-    : VarDecl(FileVariable, L, Id, T, S) {}
+  FileVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
+              Decl *PrevDecl)
+    : VarDecl(FileVariable, L, Id, T, S, PrevDecl) {}
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == FileVariable; }
@@ -177,8 +190,9 @@
 /// ParmVarDecl - Represent a parameter to a function.
 class ParmVarDecl : public VarDecl {
 public:
-  ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S)
-    : VarDecl(ParmVariable, L, Id, T, S) {}
+  ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
+              Decl *PrevDecl)
+    : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {}
   
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == ParmVariable; }
@@ -192,8 +206,9 @@
   enum StorageClass {
     None, Extern, Static
   };
-  FunctionDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S=None)
-    : ValueDecl(Function, L, Id, T), 
+  FunctionDecl(SourceLocation L, IdentifierInfo *Id, QualType T,
+               StorageClass S = None, Decl *PrevDecl)
+    : ValueDecl(Function, L, Id, T, PrevDecl), 
       ParamInfo(0), Body(0), DeclChain(0), SClass(S) {}
   virtual ~FunctionDecl();
 
@@ -240,8 +255,8 @@
 class FieldDecl : public Decl {
   QualType DeclType;
 public:
-  FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
-    : Decl(Field, L, Id), DeclType(T) {}
+  FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Decl *PrevDecl)
+    : Decl(Field, L, Id, PrevDecl), DeclType(T) {}
 
   QualType getType() const { return DeclType; }
   QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
@@ -260,8 +275,9 @@
 class EnumConstantDecl : public ValueDecl {
   Expr *Init; // an integer constant expression
 public:
-  EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E)
-    : ValueDecl(EnumConstant, L, Id, T), Init(E) {}
+  EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E,
+                   Decl *PrevDecl)
+    : ValueDecl(EnumConstant, L, Id, T, PrevDecl), Init(E) {}
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
@@ -280,8 +296,8 @@
   Type *TypeForDecl;
   friend class ASTContext;
 protected:
-  TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id)
-    : Decl(DK, L, Id), TypeForDecl(0) {}
+  TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
+    : Decl(DK, L, Id, PrevDecl), TypeForDecl(0) {}
 public:
   
   // Implement isa/cast/dyncast/etc.
@@ -296,8 +312,8 @@
   /// UnderlyingType - This is the type the typedef is set to.
   QualType UnderlyingType;
 public:
-  TypedefDecl(SourceLocation L, IdentifierInfo *Id, QualType T)
-    : TypeDecl(Typedef, L, Id), UnderlyingType(T) {}
+  TypedefDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Decl *PrevDecl)
+    : TypeDecl(Typedef, L, Id, PrevDecl), UnderlyingType(T) {}
   
   QualType getUnderlyingType() const { return UnderlyingType; }
   
@@ -313,7 +329,8 @@
   /// it is a declaration ("struct foo;").
   bool IsDefinition : 1;
 protected:
-  TagDecl(Kind DK, SourceLocation L, IdentifierInfo *Id) : TypeDecl(DK, L, Id) {
+  TagDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
+    : TypeDecl(DK, L, Id, PrevDecl) {
     IsDefinition = false;
   }
 public:
@@ -351,7 +368,8 @@
   EnumConstantDecl **Elements;   // Null if not defined.
   int NumElements;   // -1 if not defined.
 public:
-  EnumDecl(SourceLocation L, IdentifierInfo *Id) : TagDecl(Enum, L, Id) {
+  EnumDecl(SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
+    : TagDecl(Enum, L, Id, PrevDecl) {
     Elements = 0;
     NumElements = -1;
   }
@@ -379,7 +397,8 @@
   FieldDecl **Members;   // Null if not defined.
   int NumMembers;   // -1 if not defined.
 public:
-  RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id) :TagDecl(DK, L, Id){
+  RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
+    : TagDecl(DK, L, Id, PrevDecl) {
     HasFlexibleArrayMember = false;
     assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
     Members = 0;

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=39623&r1=39622&r2=39623&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/cfe/trunk/include/clang/Parse/Action.h Wed Jul 11 11:46:21 2007
@@ -98,6 +98,12 @@
     return 0;
   }
 
+  /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
+  /// gives the actions implementation a chance to process the group as a whole.
+  virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group) {
+    return Group;
+  }
+
   /// ParseStartOfFunctionDef - This is called at the start of a function
   /// definition, instead of calling ParseDeclarator.  The Declarator includes
   /// information about formal arguments that are part of this function.





More information about the cfe-commits mailing list