Next big step in function parsing: create decl objects for parameters,

inserting them into the function body scope and registering them with the
corresponding FunctionDecl.

llvm-svn: 39253
This commit is contained in:
Chris Lattner 2007-01-21 07:42:07 +00:00
parent 7f58c3dfe4
commit c5cdf4d092
8 changed files with 113 additions and 26 deletions

View File

@ -23,3 +23,20 @@ Decl::~Decl() {
const char *Decl::getName() const {
return getIdentifier()->getName();
}
FunctionDecl::~FunctionDecl() {
delete[] ParamInfo;
}
unsigned FunctionDecl::getNumParams() const {
return cast<FunctionTypeProto>(getType().getTypePtr())->getNumArgs();
}
void FunctionDecl::setParams(VarDecl **NewParamInfo, unsigned NumParams) {
assert(ParamInfo == 0 && "Already has param info!");
assert(NumParams == getNumParams() && "Parameter count mismatch!");
ParamInfo = new VarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(VarDecl*)*NumParams);
}

View File

@ -24,9 +24,11 @@ namespace clang {
class ASTContext;
class Preprocessor;
class Decl;
class VarDecl;
class TypeRef;
class LangOptions;
class FunctionDecl;
class DeclaratorChunk;
/// Sema - This implements semantic analysis and AST building for C.
class Sema : public Action {
@ -66,8 +68,9 @@ public:
virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup);
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D
/* TODO: FORMAL ARG INFO.*/);
VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
Scope *FnBodyScope);
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);

View File

@ -101,10 +101,34 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
return New;
}
VarDecl *
Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
Scope *FnScope) {
const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo];
IdentifierInfo *II = PI.Ident;
Decl *PrevDecl = 0;
if (II) {
PrevDecl = II->getFETokenInfo<Decl>();
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
}
VarDecl *New = new VarDecl(II, static_cast<Type*>(PI.TypeInfo), PrevDecl);
// If this has an identifier, add it to the scope stack.
if (II) {
// If PrevDecl includes conflicting name here, emit a diagnostic.
II->setFETokenInfo(New);
FnScope->AddDecl(II);
}
return New;
}
Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *S, Declarator &D
/* TODO: FORMAL ARG INFO.*/) {
Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
assert(CurFunctionDecl == 0 && "Function parsing confused");
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"Not a function declarator!");
@ -131,14 +155,18 @@ Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *S, Declarator &D
}
FunctionDecl *FD = static_cast<FunctionDecl*>(ParseDeclarator(S, D, 0, 0));
Scope *GlobalScope = FnBodyScope->getParent();
FunctionDecl *FD =
static_cast<FunctionDecl*>(ParseDeclarator(GlobalScope, D, 0, 0));
CurFunctionDecl = FD;
// Since this is a function definition, remember the names of the arguments in
// the FunctionDecl.
// FIXME: TODO. Add to FunctionDecl, install declarators into current scope.
// Create Decl objects for each parameter, adding them to the FunctionDecl.
SmallVector<VarDecl*, 16> Params;
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i, FnBodyScope));
FD->setParams(&Params[0], Params.size());
return FD;
}

View File

@ -24,9 +24,11 @@ namespace clang {
class ASTContext;
class Preprocessor;
class Decl;
class VarDecl;
class TypeRef;
class LangOptions;
class FunctionDecl;
class DeclaratorChunk;
/// Sema - This implements semantic analysis and AST building for C.
class Sema : public Action {
@ -66,8 +68,9 @@ public:
virtual DeclTy *isTypeName(const IdentifierInfo &II, Scope *S) const;
virtual DeclTy *ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
DeclTy *LastInGroup);
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D
/* TODO: FORMAL ARG INFO.*/);
VarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
Scope *FnBodyScope);
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D);
virtual DeclTy *ParseFunctionDefBody(DeclTy *Decl, StmtTy *Body);
virtual void PopScope(SourceLocation Loc, Scope *S);

View File

