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(); ^