diff options
author | Chris Lattner <sabre@nondot.org> | 2007-06-09 00:53:06 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2007-06-09 00:53:06 +0000 |
commit | 776fac87033d7616f1bfd46c39221688c97b0011 (patch) | |
tree | 08c9456e9bade0814529b5f7d25aa6c4dd4e8149 /clang | |
parent | d9d2fb1420afa09e2b5d6b1242c73c642ed39b25 (diff) | |
download | bcm5719-llvm-776fac87033d7616f1bfd46c39221688c97b0011.tar.gz bcm5719-llvm-776fac87033d7616f1bfd46c39221688c97b0011.zip |
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.
llvm-svn: 39623
Diffstat (limited to 'clang')
-rw-r--r-- | clang/AST/StmtPrinter.cpp | 8 | ||||
-rw-r--r-- | clang/Parse/ParseDecl.cpp | 16 | ||||
-rw-r--r-- | clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | clang/Sema/SemaDecl.cpp | 66 | ||||
-rw-r--r-- | clang/include/clang/AST/Decl.h | 69 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 6 |
6 files changed, 113 insertions, 56 deletions
diff --git a/clang/AST/StmtPrinter.cpp b/clang/AST/StmtPrinter.cpp index eea5511ffed..8d922160b15 100644 --- a/clang/AST/StmtPrinter.cpp +++ b/clang/AST/StmtPrinter.cpp @@ -124,9 +124,11 @@ void StmtPrinter::VisitNullStmt(NullStmt *Node) { } 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) { diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp index a095b2f938e..74f7602f88b 100644 --- a/clang/Parse/ParseDecl.cpp +++ b/clang/Parse/ParseDecl.cpp @@ -279,15 +279,15 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { 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 diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 1315fece29a..bf7f3134733 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -98,6 +98,8 @@ private: 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 @@ private: 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); diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index c1264050d85..99b1872ae2b 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -155,7 +155,8 @@ Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) { 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 @@ Sema::DeclTy *Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { 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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, 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 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init, } 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 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo, } // 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 @@ Decl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, } -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 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK, 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 @@ Sema::DeclTy *Sema::ParseField(Scope *S, DeclTy *TagDecl, 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 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *EnumDeclX, 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 @@ void Sema::AddTopLevelDecl(Decl *current, Decl *last) { // 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__ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index b4fbf1fad1d..d3e302b2d45 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -64,9 +64,13 @@ private: /// 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ private: /// 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 @@ public: /// 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 @@ public: /// 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 @@ public: 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 @@ private: 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 @@ public: 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 @@ class TypeDecl : public Decl { 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 @@ class TypedefDecl : public TypeDecl { /// 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 @@ class TagDecl : public TypeDecl { /// 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 @@ class EnumDecl : public TagDecl { 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 @@ class RecordDecl : public TagDecl { 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; diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 188f2f4c1a6..62692d0d841 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -98,6 +98,12 @@ public: 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. |