Bug 66957

Summary: [4.9/5/6 Regression] incorrect "is protected within this context" error
Product: gcc Reporter: dreamcooled
Component: c++Assignee: Jason Merrill <jason>
Status: RESOLVED FIXED    
Severity: normal CC: daniel.kruegler, jason, ville.voutilainen, webrown.cpp
Priority: P3 Keywords: rejects-valid
Version: 5.1.0   
Target Milestone: 4.9.4   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98662
Host: Target:
Build: Known to work: 4.3.6
Known to fail: 4.4.7, 4.9.3, 5.1.0, 6.0 Last reconfirmed: 2015-07-21 00:00:00
Bug Depends on: 38579    
Bug Blocks:    
Attachments: The code which produces the bug

Description dreamcooled 2015-07-21 15:24:05 UTC
Created attachment 36023 [details]
The code which produces the bug

In the attachment you find code which I'm trying to compile with g++.

I have a archlinux system and I have g++ version 5.1.0 from the offical repo of my system.

I'm trying to compile the attached code by invoking 
`g++ classtest.cpp`. 

gcc fires the error:
classtest.cpp: In constructor ‘DerivedB::DerivedB()’:
classtest.cpp:9:5: error: ‘int BaseClass::x’ is protected
 int BaseClass::x;
     ^
classtest.cpp:22:32: error: within this context
         std::cout << DerivedA::x;
                                ^
What I'm trying to achieve is completely legal according to the c++ standard ([class.access.base]/p5 ).

More information, discussion, and a lot of people who agree that this is indeed a gcc bug, can be found in the associated stackoverflow question: http://stackoverflow.com/questions/31389470/g-compilation-error-is-protected-from-within-this-context-while-clang-do
Comment 1 Jonathan Wakely 2015-07-21 17:23:51 UTC
class BaseClass {
protected:
  static int x;
};

struct DerivedA : BaseClass { };

struct DerivedB : BaseClass {
  DerivedB() {
    (void) DerivedA::x;
  }
};
Comment 2 Jason Merrill 2015-08-17 21:33:25 UTC
This seems to have been broken by the fix for bug 38579.  I'll revert it in the open release branches.
Comment 3 Jason Merrill 2015-08-18 14:44:17 UTC
Author: jason
Date: Tue Aug 18 14:43:44 2015
New Revision: 226974

URL: https://gcc.gnu.org/viewcvs?rev=226974&root=gcc&view=rev
Log:
	PR c++/66957
	* search.c (protected_accessible_p): Revert fix for 38579.

Added:
    branches/gcc-4_9-branch/gcc/testsuite/g++.dg/inherit/access9.C
Modified:
    branches/gcc-4_9-branch/gcc/cp/ChangeLog
    branches/gcc-4_9-branch/gcc/cp/search.c
    branches/gcc-4_9-branch/gcc/testsuite/g++.dg/conversion/access1.C
Comment 4 Jason Merrill 2015-08-18 14:44:38 UTC
Author: jason
Date: Tue Aug 18 14:44:06 2015
New Revision: 226975

URL: https://gcc.gnu.org/viewcvs?rev=226975&root=gcc&view=rev
Log:
	PR c++/66957
	* search.c (protected_accessible_p): Revert fix for 38579.

Added:
    branches/gcc-5-branch/gcc/testsuite/g++.dg/inherit/access9.C
Modified:
    branches/gcc-5-branch/gcc/cp/ChangeLog
    branches/gcc-5-branch/gcc/cp/search.c
    branches/gcc-5-branch/gcc/testsuite/g++.dg/conversion/access1.C
Comment 5 Jason Merrill 2015-08-20 01:46:21 UTC
Author: jason
Date: Thu Aug 20 01:45:49 2015
New Revision: 227023

URL: https://gcc.gnu.org/viewcvs?rev=227023&root=gcc&view=rev
Log:
	PR c++/66957
	* search.c (protected_accessible_p): Remove redundant access_in_type.
	Add otype parm instead of walking binfo.
	(friend_accessible_p): Check SCOPE itself.  Handle class
	templates.  Pass through otype.
	(dfs_accessible_post): Handle all accessibility cases.
	(dfs_accessible_pre): New.
	(accessible_p): Use it.  Don't check protected access here.  Pass
	decl and otype to dfs_walk.
	(member_declared_in_type, dfs_access_in_type_pre): New.
	(access_in_type): Use dfs_access_in_type_pre.
	* friend.c (add_friend): Fix multiple friends with the same name.

Added:
    trunk/gcc/testsuite/g++.dg/inherit/access9.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/friend.c
    trunk/gcc/cp/search.c
Comment 6 Jason Merrill 2015-08-20 02:06:00 UTC
Fixed for 4.9.4, 5.3, 6.0.
Comment 7 Ville Voutilainen 2015-08-21 11:08:51 UTC
For what it's worth, this patch looked like it might also fix
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58972, and it
does.
Comment 8 Casey Carter 2015-08-22 15:36:59 UTC
The fix for this bug seems to have broken N4381-style customization points (http://wg21.link/n4381). To wit, this program used to compile:

template <class T> T&& declval();

namespace X {
  namespace Y {
    int f(auto&&);

    struct fn {
      constexpr auto operator()(auto&& o) const {
        return f(o);
      }
    };
  }
  namespace {
    constexpr auto f = Y::fn{};
  }

  struct A {};

  struct B {
    friend double f(B&);
  };
}

static_assert(__is_same_as(int, decltype(X::f(declval<X::A&>()))));
static_assert(__is_same_as(double, decltype(X::f(declval<X::B&>()))));

but now results in the error "error: ‘f’ is not a member of ‘X’" for both static_asserts. It's possible to workaround the error be declaring the anonymous namespace inline:

inline namespace {
  constexpr auto f = Y::fn{};
}

It appears that the non-visible friend function f declared in B is incorrectly blocking name lookup of X::f before the phase of lookup that considers namespaces nominated by using directives (such as unnamed namespaces).