[cfe-commits] r61940 - in /cfe/trunk: include/clang/AST/ include/clang/Parse/ lib/AST/ lib/Parse/ lib/Sema/ test/Sema/ test/SemaCXX/ test/SemaObjC/
Daniel Dunbar
daniel at zuster.org
Thu Jan 8 17:18:41 PST 2009
Hi Doug,
My tester is pointing at this for a 2.1% slowdown at -fsyntax-only (on
essentially Cocoa.h). Can you investigate?
- Daniel
On Thu, Jan 8, 2009 at 12:45 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Author: dgregor
> Date: Thu Jan 8 14:45:30 2009
> New Revision: 61940
>
> URL: http://llvm.org/viewvc/llvm-project?rev=61940&view=rev
> Log:
> Unify the code for defining tags in C and C++, so that we always
> introduce a Scope for the body of a tag. This reduces the number of
> semantic differences between C and C++ structs and unions, and will
> help with other features (e.g., anonymous unions) in C. Some important
> points:
>
> - Fields are now in the "member" namespace (IDNS_Member), to keep
> them separate from tags and ordinary names in C. See the new test
> in Sema/member-reference.c for an example of why this matters. In
> C++, ordinary and member name lookup will find members in both the
> ordinary and member namespace, so the difference between
> IDNS_Member and IDNS_Ordinary is erased by Sema::LookupDecl (but
> only in C++!).
> - We always introduce a Scope and push a DeclContext when we're
> defining a tag, in both C and C++. Previously, we had different
> actions and different Scope/CurContext behavior for enums, C
> structs/unions, and C++ structs/unions/classes. Now, it's one pair
> of actions. (Yay!)
>
> There's still some fuzziness in the handling of struct/union/enum
> definitions within other struct/union/enum definitions in C. We'll
> need to do some more cleanup to eliminate some reliance on CurContext
> before we can solve this issue for real. What we want is for something
> like this:
>
> struct X {
> struct T { int x; } t;
> };
>
> to introduce T into translation unit scope (placing it at the
> appropriate point in the IdentifierResolver chain, too), but it should
> still have struct X as its lexical declaration
> context. PushOnScopeChains isn't smart enough to do that yet, though,
> so there's a FIXME test in nested-redef.c
>
>
> Added:
> cfe/trunk/test/Sema/nested-redef.c
> cfe/trunk/test/SemaObjC/interface-scope.m
> Modified:
> cfe/trunk/include/clang/AST/Decl.h
> cfe/trunk/include/clang/AST/DeclBase.h
> cfe/trunk/include/clang/Parse/Action.h
> cfe/trunk/lib/AST/Decl.cpp
> cfe/trunk/lib/AST/DeclBase.cpp
> cfe/trunk/lib/Parse/ParseDecl.cpp
> cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> cfe/trunk/lib/Parse/ParseObjc.cpp
> cfe/trunk/lib/Sema/IdentifierResolver.cpp
> cfe/trunk/lib/Sema/Sema.h
> cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/test/Sema/member-reference.c
> cfe/trunk/test/SemaCXX/anonymous-union.cpp
> cfe/trunk/test/SemaCXX/class.cpp
> cfe/trunk/test/SemaObjC/duplicate-ivar-check.m
> cfe/trunk/test/SemaObjC/ivar-sem-check-1.m
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Thu Jan 8 14:45:30 2009
> @@ -900,7 +900,7 @@
>
>
> /// TagDecl - Represents the declaration of a struct/union/class/enum.
> -class TagDecl : public TypeDecl {
> +class TagDecl : public TypeDecl, public DeclContext {
> public:
> enum TagKind {
> TK_struct,
> @@ -919,7 +919,7 @@
> protected:
> TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
> IdentifierInfo *Id, ScopedDecl *PrevDecl)
> - : TypeDecl(DK, DC, L, Id, PrevDecl) {
> + : TypeDecl(DK, DC, L, Id, PrevDecl), DeclContext(DK) {
> assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");
> TagDeclKind = TK;
> IsDefinition = false;
> @@ -970,7 +970,7 @@
>
> /// EnumDecl - Represents an enum. As an extension, we allow forward-declared
> /// enums.
> -class EnumDecl : public TagDecl, public DeclContext {
> +class EnumDecl : public TagDecl {
> /// IntegerType - This represent the integer type that the enum corresponds
> /// to for code generation purposes. Note that the enumerator constants may
> /// have a different type than this does.
> @@ -978,7 +978,7 @@
>
> EnumDecl(DeclContext *DC, SourceLocation L,
> IdentifierInfo *Id, ScopedDecl *PrevDecl)
> - : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl), DeclContext(Enum) {
> + : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl) {
> IntegerType = QualType();
> }
> public:
> @@ -1053,7 +1053,7 @@
> /// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
> /// This decl will be marked invalid if *any* members are invalid.
> ///
> -class RecordDecl : public TagDecl, public DeclContext {
> +class RecordDecl : public TagDecl {
> /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
> /// array member (e.g. int X[]) or if this union contains a struct that does.
> /// If so, this cannot be contained in arrays or other structs as a member.
>
> Modified: cfe/trunk/include/clang/AST/DeclBase.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclBase.h (original)
> +++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jan 8 14:45:30 2009
> @@ -68,9 +68,9 @@
> Namespace, // [DeclContext]
> // TypeDecl
> Typedef,
> - // TagDecl
> - Enum, // [DeclContext]
> - Record, // [DeclContext]
> + // TagDecl // [DeclContext]
> + Enum,
> + Record,
> CXXRecord,
> TemplateTypeParm,
> // ValueDecl
> @@ -206,9 +206,6 @@
> case OriginalParmVar:
> case EnumConstant:
> case NonTypeTemplateParm:
> - case Field:
> - case ObjCAtDefsField:
> - case ObjCIvar:
> case ObjCInterface:
> case ObjCCompatibleAlias:
> case OverloadedFunction:
> @@ -216,6 +213,12 @@
> case CXXConversion:
> case CXXClassVar:
> return IDNS_Ordinary;
> +
> + case Field:
> + case ObjCAtDefsField:
> + case ObjCIvar:
> + return IDNS_Member;
> +
> case Record:
> case CXXRecord:
> case TemplateTypeParm:
>
> Modified: cfe/trunk/include/clang/Parse/Action.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Parse/Action.h (original)
> +++ cfe/trunk/include/clang/Parse/Action.h Thu Jan 8 14:45:30 2009
> @@ -341,10 +341,14 @@
> SourceLocation LBrac, SourceLocation RBrac,
> AttributeList *AttrList) {}
>
> - /// ActOnEnumStartDefinition - Invoked when we have entered the
> - /// scope of the enumeration body and will be parsing its
> - /// enumerators.
> - virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl) { }
> + /// ActOnTagStartDefinition - Invoked when we have entered the
> + /// scope of a tag's definition (e.g., for an enumeration, class,
> + /// struct, or union).
> + virtual void ActOnTagStartDefinition(Scope *S, DeclTy *TagDecl) { }
> +
> + /// ActOnTagFinishDefinition - Invoked once we have finished parsing
> + /// the definition of a tag (enumeration, class, struct, or union).
> + virtual void ActOnTagFinishDefinition(Scope *S, DeclTy *TagDecl) { }
>
> virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
> DeclTy *LastEnumConstant,
> @@ -915,12 +919,6 @@
> unsigned NumBases) {
> }
>
> - /// ActOnStartCXXClassDef - This is called at the start of a class/struct/union
> - /// definition, when on C++.
> - virtual void ActOnStartCXXClassDef(Scope *S, DeclTy *TagDecl,
> - SourceLocation LBrace) {
> - }
> -
> /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
> /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth'
> /// specifies the bitfield width if there is one and 'Init' specifies the
> @@ -962,11 +960,6 @@
> SourceLocation RBrac) {
> }
>
> - /// ActOnFinishCXXClassDef - This is called when a class/struct/union has
> - /// completed parsing, when on C++.
> - virtual void ActOnFinishCXXClassDef(DeclTy *TagDecl) {
> - }
> -
> //===---------------------------C++ Templates----------------------------===//
>
> /// ActOnTypeParameter - Called when a C++ template type parameter
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Thu Jan 8 14:45:30 2009
> @@ -314,8 +314,7 @@
>
> RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L,
> IdentifierInfo *Id)
> - : TagDecl(DK, TK, DC, L, Id, 0), DeclContext(DK) {
> -
> + : TagDecl(DK, TK, DC, L, Id, 0) {
> HasFlexibleArrayMember = false;
> AnonymousStructOrUnion = false;
> assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Thu Jan 8 14:45:30 2009
> @@ -579,6 +579,7 @@
>
> const DeclContext *DeclContext::getLookupContext() const {
> const DeclContext *Ctx = this;
> + // Skip through transparent contexts.
> while (Ctx->isTransparentContext())
> Ctx = Ctx->getParent();
> return Ctx;
>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jan 8 14:45:30 2009
> @@ -948,6 +948,9 @@
> unsigned TagType, DeclTy *TagDecl) {
> SourceLocation LBraceLoc = ConsumeBrace();
>
> + ParseScope StructScope(this, Scope::DeclScope);
> + Actions.ActOnTagStartDefinition(CurScope, TagDecl);
> +
> // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
> // C++.
> if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
> @@ -1027,7 +1030,9 @@
> Actions.ActOnFields(CurScope,
> RecordLoc,TagDecl,&FieldDecls[0],FieldDecls.size(),
> LBraceLoc, RBraceLoc,
> - AttrList);
> + AttrList);
> + StructScope.Exit();
> + Actions.ActOnTagFinishDefinition(CurScope, TagDecl);
> }
>
>
> @@ -1125,7 +1130,7 @@
> void Parser::ParseEnumBody(SourceLocation StartLoc, DeclTy *EnumDecl) {
> // Enter the scope of the enum body and start the definition.
> ParseScope EnumScope(this, Scope::DeclScope);
> - Actions.ActOnEnumStartDefinition(CurScope, EnumDecl);
> + Actions.ActOnTagStartDefinition(CurScope, EnumDecl);
>
> SourceLocation LBraceLoc = ConsumeBrace();
>
> @@ -1178,6 +1183,9 @@
> // If attributes exist after the identifier list, parse them.
> if (Tok.is(tok::kw___attribute))
> AttrList = ParseAttributes(); // FIXME: where do they do?
> +
> + EnumScope.Exit();
> + Actions.ActOnTagFinishDefinition(CurScope, EnumDecl);
> }
>
> /// isTypeSpecifierQualifier - Return true if the current token could be the
>
> Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Jan 8 14:45:30 2009
> @@ -730,7 +730,7 @@
> // Enter a scope for the class.
> ParseScope ClassScope(this, Scope::CXXClassScope|Scope::DeclScope);
>
> - Actions.ActOnStartCXXClassDef(CurScope, TagDecl, LBraceLoc);
> + Actions.ActOnTagStartDefinition(CurScope, TagDecl);
>
> // C++ 11p3: Members of a class defined with the keyword class are private
> // by default. Members of a class defined with the keywords struct or union
> @@ -802,7 +802,7 @@
> // Leave the class scope.
> ClassScope.Exit();
>
> - Actions.ActOnFinishCXXClassDef(TagDecl);
> + Actions.ActOnTagFinishDefinition(CurScope, TagDecl);
> }
>
> /// ParseConstructorInitializer - Parse a C++ constructor initializer,
>
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Jan 8 14:45:30 2009
> @@ -840,6 +840,8 @@
> llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
> llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
>
> + ParseScope ClassScope(this, Scope::DeclScope);
> +
> SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
>
> tok::ObjCKeywordKind visibility = tok::objc_protected;
>
> Modified: cfe/trunk/lib/Sema/IdentifierResolver.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/IdentifierResolver.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/IdentifierResolver.cpp (original)
> +++ cfe/trunk/lib/Sema/IdentifierResolver.cpp Thu Jan 8 14:45:30 2009
> @@ -60,6 +60,9 @@
> else
> return TUCtx();
>
> + if (!Ctx) // FIXME: HACK! We shouldn't end up with a NULL context here.
> + return TUCtx();
> +
> Ctx = Ctx->getLookupContext();
>
> if (isa<TranslationUnitDecl>(Ctx))
>
> Modified: cfe/trunk/lib/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/Sema.h (original)
> +++ cfe/trunk/lib/Sema/Sema.h Thu Jan 8 14:45:30 2009
> @@ -327,7 +327,16 @@
> DeclTy **Fields, unsigned NumFields,
> SourceLocation LBrac, SourceLocation RBrac,
> AttributeList *AttrList);
> - virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl);
> +
> + /// ActOnTagStartDefinition - Invoked when we have entered the
> + /// scope of a tag's definition (e.g., for an enumeration, class,
> + /// struct, or union).
> + virtual void ActOnTagStartDefinition(Scope *S, DeclTy *TagDecl);
> +
> + /// ActOnTagFinishDefinition - Invoked once we have finished parsing
> + /// the definition of a tag (enumeration, class, struct, or union).
> + virtual void ActOnTagFinishDefinition(Scope *S, DeclTy *TagDecl);
> +
> virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
> DeclTy *LastEnumConstant,
> SourceLocation IdLoc, IdentifierInfo *Id,
> @@ -1017,9 +1026,6 @@
> virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
> const CXXScopeSpec *SS);
>
> - virtual void ActOnStartCXXClassDef(Scope *S, DeclTy *TagDecl,
> - SourceLocation LBrace);
> -
> virtual DeclTy *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
> Declarator &D, ExprTy *BitfieldWidth,
> ExprTy *Init, DeclTy *LastInGroup);
> @@ -1040,8 +1046,6 @@
> SourceLocation LBrac,
> SourceLocation RBrac);
>
> - virtual void ActOnFinishCXXClassDef(DeclTy *TagDecl);
> -
> virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method);
> virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *Param);
> virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method);
>
> Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Thu Jan 8 14:45:30 2009
> @@ -28,7 +28,7 @@
> DeclContext::lookup_const_iterator I, E;
> for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) {
> IdIsUndeclared = false;
> - if (((*I)->getIdentifierNamespace() & Decl::IDNS_Tag) ||
> + if (((*I)->isInIdentifierNamespace(Decl::IDNS_Tag)) ||
> isa<TypedefDecl>(*I))
> return *I;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jan 8 14:45:30 2009
> @@ -263,18 +263,37 @@
> bool NamespaceNameOnly) {
> if (!Name) return 0;
> unsigned NS = NSI;
> - if (getLangOptions().CPlusPlus && (NS & Decl::IDNS_Ordinary))
> - NS |= Decl::IDNS_Tag;
>
> - if (LookupCtx == 0 &&
> - (!getLangOptions().CPlusPlus || (NS == Decl::IDNS_Label))) {
> - // Unqualified name lookup in C/Objective-C and name lookup for
> - // labels in C++ is purely lexical, so search in the
> - // declarations attached to the name.
> + // In C++, ordinary and member lookup will always find all
> + // kinds of names.
> + if (getLangOptions().CPlusPlus &&
> + (NS & (Decl::IDNS_Ordinary | Decl::IDNS_Member)))
> + NS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Ordinary;
> +
> + if (LookupCtx == 0 && !getLangOptions().CPlusPlus) {
> + // Unqualified name lookup in C/Objective-C is purely lexical, so
> + // search in the declarations attached to the name.
> assert(!LookupCtx && "Can't perform qualified name lookup here");
> assert(!NamespaceNameOnly && "Can't perform namespace name lookup here");
> +
> + // For the purposes of unqualified name lookup, structs and unions
> + // don't have scopes at all. For example:
> + //
> + // struct X {
> + // struct T { int i; } x;
> + // };
> + //
> + // void f() {
> + // struct T t; // okay: T is defined lexically within X, but
> + // // semantically at global scope
> + // };
> + //
> + // FIXME: Is there a better way to deal with this?
> + DeclContext *SearchCtx = CurContext;
> + while (isa<RecordDecl>(SearchCtx) || isa<EnumDecl>(SearchCtx))
> + SearchCtx = SearchCtx->getParent();
> IdentifierResolver::iterator I
> - = IdResolver.begin(Name, CurContext, LookInParent);
> + = IdResolver.begin(Name, SearchCtx, LookInParent);
>
> // Scan up the scope chain looking for a decl that matches this
> // identifier that is in the appropriate namespace. This search
> @@ -284,6 +303,11 @@
> if ((*I)->isInIdentifierNamespace(NS))
> return *I;
> } else if (LookupCtx) {
> + // If we're performing qualified name lookup (e.g., lookup into a
> + // struct), find fields as part of ordinary name lookup.
> + if (NS & Decl::IDNS_Ordinary)
> + NS |= Decl::IDNS_Member;
> +
> // Perform qualified name lookup into the LookupCtx.
> // FIXME: Will need to look into base classes and such.
> DeclContext::lookup_const_iterator I, E;
> @@ -2852,6 +2876,15 @@
> // declaration or definition.
> // Use ScopedDecl instead of TagDecl, because a NamespaceDecl may come up.
> PrevDecl = dyn_cast_or_null<ScopedDecl>(LookupDecl(Name, Decl::IDNS_Tag,S));
> +
> + if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
> + // FIXME: This makes sure that we ignore the contexts associated
> + // with C structs, unions, and enums when looking for a matching
> + // tag declaration or definition. See the similar lookup tweak
> + // in Sema::LookupDecl; is there a better way to deal with this?
> + while (isa<RecordDecl>(DC) || isa<EnumDecl>(DC))
> + DC = DC->getParent();
> + }
> }
>
> if (PrevDecl && PrevDecl->isTemplateParameter()) {
> @@ -3007,6 +3040,43 @@
> return New;
> }
>
> +void Sema::ActOnTagStartDefinition(Scope *S, DeclTy *TagD) {
> + TagDecl *Tag = cast<TagDecl>((Decl *)TagD);
> +
> + // Enter the tag context.
> + PushDeclContext(S, Tag);
> +
> + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Tag)) {
> + FieldCollector->StartClass();
> +
> + if (Record->getIdentifier()) {
> + // C++ [class]p2:
> + // [...] The class-name is also inserted into the scope of the
> + // class itself; this is known as the injected-class-name. For
> + // purposes of access checking, the injected-class-name is treated
> + // as if it were a public member name.
> + RecordDecl *InjectedClassName
> + = CXXRecordDecl::Create(Context, Record->getTagKind(),
> + CurContext, Record->getLocation(),
> + Record->getIdentifier(), Record);
> + InjectedClassName->setImplicit();
> + PushOnScopeChains(InjectedClassName, S);
> + }
> + }
> +}
> +
> +void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
> + TagDecl *Tag = cast<TagDecl>((Decl *)TagD);
> +
> + if (isa<CXXRecordDecl>(Tag))
> + FieldCollector->FinishClass();
> +
> + // Exit this scope of this tag's definition.
> + PopDeclContext();
> +
> + // Notify the consumer that we've defined a tag.
> + Consumer.HandleTagDeclDefinition(Tag);
> +}
>
> /// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
> /// types into constant array types in certain situations which would otherwise
> @@ -3108,6 +3178,18 @@
> DeclSpec::SCS_mutable,
> /*PrevDecl=*/0);
>
> + if (II) {
> + Decl *PrevDecl
> + = LookupDecl(II, Decl::IDNS_Member, S, 0, false, false, false);
> + if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
> + && !isa<TagDecl>(PrevDecl)) {
> + Diag(Loc, diag::err_duplicate_member) << II;
> + Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
> + NewFD->setInvalidDecl();
> + Record->setInvalidDecl();
> + }
> + }
> +
> if (getLangOptions().CPlusPlus) {
> CheckExtraCXXDefaultArguments(D);
> if (!T->isPODType())
> @@ -3119,9 +3201,9 @@
> if (D.getInvalidType() || InvalidDecl)
> NewFD->setInvalidDecl();
>
> - if (II && getLangOptions().CPlusPlus)
> + if (II) {
> PushOnScopeChains(NewFD, S);
> - else
> + } else
> Record->addDecl(Context, NewFD);
>
> return NewFD;
> @@ -3146,6 +3228,7 @@
> SourceLocation DeclStart,
> Declarator &D, ExprTy *BitfieldWidth,
> tok::ObjCKeywordKind Visibility) {
> +
> IdentifierInfo *II = D.getIdentifier();
> Expr *BitWidth = (Expr*)BitfieldWidth;
> SourceLocation Loc = DeclStart;
> @@ -3188,12 +3271,30 @@
> ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, Loc, II, T, ac,
> (Expr *)BitfieldWidth);
>
> + if (II) {
> + Decl *PrevDecl
> + = LookupDecl(II, Decl::IDNS_Member, S, 0, false, false, false);
> + if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
> + && !isa<TagDecl>(PrevDecl)) {
> + Diag(Loc, diag::err_duplicate_member) << II;
> + Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
> + NewID->setInvalidDecl();
> + }
> + }
> +
> // Process attributes attached to the ivar.
> ProcessDeclAttributes(NewID, D);
>
> if (D.getInvalidType() || InvalidDecl)
> NewID->setInvalidDecl();
>
> + if (II) {
> + // FIXME: When interfaces are DeclContexts, we'll need to add
> + // these to the interface.
> + S->AddDecl(NewID);
> + IdResolver.AddDecl(NewID);
> + }
> +
> return NewID;
> }
>
> @@ -3206,27 +3307,26 @@
> assert(EnclosingDecl && "missing record or interface decl");
> RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl);
>
> - if (Record)
> - if (RecordDecl* DefRecord = Record->getDefinition(Context)) {
> + if (Record) {
> + QualType RecordType = Context.getTypeDeclType(Record);
> + if (RecordType->getAsRecordType()->getDecl()->isDefinition()) {
> + RecordDecl *Def = RecordType->getAsRecordType()->getDecl();
> // Diagnose code like:
> // struct S { struct S {} X; };
> // We discover this when we complete the outer S. Reject and ignore the
> // outer S.
> - Diag(DefRecord->getLocation(), diag::err_nested_redefinition)
> - << DefRecord->getDeclName();
> + Diag(Def->getLocation(), diag::err_nested_redefinition)
> + << Def->getDeclName();
> Diag(RecLoc, diag::note_previous_definition);
> Record->setInvalidDecl();
> return;
> }
> + }
>
> // Verify that all the fields are okay.
> unsigned NumNamedMembers = 0;
> llvm::SmallVector<FieldDecl*, 32> RecFields;
>
> - // FIXME: Eventually, we'd like to eliminate this in favor of
> - // checking for redeclarations on-the-fly.
> - llvm::DenseMap<const IdentifierInfo*, FieldDecl *> FieldIDs;
> -
> for (unsigned i = 0; i != NumFields; ++i) {
> FieldDecl *FD = cast_or_null<FieldDecl>(static_cast<Decl*>(Fields[i]));
> assert(FD && "missing field decl");
> @@ -3234,37 +3334,7 @@
> // Get the type for the field.
> Type *FDTy = FD->getType().getTypePtr();
>
> - if (FD->isAnonymousStructOrUnion()) {
> - // We have found a field that represents an anonymous struct
> - // or union. Introduce all of the inner fields (recursively)
> - // into the list of fields we know about, so that we can produce
> - // an appropriate error message in cases like:
> - //
> - // struct X {
> - // union {
> - // int x;
> - // float f;
> - // };
> - // double x;
> - // };
> - llvm::SmallVector<FieldDecl *, 4> AnonStructUnionFields;
> - AnonStructUnionFields.push_back(FD);
> - while (!AnonStructUnionFields.empty()) {
> - FieldDecl *AnonField = AnonStructUnionFields.back();
> - AnonStructUnionFields.pop_back();
> -
> - RecordDecl *AnonRecord
> - = AnonField->getType()->getAsRecordType()->getDecl();
> - for (RecordDecl::field_iterator F = AnonRecord->field_begin(),
> - FEnd = AnonRecord->field_end();
> - F != FEnd; ++F) {
> - if ((*F)->isAnonymousStructOrUnion())
> - AnonStructUnionFields.push_back(*F);
> - else if (const IdentifierInfo *II = (*F)->getIdentifier())
> - FieldIDs[II] = *F;
> - }
> - }
> - } else {
> + if (!FD->isAnonymousStructOrUnion()) {
> // Remember all fields written by the user.
> RecFields.push_back(FD);
> }
> @@ -3340,28 +3410,13 @@
> continue;
> }
> // Keep track of the number of named members.
> - if (IdentifierInfo *II = FD->getIdentifier()) {
> - // Detect duplicate member names.
> - if (FieldIDs[II]) {
> - Diag(FD->getLocation(), diag::err_duplicate_member) << II;
> - // Find the previous decl.
> - Diag(FieldIDs[II]->getLocation(), diag::note_previous_definition);
> - FD->setInvalidDecl();
> - EnclosingDecl->setInvalidDecl();
> - continue;
> - }
> + if (FD->getIdentifier())
> ++NumNamedMembers;
> - FieldIDs[II] = FD;
> - }
> }
>
> // Okay, we successfully defined 'Record'.
> if (Record) {
> Record->completeDefinition(Context);
> - // If this is a C++ record, HandleTagDeclDefinition will be invoked in
> - // Sema::ActOnFinishCXXClassDef.
> - if (!isa<CXXRecordDecl>(Record))
> - Consumer.HandleTagDeclDefinition(Record);
> } else {
> ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(&RecFields[0]);
> if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) {
> @@ -3376,7 +3431,7 @@
> ObjCIvarDecl* prevIvar = ID->getSuperClass()->FindIvarDeclaration(II);
> if (prevIvar) {
> Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
> - Diag(prevIvar->getLocation(), diag::note_previous_definition);
> + Diag(prevIvar->getLocation(), diag::note_previous_declaration);
> }
> }
> }
> @@ -3393,13 +3448,6 @@
> ProcessDeclAttributeList(Record, Attr);
> }
>
> -void Sema::ActOnEnumStartDefinition(Scope *S, DeclTy *EnumD) {
> - EnumDecl *Enum = cast<EnumDecl>((Decl *)EnumD);
> -
> - // Enter the enumeration context.
> - PushDeclContext(S, Enum);
> -}
> -
> Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
> DeclTy *lastEnumConst,
> SourceLocation IdLoc, IdentifierInfo *Id,
> @@ -3507,7 +3555,6 @@
> << Enum->getDeclName();
> Diag(Enum->getLocation(), diag::note_previous_definition);
> Enum->setInvalidDecl();
> - PopDeclContext();
> return;
> }
>
> @@ -3675,10 +3722,6 @@
> }
>
> Enum->completeDefinition(Context, BestType);
> - Consumer.HandleTagDeclDefinition(Enum);
> -
> - // Leave the context of the enumeration.
> - PopDeclContext();
> }
>
> Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jan 8 14:45:30 2009
> @@ -414,28 +414,6 @@
> // C++ class member Handling
> //===----------------------------------------------------------------------===//
>
> -/// ActOnStartCXXClassDef - This is called at the start of a class/struct/union
> -/// definition, when on C++.
> -void Sema::ActOnStartCXXClassDef(Scope *S, DeclTy *D, SourceLocation LBrace) {
> - CXXRecordDecl *Dcl = cast<CXXRecordDecl>(static_cast<Decl *>(D));
> - PushDeclContext(S, Dcl);
> - FieldCollector->StartClass();
> -
> - if (Dcl->getIdentifier()) {
> - // C++ [class]p2:
> - // [...] The class-name is also inserted into the scope of the
> - // class itself; this is known as the injected-class-name. For
> - // purposes of access checking, the injected-class-name is treated
> - // as if it were a public member name.
> - RecordDecl *InjectedClassName
> - = CXXRecordDecl::Create(Context, Dcl->getTagKind(),
> - CurContext, Dcl->getLocation(),
> - Dcl->getIdentifier(), Dcl);
> - InjectedClassName->setImplicit();
> - PushOnScopeChains(InjectedClassName, S);
> - }
> -}
> -
> /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
> /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
> /// bitfield width if there is one and 'InitExpr' specifies the initializer if
> @@ -975,16 +953,6 @@
> }
> }
>
> -void Sema::ActOnFinishCXXClassDef(DeclTy *D) {
> - CXXRecordDecl *Rec = cast<CXXRecordDecl>(static_cast<Decl *>(D));
> - FieldCollector->FinishClass();
> - PopDeclContext();
> -
> - // Everything, including inline method definitions, have been parsed.
> - // Let the consumer know of the new TagDecl definition.
> - Consumer.HandleTagDeclDefinition(Rec);
> -}
> -
> /// ActOnStartDelayedCXXMethodDeclaration - We have completed
> /// parsing a top-level (non-nested) C++ class, and we are now
> /// parsing those parts of the given Method declaration that could
>
> Modified: cfe/trunk/test/Sema/member-reference.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/member-reference.c?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/Sema/member-reference.c (original)
> +++ cfe/trunk/test/Sema/member-reference.c Thu Jan 8 14:45:30 2009
> @@ -7,3 +7,14 @@
> s->i = 1;
> }
>
> +typedef int x;
> +struct S {
> + int x;
> + x z;
> +};
> +
> +void g(void) {
> + struct S s[1];
> + s->x = 1;
> + s->z = 2;
> +}
>
> Added: cfe/trunk/test/Sema/nested-redef.c
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/nested-redef.c?rev=61940&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Sema/nested-redef.c (added)
> +++ cfe/trunk/test/Sema/nested-redef.c Thu Jan 8 14:45:30 2009
> @@ -0,0 +1,22 @@
> +// RUN: clang -fsyntax-only -verify %s
> +struct X { // expected-note{{previous definition is here}}
> + struct X { } x; // expected-error{{nested redefinition of 'X'}}
> +};
> +
> +struct Y { };
> +void f(void) {
> + struct Y { }; // okay: this is a different Y
> +}
> +
> +struct T;
> +struct Z {
> + struct T { int x; } t;
> + struct U { int x; } u;
> +};
> +
> +void f2(void) {
> + struct T t;
> + // FIXME: this is well-formed, but Clang breaks on it struct U u;
> +}
> +
> +
>
> Modified: cfe/trunk/test/SemaCXX/anonymous-union.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/anonymous-union.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/anonymous-union.cpp (original)
> +++ cfe/trunk/test/SemaCXX/anonymous-union.cpp Thu Jan 8 14:45:30 2009
> @@ -66,7 +66,7 @@
> union {
> int x; // expected-error{{member of anonymous union redeclares 'x'}}
> float y;
> - double z; // expected-note{{previous definition is here}}
> + double z; // expected-note{{previous declaration is here}}
> double zz; // expected-note{{previous definition is here}}
> };
>
>
> Modified: cfe/trunk/test/SemaCXX/class.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/class.cpp?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/class.cpp (original)
> +++ cfe/trunk/test/SemaCXX/class.cpp Thu Jan 8 14:45:30 2009
> @@ -53,7 +53,7 @@
>
> typedef int A;
>
> - virtual int vi; // expected-error {{error: 'virtual' can only appear on non-static member functions}}
> + virtual int viv; // expected-error {{error: 'virtual' can only appear on non-static member functions}}
> virtual static int vsif(); // expected-error {{error: 'virtual' can only appear on non-static member functions}}
> virtual int vif();
>
> @@ -105,3 +105,8 @@
> struct C4;
> C4; // expected-error {{declaration does not declare anything}}
> }
> +
> +struct C4 {
> + void f(); // expected-note{{previous declaration is here}}
> + int f; // expected-error{{duplicate member 'f'}}
> +};
>
> Modified: cfe/trunk/test/SemaObjC/duplicate-ivar-check.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/duplicate-ivar-check.m?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/duplicate-ivar-check.m (original)
> +++ cfe/trunk/test/SemaObjC/duplicate-ivar-check.m Thu Jan 8 14:45:30 2009
> @@ -2,13 +2,13 @@
>
> @interface B1 {
> @public
> - double fill_B; // expected-note {{previous definition is here}}
> + double fill_B; // expected-note {{previous declaration is here}}
> }
> @end
>
> @interface B : B1 {
> @public
> - int one; // expected-note {{previous definition is here}}
> + int one; // expected-note {{previous declaration is here}}
> int one; // expected-error {{duplicate member 'one'}}
> }
> @end
>
> Added: cfe/trunk/test/SemaObjC/interface-scope.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/interface-scope.m?rev=61940&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/interface-scope.m (added)
> +++ cfe/trunk/test/SemaObjC/interface-scope.m Thu Jan 8 14:45:30 2009
> @@ -0,0 +1,12 @@
> +// RUN: clang -fsyntax-only -verify %s
> +
> + at interface I1 {
> + at private
> + int x;
> + struct {
> + unsigned int x : 3;
> + unsigned int y : 3;
> + } flags;
> + int y;
> +}
> + at end
>
> Modified: cfe/trunk/test/SemaObjC/ivar-sem-check-1.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-sem-check-1.m?rev=61940&r1=61939&r2=61940&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/ivar-sem-check-1.m (original)
> +++ cfe/trunk/test/SemaObjC/ivar-sem-check-1.m Thu Jan 8 14:45:30 2009
> @@ -12,7 +12,7 @@
> struct T {} X; // expected-error {{nested redefinition of 'T'}}
> }YYY;
> FOO BADFUNC; // expected-error {{field 'BADFUNC' declared as a function}}
> - int kaka; // expected-note {{previous definition is here}}
> + int kaka; // expected-note {{previous declaration is here}}
> int kaka; // expected-error {{duplicate member 'kaka'}}
> char ch[]; // expected-error {{field 'ch' has incomplete type}}
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list