@ -101,10 +101,34 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, ExprTy *Init,
return New;
}
VarDecl *
Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
Scope *FnScope) {
const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo];
IdentifierInfo *II = PI.Ident;
Decl *PrevDecl = 0;
if (II) {
PrevDecl = II->getFETokenInfo<Decl>();
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
}
VarDecl *New = new VarDecl(II, static_cast<Type*>(PI.TypeInfo), PrevDecl);
// If this has an identifier, add it to the scope stack.
if (II) {
// If PrevDecl includes conflicting name here, emit a diagnostic.
II->setFETokenInfo(New);
FnScope->AddDecl(II);
}
return New;
}
Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *S, Declarator &D
/* TODO: FORMAL ARG INFO.*/) {
Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
assert(CurFunctionDecl == 0 && "Function parsing confused");
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"Not a function declarator!");
@ -131,14 +155,18 @@ Sema::DeclTy *Sema::ParseStartOfFunctionDef(Scope *S, Declarator &D
}
FunctionDecl *FD = static_cast<FunctionDecl*>(ParseDeclarator(S, D, 0, 0));
Scope *GlobalScope = FnBodyScope->getParent();
FunctionDecl *FD =
static_cast<FunctionDecl*>(ParseDeclarator(GlobalScope, D, 0, 0));
CurFunctionDecl = FD;
// Since this is a function definition, remember the names of the arguments in
// the FunctionDecl.
// FIXME: TODO. Add to FunctionDecl, install declarators into current scope.
// Create Decl objects for each parameter, adding them to the FunctionDecl.
SmallVector<VarDecl*, 16> Params;
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
Params.push_back(ParseParamDeclarator(D.getTypeObject(0), i, FnBodyScope));
FD->setParams(&Params[0], Params.size());
return FD;
}

View File

@ -118,7 +118,12 @@ public:
/// FunctionDecl - An instance of this class is created to represent a function
/// declaration or definition.
class FunctionDecl : public ObjectDecl {
// FIXME: Args etc.
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals. TODO: we could allocate this space immediately after the
/// FunctionDecl object to save an allocation like FunctionType does.
VarDecl **ParamInfo;
Stmt *Body; // Null if a prototype.
/// DeclChain - Linked list of declarations that are defined inside this
@ -126,7 +131,8 @@ class FunctionDecl : public ObjectDecl {
Decl *DeclChain;
public:
FunctionDecl(IdentifierInfo *Id, TypeRef T, Decl *Next)
: ObjectDecl(Function, Id, T, Next), Body(0), DeclChain(0) {}
: ObjectDecl(Function, Id, T, Next), ParamInfo(0), Body(0), DeclChain(0) {}
virtual ~FunctionDecl();
Stmt *getBody() const { return Body; }
void setBody(Stmt *B) { Body = B; }
@ -134,6 +140,9 @@ public:
Decl *getDeclChain() const { return DeclChain; }
void setDeclChain(Decl *D) { DeclChain = D; }
unsigned getNumParams() const;
void setParams(VarDecl **NewParamInfo, unsigned NumParams);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Function; }
static bool classof(const FunctionDecl *D) { return true; }

View File

@ -98,11 +98,11 @@ public:
}
/// ParseStartOfFunctionDef - This is called at the start of a function
/// definition, instead of calling ParseDeclarator.
virtual DeclTy *ParseStartOfFunctionDef(Scope *S, Declarator &D
/* TODO: FORMAL ARG INFO.*/) {
/// definition, instead of calling ParseDeclarator. The Declarator includes
/// information about formal arguments that are part of this function.
virtual DeclTy *ParseStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
// Default to ParseDeclarator.
return ParseDeclarator(S, D, 0, 0);
return ParseDeclarator(FnBodyScope, D, 0, 0);
}
/// ParseFunctionDefBody - This is called when a function body has completed

View File

@ -259,7 +259,6 @@ struct DeclaratorChunk {
/// Parameter type lists will have type info (if the actions module provides
/// it), but may have null identifier info: e.g. for 'void foo(int X, int)'.
struct ParamInfo {
/// Ident - In a K&R
IdentifierInfo *Ident;
SourceLocation IdentLoc;
Action::TypeTy *TypeInfo;