This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/78609] invalid member's visibility detection in constexpr


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78609

Matthijs Kooijman <matthijs at stdin dot nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |matthijs at stdin dot nl

--- Comment #2 from Matthijs Kooijman <matthijs at stdin dot nl> ---
I also ran into this problem. It seems that gcc somehow inlines c_str() (or
rather, evaluates the constexpr variable it is assigned to) before visibility
checks (possibly because the constexpr is evaluated before template
initialization?).

Below is a smaller example, which is confirmed broken up to gcc 8. I could not
reduce this example any further, so it seems the essential pattern that
triggers this is:
 - There is a class instance in a constexpr variable with static storage
duration
 - A pointer to a private member of this object is accessed through a method
 - This pointer is assigned to a constexpr variable
 - This pointer is assigned in a template instantiation

Here's the code:

  class foo {
      char c;
    public:
      //constexpr foo(): c(1) { }
      //constexpr foo(char c): c(c) { }
      constexpr const char* c_str() const { return &c; }
  };

  constexpr foo basename = foo(); // Fails
  // These also fail, if you add the appropriate constructor above
  //static constexpr foo basename = foo(1); // Fails
  //static constexpr foo basename(1); // Fails
  //static constexpr foo basename{1}; // Fails
  //static constexpr foo basename{}; // Fails
  // Surprisingly this works (but needs a constructor above):
  //static constexpr foo basename; // Works

  template <class T>
  void call() {
    // This is where it breaks
    constexpr const char *unused = basename.c_str();
  }

  int main() {
    // Instantiate the call function
    call<int>();
  }

  // Removing the template argument on T makes it work
  // Letting T be deduced by adding an argument to call() also fails
  // Making the "unused" variable non-constexpr makes it work
  // Making get() return c instead of &c makes it work
  // Making "basename" a static variable inside call() also fails
  //
  // Tested on avr-gcc avr-gcc 4.9.2, gcc Debian 6.3.0-18, gcc Debian
  // 7.2.0-19, gcc Debian 8-20180110-1


$ avr-gcc ATest.cpp -std=c++11
ATest.cpp: In instantiation of ‘void call() [with T = int]’:
ATest.cpp:26:13:   required from here
ATest.cpp:2:10: error: ‘char foo::c’ is private
     char c;
          ^
ATest.cpp:21:49: error: within this context
   constexpr const char *unused = basename.c_str();
                                                 ^

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]