From 8799cf202c40e19625a156db52fd9b4e45d30387 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 23 Jan 2007 01:57:16 +0000 Subject: [PATCH] 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 --- clang/AST/Sema.h | 2 +- clang/AST/SemaDecl.cpp | 20 ++++++++++++++++++-- clang/Parse/ParseDecl.cpp | 14 +++++++++++--- clang/Sema/Sema.h | 2 +- clang/Sema/SemaDecl.cpp | 20 ++++++++++++++++++-- clang/include/clang/Parse/Action.h | 2 +- 6 files changed, 50 insertions(+), 10 deletions(-) diff --git a/clang/AST/Sema.h b/clang/AST/Sema.h index 1cbc5952aa3d..974ba4d1ef92 100644 --- a/clang/AST/Sema.h +++ b/clang/AST/Sema.h @@ -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); diff --git a/clang/AST/SemaDecl.cpp b/clang/AST/SemaDecl.cpp index 0e4f7e4457f4..0ff4e6553477 100644 --- a/clang/AST/SemaDecl.cpp +++ b/clang/AST/SemaDecl.cpp @@ -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 diff --git a/clang/Parse/ParseDecl.cpp b/clang/Parse/ParseDecl.cpp index d52e5b2a31e9..191e590f0e54 100644 --- a/clang/Parse/ParseDecl.cpp +++ b/clang/Parse/ParseDecl.cpp @@ -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(); diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 1cbc5952aa3d..974ba4d1ef92 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -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); diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 0e4f7e4457f4..0ff4e6553477 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -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 diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index e1d2686f8e13..5a10a39df1a4 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -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;