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
This commit is contained in:
Chris Lattner 2007-06-09 00:53:06 +00:00
parent d9d2fb1420
commit 776fac8703
6 changed files with 113 additions and 56 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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__

View File

@ -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;

View File

@ -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.