[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