diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 39 | ||||
| -rw-r--r-- | clang/include/clang/AST/RecursiveASTVisitor.h | 2 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DeclNodes.td | 1 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Template.h | 1 | ||||
| -rw-r--r-- | clang/include/clang/Serialization/ASTBitCodes.h | 4 | ||||
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 37 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/AST/DeclBase.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/ExprClassification.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 145 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 12 | 
17 files changed, 247 insertions, 117 deletions
| diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 1c6a97282b4..a5e29c6146a 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1794,6 +1794,45 @@ public:    friend class StmtIteratorBase;  }; +/// IndirectFieldDecl - An instance of this class is created to represent a +/// field injected from an anonymous union/struct into the parent scope. +/// IndirectFieldDecl are always implicit. +class IndirectFieldDecl : public ValueDecl { +  NamedDecl **Chaining; +  int ChainingSize; + +  IndirectFieldDecl(DeclContext *DC, SourceLocation L, +                    DeclarationName N, QualType T, +                    NamedDecl **CH, int CHS) +    : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH), ChainingSize(CHS) {} + +public: +  static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, +                                   SourceLocation L, IdentifierInfo *Id, +                                   QualType T, NamedDecl **CH, int CHS); +   +  typedef NamedDecl * const *chain_iterator; +  chain_iterator chain_begin() const { return Chaining; } +  chain_iterator chain_end() const  { return Chaining+ChainingSize; } + +  int getChainingSize() const { return ChainingSize; } + +  FieldDecl *getAnonField() const { +    assert(ChainingSize >= 2); +    return cast<FieldDecl>(Chaining[ChainingSize - 1]); +  } + +  VarDecl *getVarDecl() const { +    assert(ChainingSize >= 2); +    return dyn_cast<VarDecl>(*chain_begin()); +  } + +  // Implement isa/cast/dyncast/etc. +  static bool classof(const Decl *D) { return classofKind(D->getKind()); } +  static bool classof(const IndirectFieldDecl *D) { return true; } +  static bool classofKind(Kind K) { return K == IndirectField; } +  friend class ASTDeclReader; +};  /// TypeDecl - Represents a declaration of a type.  /// diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index f343881685a..f05ab931ec2 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1381,6 +1381,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {      TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier()));    }) +DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) +  template<typename Derived>  bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {    TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index e2f93e02c52..3e60d864a91 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -29,6 +29,7 @@ def Named : Decl<1>;    def Value : DDecl<Named, 1>;      def EnumConstant : DDecl<Value>;      def UnresolvedUsingValue : DDecl<Value>; +    def IndirectField : DDecl<Value>;      def Declarator : DDecl<Value, 1>;        def Function : DDecl<Declarator>, DeclContext;          def CXXMethod : DDecl<Function>; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9c36ce03473..4769722159e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -139,7 +139,8 @@ namespace clang {    class VarDecl;    class VisibilityAttr;    class VisibleDeclConsumer; - +  class IndirectFieldDecl; +    namespace sema {    class AccessedEntity;    class BlockScopeInfo; @@ -1739,11 +1740,9 @@ public:                                ExprValueKind VK,                                const DeclarationNameInfo &NameInfo,                                const CXXScopeSpec *SS = 0); -  VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field, -                                    llvm::SmallVectorImpl<FieldDecl *> &Path);    ExprResult    BuildAnonymousStructUnionMemberReference(SourceLocation Loc, -                                           FieldDecl *Field, +                                           IndirectFieldDecl *IndirectField,                                             Expr *BaseObjectExpr = 0,                                        SourceLocation OpLoc = SourceLocation());    ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index dd3f344cc2a..38d4b9fd254 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -269,6 +269,7 @@ namespace clang {      Decl *VisitVarDecl(VarDecl *D);      Decl *VisitAccessSpecDecl(AccessSpecDecl *D);      Decl *VisitFieldDecl(FieldDecl *D); +    Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);      Decl *VisitStaticAssertDecl(StaticAssertDecl *D);      Decl *VisitEnumDecl(EnumDecl *D);      Decl *VisitEnumConstantDecl(EnumConstantDecl *D); diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 646d09006a9..eb6c973d5e7 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -718,7 +718,9 @@ namespace clang {        /// \brief A StaticAssertDecl record.        DECL_STATIC_ASSERT,        /// \brief A record containing CXXBaseSpecifiers. -      DECL_CXX_BASE_SPECIFIERS +      DECL_CXX_BASE_SPECIFIERS, +      /// \brief A IndirectFieldDecl record. +      DECL_INDIRECTFIELD,      };      /// \brief Record codes for each kind of statement or expression. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 7b16809a1f1..980e93c04d3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -98,6 +98,7 @@ namespace {      Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);      Decl *VisitCXXConversionDecl(CXXConversionDecl *D);      Decl *VisitFieldDecl(FieldDecl *D); +    Decl *VisitIndirectFieldDecl(IndirectFieldDecl *D);      Decl *VisitObjCIvarDecl(ObjCIvarDecl *D);      Decl *VisitVarDecl(VarDecl *D);      Decl *VisitImplicitParamDecl(ImplicitParamDecl *D); @@ -2020,6 +2021,42 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {    return ToField;  } +Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { +  // Import the major distinguishing characteristics of a variable. +  DeclContext *DC, *LexicalDC; +  DeclarationName Name; +  SourceLocation Loc; +  if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) +    return 0; + +  // Import the type. +  QualType T = Importer.Import(D->getType()); +  if (T.isNull()) +    return 0; + +  NamedDecl **NamedChain = +    new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; + +  unsigned i = 0; +  for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), +       PE = D->chain_end(); PI != PE; ++PI) { +    Decl* D = Importer.Import(*PI); +    if (!D) +      return 0; +    NamedChain[i++] = cast<NamedDecl>(D); +  } + +  IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( +                                         Importer.getToContext(), DC, +                                         Loc, Name.getAsIdentifierInfo(), T, +                                         NamedChain, D->getChainingSize()); +  ToIndirectField->setAccess(D->getAccess()); +  ToIndirectField->setLexicalDeclContext(LexicalDC); +  Importer.Imported(D, ToIndirectField); +  LexicalDC->addDecl(ToIndirectField); +  return ToIndirectField; +} +  Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) {    // Import the major distinguishing characteristics of an ivar.    DeclContext *DC, *LexicalDC; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c448116ed2e..ef8f16861e2 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -768,7 +768,7 @@ bool NamedDecl::isCXXInstanceMember() const {    if (isa<UsingShadowDecl>(D))      D = cast<UsingShadowDecl>(D)->getTargetDecl(); -  if (isa<FieldDecl>(D)) +  if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D))      return true;    if (isa<CXXMethodDecl>(D))      return cast<CXXMethodDecl>(D)->isInstance(); @@ -2030,6 +2030,12 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,    return new (C) EnumConstantDecl(CD, L, Id, T, E, V);  } +IndirectFieldDecl *IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, +                                          SourceLocation L, IdentifierInfo *Id, +                                          QualType T, NamedDecl **CH, int CHS) { +  return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); +} +  SourceRange EnumConstantDecl::getSourceRange() const {    SourceLocation End = getLocation();    if (Init) diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 5ba6623b20b..7d8a92530e0 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -249,6 +249,9 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {      case ObjCProperty:        return IDNS_Ordinary; +    case IndirectField: +      return IDNS_Ordinary | IDNS_Member; +      case ObjCCompatibleAlias:      case ObjCInterface:        return IDNS_Ordinary | IDNS_Type; @@ -524,8 +527,6 @@ bool DeclContext::isTransparentContext() const {      return !cast<EnumDecl>(this)->isScoped();    else if (DeclKind == Decl::LinkageSpec)      return true; -  else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord) -    return cast<RecordDecl>(this)->isAnonymousStructOrUnion();    return false;  } diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index ba5970038d7..bf26bd1f93f 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -333,6 +333,7 @@ static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {      islvalue = NTTParm->getType()->isReferenceType();    else      islvalue = isa<VarDecl>(D) || isa<FieldDecl>(D) || +	  isa<IndirectFieldDecl>(D) ||        (Ctx.getLangOptions().CPlusPlus &&          (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D))); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7c2a8fb105e..2b970a34c45 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1748,7 +1748,8 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,  static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,                                                  DeclContext *Owner,                                                  RecordDecl *AnonRecord, -                                                AccessSpecifier AS) { +                                                AccessSpecifier AS, +                              llvm::SmallVector<NamedDecl*, 2> &Chaining) {    unsigned diagKind      = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl                              : diag::err_anonymous_struct_member_redecl; @@ -1771,20 +1772,37 @@ static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,          //   definition, the members of the anonymous union are          //   considered to have been defined in the scope in which the          //   anonymous union is declared. -        Owner->makeDeclVisibleInContext(*F); -        S->AddDecl(*F); -        SemaRef.IdResolver.AddDecl(*F); +        Chaining.push_back(*F); +        assert(Chaining.size() >= 2); +        NamedDecl **NamedChain = +          new (SemaRef.Context)NamedDecl*[Chaining.size()]; +        for (unsigned i = 0; i < Chaining.size(); i++) +          NamedChain[i] = Chaining[i]; + +        IndirectFieldDecl* IndirectField = +          IndirectFieldDecl::Create(SemaRef.Context, Owner, F->getLocation(), +                                    F->getIdentifier(), F->getType(), +                                    NamedChain, Chaining.size()); + +        IndirectField->setAccess(AS); +        IndirectField->setImplicit(); +        SemaRef.PushOnScopeChains(IndirectField, S);          // That includes picking up the appropriate access specifier.          if (AS != AS_none) (*F)->setAccess(AS); + +        Chaining.pop_back();        }      } else if (const RecordType *InnerRecordType                   = (*F)->getType()->getAs<RecordType>()) {        RecordDecl *InnerRecord = InnerRecordType->getDecl(); + +      Chaining.push_back(*F);        if (InnerRecord->isAnonymousStructOrUnion())          Invalid = Invalid ||            InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner, -                                              InnerRecord, AS); +                                              InnerRecord, AS, Chaining); +      Chaining.pop_back();      }    } @@ -1999,7 +2017,10 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,    // Inject the members of the anonymous struct/union into the owning    // context and into the identifier resolver chain for name lookup    // purposes. -  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS)) +  llvm::SmallVector<NamedDecl*, 2> Chain; +  Chain.push_back(Anon); + +  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, Chain))      Invalid = true;    // Mark this as an anonymous struct/union type. Note that we do not diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2741c6de657..235b41e342e 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1067,10 +1067,15 @@ Sema::ActOnMemInitializer(Decl *ConstructorD,      FieldDecl *Member = 0;      DeclContext::lookup_result Result        = ClassDecl->lookup(MemberOrBase); -    if (Result.first != Result.second) +    if (Result.first != Result.second) {        Member = dyn_cast<FieldDecl>(*Result.first); - -    // FIXME: Handle members of an anonymous union. +     +	  // Handle anonymous union case. +	  if (!Member) +      if (IndirectFieldDecl* IndirectField +          = dyn_cast<IndirectFieldDecl>(*Result.first)) +        Member = IndirectField->getAnonField(); +    }      if (Member)        return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, @@ -2600,15 +2605,15 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {      //   In addition, if class T has a user-declared constructor (12.1), every       //   non-static data member of class T shall have a name different from T.      for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); -         R.first != R.second; ++R.first) -      if (FieldDecl *Field = dyn_cast<FieldDecl>(*R.first)) { -        if (Record->hasUserDeclaredConstructor() || -            !Field->getDeclContext()->Equals(Record)) { -        Diag(Field->getLocation(), diag::err_member_name_of_class) -          << Field->getDeclName(); +         R.first != R.second; ++R.first) { +      NamedDecl *D = *R.first; +      if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || +          isa<IndirectFieldDecl>(D)) { +        Diag(D->getLocation(), diag::err_member_name_of_class) +          << D->getDeclName();          break;        } -      } +    }    }  } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index bc811d0e77b..37561028c26 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -795,59 +795,18 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,                                     D, NameInfo, Ty, VK));  } -/// \brief Given a field that represents a member of an anonymous -/// struct/union, build the path from that field's context to the -/// actual member. -/// -/// Construct the sequence of field member references we'll have to -/// perform to get to the field in the anonymous union/struct. The -/// list of members is built from the field outward, so traverse it -/// backwards to go from an object in the current context to the field -/// we found. -/// -/// \returns The variable from which the field access should begin, -/// for an anonymous struct/union that is not a member of another -/// class. Otherwise, returns NULL. -VarDecl *Sema::BuildAnonymousStructUnionMemberPath(FieldDecl *Field, -                                   llvm::SmallVectorImpl<FieldDecl *> &Path) { -  assert(Field->getDeclContext()->isRecord() && -         cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion() -         && "Field must be stored inside an anonymous struct or union"); - -  Path.push_back(Field); -  VarDecl *BaseObject = 0; -  DeclContext *Ctx = Field->getDeclContext(); -  do { -    RecordDecl *Record = cast<RecordDecl>(Ctx); -    ValueDecl *AnonObject = Record->getAnonymousStructOrUnionObject(); -    if (FieldDecl *AnonField = dyn_cast<FieldDecl>(AnonObject)) -      Path.push_back(AnonField); -    else { -      BaseObject = cast<VarDecl>(AnonObject); -      break; -    } -    Ctx = Ctx->getParent(); -  } while (Ctx->isRecord() && -           cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()); - -  return BaseObject; -} -  ExprResult  Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, -                                               FieldDecl *Field, +                                            IndirectFieldDecl *IndirectField,                                                 Expr *BaseObjectExpr,                                                 SourceLocation OpLoc) { -  llvm::SmallVector<FieldDecl *, 4> AnonFields; -  VarDecl *BaseObject = BuildAnonymousStructUnionMemberPath(Field, -                                                            AnonFields); -    // Build the expression that refers to the base object, from    // which we will build a sequence of member references to each    // of the anonymous union objects and, eventually, the field we    // found via name lookup.    bool BaseObjectIsPointer = false;    Qualifiers BaseQuals; +  VarDecl *BaseObject = IndirectField->getVarDecl();    if (BaseObject) {      // BaseObject is an anonymous struct/union variable (and is,      // therefore, not part of another non-anonymous record). @@ -877,7 +836,8 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,        if (!MD->isStatic()) {          QualType AnonFieldType            = Context.getTagDeclType( -                     cast<RecordDecl>(AnonFields.back()->getDeclContext())); +                     cast<RecordDecl>( +                       (*IndirectField->chain_begin())->getDeclContext()));          QualType ThisType = Context.getTagDeclType(MD->getParent());          if ((Context.getCanonicalType(AnonFieldType)                 == Context.getCanonicalType(ThisType)) || @@ -890,24 +850,29 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,          }        } else {          return ExprError(Diag(Loc,diag::err_invalid_member_use_in_static_method) -          << Field->getDeclName()); +          << IndirectField->getDeclName());        }        BaseQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());      }      if (!BaseObjectExpr)        return ExprError(Diag(Loc, diag::err_invalid_non_static_member_use) -        << Field->getDeclName()); +        << IndirectField->getDeclName());    }    // Build the implicit member references to the field of the    // anonymous struct/union.    Expr *Result = BaseObjectExpr;    Qualifiers ResultQuals = BaseQuals; -  for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator -         FI = AnonFields.rbegin(), FIEnd = AnonFields.rend(); -       FI != FIEnd; ++FI) { -    FieldDecl *Field = *FI; +   +  IndirectFieldDecl::chain_iterator FI = IndirectField->chain_begin(), +    FEnd = IndirectField->chain_end(); +   +  // Skip the first VarDecl if present.  +  if (BaseObject) +    FI++;     +  for (; FI != FEnd; FI++) { +    FieldDecl *Field = cast<FieldDecl>(*FI);      QualType MemberType = Field->getType();      Qualifiers MemberTypeQuals =        Context.getCanonicalType(MemberType).getQualifiers(); @@ -930,8 +895,9 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,      MarkDeclarationReferenced(Loc, *FI);      PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);      // FIXME: Might this end up being a qualified name? -    Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, -                                      OpLoc, MemberType, VK_LValue, +    Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, +                                      cast<FieldDecl>(*FI), OpLoc, +                                      MemberType, VK_LValue,                                        Field->isBitField() ?                                          OK_BitField : OK_Ordinary);      BaseObjectIsPointer = false; @@ -1048,10 +1014,6 @@ enum IMAKind {    /// context is not an instance method.    IMA_Unresolved_StaticContext, -  /// The reference is to a member of an anonymous structure in a -  /// non-class context. -  IMA_AnonymousMember, -    /// All possible referrents are instance members and the current    /// context is not an instance method.    IMA_Error_StaticContext, @@ -1084,16 +1046,9 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,    llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes;    for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {      NamedDecl *D = *I; +      if (D->isCXXInstanceMember()) {        CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); - -      // If this is a member of an anonymous record, move out to the -      // innermost non-anonymous struct or union.  If there isn't one, -      // that's a special case. -      while (R->isAnonymousStructOrUnion()) { -        R = dyn_cast<CXXRecordDecl>(R->getParent()); -        if (!R) return IMA_AnonymousMember; -      }        Classes.insert(R->getCanonicalDecl());      }      else @@ -1577,7 +1532,8 @@ ExprResult Sema::ActOnIdExpression(Scope *S,      else if (R.isUnresolvableResult())        MightBeImplicitMember = true;      else -      MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()); +      MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || +                              isa<IndirectFieldDecl>(R.getFoundDecl());      if (MightBeImplicitMember)        return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); @@ -1598,11 +1554,6 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,    case IMA_Instance:      return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); -  case IMA_AnonymousMember: -    assert(R.isSingleResult()); -    return BuildAnonymousStructUnionMemberReference(R.getNameLoc(), -                                                    R.getAsSingle<FieldDecl>()); -    case IMA_Mixed:    case IMA_Mixed_Unrelated:    case IMA_Unresolved: @@ -1959,9 +1910,9 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,    // (C++ [class.union]).    // FIXME: This needs to happen post-isImplicitMemberReference?    // FIXME: template-ids inside anonymous structs? -  if (FieldDecl *FD = R.getAsSingle<FieldDecl>()) -    if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion()) -      return BuildAnonymousStructUnionMemberReference(Loc, FD); +  if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) +    return BuildAnonymousStructUnionMemberReference(Loc, FD); +    // If this is known to be an instance access, go ahead and build a    // 'this' expression now. @@ -2153,6 +2104,10 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,    if (VD->isInvalidDecl())      return ExprError(); +  // Handle anonymous. +  if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(VD)) +    return BuildAnonymousStructUnionMemberReference(Loc, FD); +    ExprValueKind VK = getValueKindForDecl(Context, VD);    // If the identifier reference is inside a block, and it refers to a value @@ -3308,12 +3263,6 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,    }    if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { -    // We may have found a field within an anonymous union or struct -    // (C++ [class.union]). -    if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion() && -        !BaseType->getAs<RecordType>()->getDecl()->isAnonymousStructOrUnion()) -      return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, -                                                      BaseExpr, OpLoc);      // x.a is an l-value if 'a' has a reference type. Otherwise:      // x.a is an l-value/x-value/pr-value if the base is (and note @@ -3356,6 +3305,12 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,                                   MemberType, VK, OK));    } +  if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) +    // We may have found a field within an anonymous union or struct +    // (C++ [class.union]). +    return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, +                                                     BaseExpr, OpLoc); +    if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {      MarkDeclarationReferenced(MemberLoc, Var);      return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, @@ -7956,6 +7911,12 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,      LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName);      LookupQualifiedName(R, RD);      FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>(); +    IndirectFieldDecl *IndirectMemberDecl = 0; +    if (!MemberDecl) { +      if (IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>()) +        MemberDecl = IndirectMemberDecl->getAnonField(); +    } +      if (!MemberDecl)        return ExprError(Diag(BuiltinLoc, diag::err_no_member)                         << OC.U.IdentInfo << RD << SourceRange(OC.LocStart,  @@ -7974,12 +7935,8 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,      }      RecordDecl *Parent = MemberDecl->getParent(); -    bool AnonStructUnion = Parent->isAnonymousStructOrUnion(); -    if (AnonStructUnion) { -      do { -        Parent = cast<RecordDecl>(Parent->getParent()); -      } while (Parent->isAnonymousStructOrUnion()); -    } +    if (IndirectMemberDecl) +      Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext());      // If the member was found in a base class, introduce OffsetOfNodes for      // the base class indirections. @@ -7992,15 +7949,17 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc,          Comps.push_back(OffsetOfNode(B->Base));      } -    if (AnonStructUnion) { -      llvm::SmallVector<FieldDecl*, 4> Path; -      BuildAnonymousStructUnionMemberPath(MemberDecl, Path); -      unsigned n = Path.size(); -      for (int j = n - 1; j > -1; --j) -        Comps.push_back(OffsetOfNode(OC.LocStart, Path[j], OC.LocEnd)); -    } else { +    if (IndirectMemberDecl) { +      for (IndirectFieldDecl::chain_iterator FI = +           IndirectMemberDecl->chain_begin(), +           FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) { +        assert(isa<FieldDecl>(*FI)); +        Comps.push_back(OffsetOfNode(OC.LocStart, +                                     cast<FieldDecl>(*FI), OC.LocEnd)); +      } +    } else        Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); -    } +      CurrentType = MemberDecl->getType().getNonReferenceType();     } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 9458e3580c3..1b47332c53f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1429,6 +1429,11 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,        } else if (!KnownField) {          // Determine whether we found a field at all.          ReplacementField = dyn_cast<FieldDecl>(*Lookup.first); +         +        // Check if ReplacementField is an anonymous field.  +        if (!ReplacementField) +          if (IndirectFieldDecl* IField = dyn_cast<IndirectFieldDecl>(*Lookup.first)) +            ReplacementField = IField->getAnonField();        }        if (!ReplacementField) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 436488ed263..fc298c10e46 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -456,6 +456,29 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {    return Field;  } +Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { +  NamedDecl **NamedChain = +    new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; + +  int i = 0; +  for (IndirectFieldDecl::chain_iterator PI = +       D->chain_begin(), PE = D->chain_end(); +       PI != PE; ++PI) +    NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(), +                                            *PI, TemplateArgs)); + +  IndirectFieldDecl* IndirectField +    = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(), +                                D->getIdentifier(), D->getType(), +                                NamedChain, D->getChainingSize()); + + +  IndirectField->setImplicit(D->isImplicit()); +  IndirectField->setAccess(D->getAccess()); +  Owner->addDecl(IndirectField); +  return IndirectField; +} +  Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {    // Handle friend type expressions by simply substituting template    // parameters into the pattern type and checking the result. diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 9f5d0c11d19..b1e46a623e4 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -107,6 +107,7 @@ namespace clang {      void VisitCXXDestructorDecl(CXXDestructorDecl *D);      void VisitCXXConversionDecl(CXXConversionDecl *D);      void VisitFieldDecl(FieldDecl *FD); +    void VisitIndirectFieldDecl(IndirectFieldDecl *FD);      void VisitVarDecl(VarDecl *VD);      void VisitImplicitParamDecl(ImplicitParamDecl *PD);      void VisitParmVarDecl(ParmVarDecl *PD); @@ -635,6 +636,17 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {    }  } +void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { +  VisitValueDecl(FD); + +  FD->ChainingSize = Record[Idx++]; +  assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2"); +  FD->Chaining = new (*Reader.getContext())NamedDecl*[FD->ChainingSize]; + +  for (unsigned I = 0; I != FD->ChainingSize; ++I) +    FD->Chaining[I] = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); +} +  void ASTDeclReader::VisitVarDecl(VarDecl *VD) {    VisitDeclaratorDecl(VD);    VisitRedeclarable(VD); @@ -1475,6 +1487,10 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {      D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,                            false);      break; +  case DECL_INDIRECTFIELD: +    D = IndirectFieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), +                                  0, 0); +    break;    case DECL_VAR:      D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,                          SC_None, SC_None); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index f7bb23764da..27adb26d713 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -72,6 +72,7 @@ namespace clang {      void VisitCXXDestructorDecl(CXXDestructorDecl *D);      void VisitCXXConversionDecl(CXXConversionDecl *D);      void VisitFieldDecl(FieldDecl *D); +    void VisitIndirectFieldDecl(IndirectFieldDecl *D);      void VisitVarDecl(VarDecl *D);      void VisitImplicitParamDecl(ImplicitParamDecl *D);      void VisitParmVarDecl(ParmVarDecl *D); @@ -528,6 +529,17 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {    Code = serialization::DECL_FIELD;  } +void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { +  VisitValueDecl(D); +  Record.push_back(D->getChainingSize()); + +  for (IndirectFieldDecl::chain_iterator +       P = D->chain_begin(), +       PEnd = D->chain_end(); P != PEnd; ++P) +    Writer.AddDeclRef(*P, Record); +  Code = serialization::DECL_INDIRECTFIELD; +} +  void ASTDeclWriter::VisitVarDecl(VarDecl *D) {    VisitDeclaratorDecl(D);    VisitRedeclarable(D); | 

