[cfe-commits] protected anonymous union member not visible in derived class

Aaron Ballman aaron at aaronballman.com
Sun Jan 27 07:59:19 PST 2013


On Sun, Jan 27, 2013 at 12:32 AM, Nikola Smiljanic <popizdeh at gmail.com> wrote:
> Ping.
>
> Index: include/clang/Sema/Sema.h
> ===================================================================
> --- include/clang/Sema/Sema.h (revision 172709)
> +++ include/clang/Sema/Sema.h (working copy)
> @@ -2968,6 +2968,7 @@
>    BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
>                                             SourceLocation nameLoc,
>                                             IndirectFieldDecl *indirectField,
> +                                           LookupResult *R = 0,
>                                             Expr *baseObjectExpr = 0,
>                                        SourceLocation opLoc = SourceLocation());
>    ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
> Index: lib/Sema/SemaExprMember.cpp
> ===================================================================
> --- lib/Sema/SemaExprMember.cpp (revision 172709)
> +++ lib/Sema/SemaExprMember.cpp (working copy)
> @@ -669,6 +669,7 @@
>  Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
>                                                 SourceLocation loc,
>                                                 IndirectFieldDecl *indirectField,
> +                                               LookupResult *R,
>                                                 Expr *baseObjectExpr,
>                                                 SourceLocation opLoc) {
>    // First, build the expression that refers to the base object.
> @@ -734,6 +735,7 @@
>        = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
>      baseObjectIsPointer = true;
>      baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
> +    R->setBaseObjectType(ThisTy->castAs<PointerType>()->getPointeeType());
>    }
>
>    // Build the implicit member references to the field of the
> @@ -746,8 +748,9 @@
>    if (!baseVariable) {
>      FieldDecl *field = cast<FieldDecl>(*FI);
>
> -    // FIXME: use the real found-decl info!
> -    DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
> +    assert(R->getResultKind() == LookupResult::Found);
> +    NamedDecl *ND = *R->begin();
> +    DeclAccessPair foundDecl = DeclAccessPair::make(ND, ND->getAccess());
>
>      // Make a nameInfo that properly uses the anonymous name.
>      DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
> @@ -938,7 +941,7 @@
>    if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
>      // We may have found a field within an anonymous union or struct
>      // (C++ [class.union]).
> -    return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
> +    return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, &R,
>                                                      BaseExpr, OpLoc);
>
>    if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
> @@ -1649,7 +1652,7 @@
>    // (C++ [class.union]).
>    // FIXME: template-ids inside anonymous structs?
>    if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
> -    return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
> +    return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD, &R);
>
>    // If this is known to be an instance access, go ahead and build an
>    // implicit 'this' expression now.
> Index: test/CXX/class.access/class.access.base/p1.cpp
> ===================================================================
> --- test/CXX/class.access/class.access.base/p1.cpp (revision 172709)
> +++ test/CXX/class.access/class.access.base/p1.cpp (working copy)
> @@ -1,155 +1,169 @@
> -// RUN: %clang_cc1 -fsyntax-only -verify %s
> -
> -// C++0x [class.access.base]p1(a):
> -//   If a class is declared to be a base class for another class using
> -//   the public access specifier, the public members of the base class
> -//   are accessible as public members of the derived class and protected
> -//   members of the base class are accessible as protected members of
> -//   the derived class.
> -namespace test0 {
> -  class Base {
> -  public: int pub; static int spub;
> -  protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
> -  private: int priv; static int spriv; // expected-note 8 {{declared private here}}
> -  };
> -
> -  class Test : public Base {
> -    void test() {
> -      pub++;
> -      spub++;
> -      prot++;
> -      sprot++;
> -      priv++; // expected-error {{private member}}
> -      spriv++; // expected-error {{private member}}
> -
> -      Base::pub++;
> -      Base::spub++;
> -      Base::prot++;
> -      Base::sprot++;
> -      Base::priv++; // expected-error {{private member}}
> -      Base::spriv++; // expected-error {{private member}}
> -    }
> -  };
> -
> -  void test(Test *t) {
> -    t->pub++;
> -    t->spub++;
> -    t->prot++; // expected-error {{protected member}}
> -    t->sprot++; // expected-error {{protected member}}
> -    t->priv++; // expected-error {{private member}}
> -    t->spriv++; // expected-error {{private member}}
> -
> -    t->Base::pub++;
> -    t->Base::spub++;
> -    t->Base::prot++; // expected-error {{protected member}}
> -    t->Base::sprot++; // expected-error {{protected member}}
> -    t->Base::priv++; // expected-error {{private member}}
> -    t->Base::spriv++; // expected-error {{private member}}
> -  }
> -}
> -
> -// C++0x [class.access.base]p1(b):
> -//   If a class is declared to be a base class for another class using
> -//   the protected access specifier, the public and protected members
> -//   of the base class are accessible as protected members of the
> -//   derived class.
> -namespace test1 {
> -  class Base { // expected-note 6{{member is declared here}}
> -  public:
> -    int pub; // expected-note{{member is declared here}}
> -    static int spub; // expected-note{{member is declared here}}
> -  protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
> -  private: int priv; static int spriv; // expected-note 8 {{declared private here}}
> -  };
> -
> -  class Test : protected Base { // expected-note 6 {{declared protected here}} expected-note 8 {{constrained by protected inheritance here}}
> -    void test() {
> -      pub++;
> -      spub++;
> -      prot++;
> -      sprot++;
> -      priv++; // expected-error {{private member}}
> -      spriv++; // expected-error {{private member}}
> -
> -      Base::pub++;
> -      Base::spub++;
> -      Base::prot++;
> -      Base::sprot++;
> -      Base::priv++; // expected-error {{private member}}
> -      Base::spriv++; // expected-error {{private member}}
> -    }
> -  };
> -
> -  void test(Test *t) {
> -    t->pub++; // expected-error {{protected member}} expected-error {{protected base class}}
> -    t->spub++; // expected-error {{protected member}}
> -    t->prot++; // expected-error {{protected member}} expected-error {{protected base class}}
> -    t->sprot++; // expected-error {{protected member}}
> -    t->priv++; // expected-error {{private member}} expected-error {{protected base class}}
> -    t->spriv++; // expected-error {{private member}}
> -
> -    // Two possible errors here: one for Base, one for the member
> -    t->Base::pub++; // expected-error {{protected member}} expected-error {{protected base class}}
> -    t->Base::spub++; // expected-error {{protected member}}
> -    t->Base::prot++; // expected-error 2 {{protected member}} expected-error {{protected base class}}
> -    t->Base::sprot++; // expected-error 2 {{protected member}}
> -    t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{protected base class}}
> -    t->Base::spriv++; // expected-error {{protected member}} expected-error {{private member}}
> -  }
> -}
> -
> -// C++0x [class.access.base]p1(b):
> -//   If a class is declared to be a base class for another class using
> -//   the private access specifier, the public and protected members of
> -//   the base class are accessible as private members of the derived
> -//   class.
> -namespace test2 {
> -  class Base { // expected-note 6{{member is declared here}}
> -  public:
> -    int pub; // expected-note{{member is declared here}}
> -    static int spub; // expected-note{{member is declared here}}
> -  protected:
> -    int prot; // expected-note {{declared protected here}} \
> -    // expected-note{{member is declared here}}
> -    static int sprot; // expected-note {{declared protected here}} \
> -    // expected-note{{member is declared here}}
> -  private:
> -    int priv; // expected-note 4 {{declared private here}}
> -    static int spriv; // expected-note 4 {{declared private here}}
> -  };
> -
> -  class Test : private Base { // expected-note 6 {{declared private here}} \
> -                              // expected-note 10 {{constrained by private inheritance here}}
> -    void test() {
> -      pub++;
> -      spub++;
> -      prot++;
> -      sprot++;
> -      priv++; // expected-error {{private member}}
> -      spriv++; // expected-error {{private member}}
> -
> -      Base::pub++;
> -      Base::spub++;
> -      Base::prot++;
> -      Base::sprot++;
> -      Base::priv++; // expected-error {{private member}}
> -      Base::spriv++; // expected-error {{private member}}
> -    }
> -  };
> -
> -  void test(Test *t) {
> -    t->pub++; // expected-error {{private member}} expected-error {{private base class}}
> -    t->spub++; // expected-error {{private member}}
> -    t->prot++; // expected-error {{private member}} expected-error {{private base class}}
> -    t->sprot++; // expected-error {{private member}}
> -    t->priv++; // expected-error {{private member}} expected-error {{private base class}}
> -    t->spriv++; // expected-error {{private member}}
> -
> -    t->Base::pub++; // expected-error {{private member}} expected-error {{private base class}}
> -    t->Base::spub++; // expected-error {{private member}}
> -    t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{private base class}}
> -    t->Base::sprot++; // expected-error {{protected member}} expected-error {{private member}}
> -    t->Base::priv++; // expected-error 2 {{private member}} expected-error {{private base class}}
> -    t->Base::spriv++; // expected-error 2 {{private member}}
> -  }
> -}
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +// C++0x [class.access.base]p1(a):
> +//   If a class is declared to be a base class for another class using
> +//   the public access specifier, the public members of the base class
> +//   are accessible as public members of the derived class and protected
> +//   members of the base class are accessible as protected members of
> +//   the derived class.
> +namespace test0 {
> +  class Base {
> +  public: int pub; static int spub;
> +  protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
> +  private: int priv; static int spriv; // expected-note 8 {{declared private here}}
> +  };
> +
> +  class Test : public Base {
> +    void test() {
> +      pub++;
> +      spub++;
> +      prot++;
> +      sprot++;
> +      priv++; // expected-error {{private member}}
> +      spriv++; // expected-error {{private member}}
> +
> +      Base::pub++;
> +      Base::spub++;
> +      Base::prot++;
> +      Base::sprot++;
> +      Base::priv++; // expected-error {{private member}}
> +      Base::spriv++; // expected-error {{private member}}
> +    }
> +  };
> +
> +  void test(Test *t) {
> +    t->pub++;
> +    t->spub++;
> +    t->prot++; // expected-error {{protected member}}
> +    t->sprot++; // expected-error {{protected member}}
> +    t->priv++; // expected-error {{private member}}
> +    t->spriv++; // expected-error {{private member}}
> +
> +    t->Base::pub++;
> +    t->Base::spub++;
> +    t->Base::prot++; // expected-error {{protected member}}
> +    t->Base::sprot++; // expected-error {{protected member}}
> +    t->Base::priv++; // expected-error {{private member}}
> +    t->Base::spriv++; // expected-error {{private member}}
> +  }
> +}
> +
> +// C++0x [class.access.base]p1(b):
> +//   If a class is declared to be a base class for another class using
> +//   the protected access specifier, the public and protected members
> +//   of the base class are accessible as protected members of the
> +//   derived class.
> +namespace test1 {
> +  class Base { // expected-note 6{{member is declared here}}
> +  public:
> +    int pub; // expected-note{{member is declared here}}
> +    static int spub; // expected-note{{member is declared here}}
> +  protected: int prot; static int sprot; // expected-note 4 {{declared protected here}}
> +  private: int priv; static int spriv; // expected-note 8 {{declared private here}}
> +  };
> +
> +  class Test : protected Base { // expected-note 6 {{declared protected here}} expected-note 8 {{constrained by protected inheritance here}}
> +    void test() {
> +      pub++;
> +      spub++;
> +      prot++;
> +      sprot++;
> +      priv++; // expected-error {{private member}}
> +      spriv++; // expected-error {{private member}}
> +
> +      Base::pub++;
> +      Base::spub++;
> +      Base::prot++;
> +      Base::sprot++;
> +      Base::priv++; // expected-error {{private member}}
> +      Base::spriv++; // expected-error {{private member}}
> +    }
> +  };
> +
> +  void test(Test *t) {
> +    t->pub++; // expected-error {{protected member}} expected-error {{protected base class}}
> +    t->spub++; // expected-error {{protected member}}
> +    t->prot++; // expected-error {{protected member}} expected-error {{protected base class}}
> +    t->sprot++; // expected-error {{protected member}}
> +    t->priv++; // expected-error {{private member}} expected-error {{protected base class}}
> +    t->spriv++; // expected-error {{private member}}
> +
> +    // Two possible errors here: one for Base, one for the member
> +    t->Base::pub++; // expected-error {{protected member}} expected-error {{protected base class}}
> +    t->Base::spub++; // expected-error {{protected member}}
> +    t->Base::prot++; // expected-error 2 {{protected member}} expected-error {{protected base class}}
> +    t->Base::sprot++; // expected-error 2 {{protected member}}
> +    t->Base::priv++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{protected base class}}
> +    t->Base::spriv++; // expected-error {{protected member}} expected-error {{private member}}
> +  }
> +}
> +
> +// C++0x [class.access.base]p1(b):
> +//   If a class is declared to be a base class for another class using
> +//   the private access specifier, the public and protected members of
> +//   the base class are accessible as private members of the derived
> +//   class.
> +namespace test2 {
> +  class Base { // expected-note 6{{member is declared here}}
> +  public:
> +    int pub; // expected-note{{member is declared here}}
> +    static int spub; // expected-note{{member is declared here}}
> +  protected:
> +    int prot; // expected-note {{declared protected here}} \
> +    // expected-note{{member is declared here}}
> +    static int sprot; // expected-note {{declared protected here}} \
> +    // expected-note{{member is declared here}}
> +  private:
> +    int priv; // expected-note 4 {{declared private here}}
> +    static int spriv; // expected-note 4 {{declared private here}}
> +  };
> +
> +  class Test : private Base { // expected-note 6 {{declared private here}} \
> +                              // expected-note 10 {{constrained by private inheritance here}}
> +    void test() {
> +      pub++;
> +      spub++;
> +      prot++;
> +      sprot++;
> +      priv++; // expected-error {{private member}}
> +      spriv++; // expected-error {{private member}}
> +
> +      Base::pub++;
> +      Base::spub++;
> +      Base::prot++;
> +      Base::sprot++;
> +      Base::priv++; // expected-error {{private member}}
> +      Base::spriv++; // expected-error {{private member}}
> +    }
> +  };
> +
> +  void test(Test *t) {
> +    t->pub++; // expected-error {{private member}} expected-error {{private base class}}
> +    t->spub++; // expected-error {{private member}}
> +    t->prot++; // expected-error {{private member}} expected-error {{private base class}}
> +    t->sprot++; // expected-error {{private member}}
> +    t->priv++; // expected-error {{private member}} expected-error {{private base class}}
> +    t->spriv++; // expected-error {{private member}}
> +
> +    t->Base::pub++; // expected-error {{private member}} expected-error {{private base class}}
> +    t->Base::spub++; // expected-error {{private member}}
> +    t->Base::prot++; // expected-error {{protected member}} expected-error {{private member}} expected-error {{private base class}}
> +    t->Base::sprot++; // expected-error {{protected member}} expected-error {{private member}}
> +    t->Base::priv++; // expected-error 2 {{private member}} expected-error {{private base class}}
> +    t->Base::spriv++; // expected-error 2 {{private member}}
> +  }
> +}
> +
> +namespace PR12788 {
> +  class Base {
> +  protected:
> +    struct { int x; };
> +  };
> +
> +  class Test : public Base {
> +    void mem() {
> +      x++;
> +      Base::x++;
> +    }
> +  };
> +}
>

Everything LGTM, except that it seems there's a line endings change in
the test file (switched from UNIX to PC line endings).

~Aaron



More information about the cfe-commits mailing list