[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