When parsing a struct/union tag, we need to know whether the tag is a use

or a definition/declaration of a tag.  This is required to handle
C99 6.7.2.3p11 properly.

llvm-svn: 39274
This commit is contained in:
Chris Lattner
2007-01-23 01:57:16 +00:00
parent 3e29d0efd5
commit 8799cf202c
6 changed files with 50 additions and 10 deletions

View File

@@ -83,7 +83,7 @@ public:
Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
Scope *S);
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion,
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion, bool isUse,
SourceLocation KWLoc,IdentifierInfo *Name,
SourceLocation NameLoc);

View File

@@ -141,7 +141,6 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo];
IdentifierInfo *II = PI.Ident;
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary)) {
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
@@ -265,14 +264,31 @@ Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) {
/// 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. isUnion indicates whether this is a union or struct tag.
Sema::DeclTy *Sema::ParseStructUnionTag(Scope *S, bool isUnion,
/// isUse indicates whether this is a use of a preexisting struct tag, or if it
/// is a definition or declaration of a new one.
Sema::DeclTy *Sema::ParseStructUnionTag(Scope *S, bool isUnion, bool isUse,
SourceLocation KWLoc,
IdentifierInfo *Name,
SourceLocation NameLoc) {
// If this is a use of an existing tag, it must have a name.
assert((isUse || Name != 0) && "Nameless record must have a name!");
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
if (Decl *PrevDecl = LookupScopedDecl(Name, Decl::IDNS_Tag)) {
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (isUse || S->isDeclScope(PrevDecl)) {
}
// TODO: verify it's struct/union, etc.
}
// If there is an identifier, use the location of the identifier as the

View File

@@ -454,9 +454,17 @@ void Parser::ParseStructUnionSpecifier(DeclSpec &DS) {
// There are three options here. If we have 'struct foo;', then this is a
// forward declaration. If we have 'struct foo {...' then this is a
// definition. Otherwise we have something like 'struct foo xyz', a use.
DeclTy *TagDecl = Actions.ParseStructUnionTag(CurScope, isUnion, StartLoc,
Name, NameLoc);
// definition. Otherwise we have something like 'struct foo xyz', a use. Tell
// the actions module whether this is a definition (forward or not) of the
// type insted of a use.
//
// This is needed to handle stuff like this right (C99 6.7.2.3p11):
// struct foo {..}; void bar() { struct foo; } <- new foo in bar.
// struct foo {..}; void bar() { struct foo x; } <- use of old foo.
//
bool isUse = Tok.getKind() != tok::l_brace && Tok.getKind() != tok::semi;
DeclTy *TagDecl = Actions.ParseStructUnionTag(CurScope, isUnion, isUse,
StartLoc, Name, NameLoc);
// TODO: more with the tag decl.
if (Tok.getKind() == tok::l_brace) {
SourceLocation LBraceLoc = ConsumeBrace();

View File

@@ -83,7 +83,7 @@ public:
Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
Scope *S);
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion,
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion, bool isUse,
SourceLocation KWLoc,IdentifierInfo *Name,
SourceLocation NameLoc);

View File

@@ -141,7 +141,6 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
const DeclaratorChunk::ParamInfo &PI = FTI.Fun.ArgInfo[ArgNo];
IdentifierInfo *II = PI.Ident;
if (Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary)) {
// TODO: CHECK FOR CONFLICTS, multiple decls with same name in one scope.
@@ -265,14 +264,31 @@ Decl *Sema::ParseTypedefDecl(Scope *S, Declarator &D) {
/// 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. isUnion indicates whether this is a union or struct tag.
Sema::DeclTy *Sema::ParseStructUnionTag(Scope *S, bool isUnion,
/// isUse indicates whether this is a use of a preexisting struct tag, or if it
/// is a definition or declaration of a new one.
Sema::DeclTy *Sema::ParseStructUnionTag(Scope *S, bool isUnion, bool isUse,
SourceLocation KWLoc,
IdentifierInfo *Name,
SourceLocation NameLoc) {
// If this is a use of an existing tag, it must have a name.
assert((isUse || Name != 0) && "Nameless record must have a name!");
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
if (Decl *PrevDecl = LookupScopedDecl(Name, Decl::IDNS_Tag)) {
// If this is a use of a previous tag, or if the tag is already declared in
// the same scope (so that the definition/declaration completes or
// rementions the tag), reuse the decl.
if (isUse || S->isDeclScope(PrevDecl)) {
}
// TODO: verify it's struct/union, etc.
}
// If there is an identifier, use the location of the identifier as the

View File

@@ -140,7 +140,7 @@ public:
return 0;
}
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion,
virtual DeclTy *ParseStructUnionTag(Scope *S, bool isUnion, bool isUse,
SourceLocation KWLoc,IdentifierInfo *Name,
SourceLocation NameLoc) {
return 0;