[Bug c++/58040] Cannot take address-of public using-declaration of member from protected base class

2021-08-04 Thread gcc at mattwhitlock dot name via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58040

--- Comment #10 from Matt Whitlock  ---
So using declarations are not a direct replacement for user-defined thunks.
Today I learned! This makes using declarations decidedly less useful than I
believed.

Thank you for your time, Jonathan Wakely.

[Bug c++/58040] Cannot take address-of public using-declaration of member from protected base class

2021-08-04 Thread gcc at mattwhitlock dot name via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58040

--- Comment #8 from Matt Whitlock  ---
Maybe this example will demonstrate it more clearly.

/* begin example */

class PublicBase {
public:
void pub_base_pub_memb();
protected:
void pub_base_prot_memb();
};

class ProtectedBase {
public:
void prot_base_pub_memb();
protected:
void prot_base_prot_memb();
};

class Derived : public PublicBase, protected ProtectedBase {
public:
using PublicBase::pub_base_pub_memb;
using PublicBase::pub_base_prot_memb;
using ProtectedBase::prot_base_pub_memb;
using ProtectedBase::prot_base_prot_memb;
};

void (Derived::*pub_base_pub_memb)() = ::pub_base_pub_memb;
void (Derived::*pub_base_prot_memb)() = ::pub_base_prot_memb;
void (Derived::*prot_base_pub_memb)() = ::prot_base_pub_memb; // ERROR
void (Derived::*prot_base_prot_memb)() = ::prot_base_prot_memb; //
ERROR

void func(Derived *d) {
d->Derived::pub_base_pub_memb();
d->Derived::pub_base_prot_memb();
d->Derived::prot_base_pub_memb(); // OK
d->Derived::prot_base_prot_memb(); // OK

auto pub_base_pub_memb = ::pub_base_pub_memb;
auto pub_base_prot_memb = ::pub_base_prot_memb;
auto prot_base_pub_memb = ::prot_base_pub_memb; // OK
auto prot_base_prot_memb = ::prot_base_prot_memb; // OK

(d->*pub_base_pub_memb)();
(d->*pub_base_prot_memb)();
(d->*prot_base_pub_memb)(); // ERROR
(d->*prot_base_prot_memb)(); // ERROR
}

/* end example */

As you can see, it is possible to call all four member functions directly using
their qualified names, but it is not possible to assign the addresses of the
members from the protected base into variables whose type is pointer to member
function of the derived class, nor is it possible to call the members of the
protected base indirectly through pointers to member function of the derived
class.

Maybe this is a defect of the language? It's certainly an asymmetry and a
surprise.

[Bug c++/95242] New: [10 Regression] spurious "warning: zero as null pointer constant [-Wzero-as-null-pointer-constant]" on comparisons with -std=c++2a

2020-05-20 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95242

Bug ID: 95242
   Summary: [10 Regression] spurious "warning: zero as null
pointer constant [-Wzero-as-null-pointer-constant]" on
comparisons with -std=c++2a
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name
  Target Milestone: ---
  Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
 Build: x86_64-pc-linux-gnu

/* BEGIN bug.cpp */

#include 
#include 

bool bug(std::chrono::milliseconds lhs, std::chrono::milliseconds rhs) {
return lhs < rhs; // spurious "warning: zero as null pointer constant"
}

bool bug(std::string::const_iterator lhs, std::string::const_iterator rhs) {
return lhs < rhs; // spurious "warning: zero as null pointer constant"
}

/* END bug.cpp */


$ g++ -std=c++2a -Wzero-as-null-pointer-constant -c bug.cpp
bug.cpp: In function 'bool bug(std::chrono::milliseconds,
std::chrono::milliseconds)':
bug.cpp:5:15: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
5 |  return lhs < rhs; // spurious "warning: zero as null pointer constant"
  |   ^~~
bug.cpp: In function 'bool
bug(std::__cxx11::basic_string::const_iterator,
std::__cxx11::basic_string::const_iterator)':
bug.cpp:9:15: warning: zero as null pointer constant
[-Wzero-as-null-pointer-constant]
9 |  return lhs < rhs; // spurious "warning: zero as null pointer constant"
  |   ^~~


$ g++ --version | head -n1
g++ (Gentoo 10.1.0 p1) 10.1.0


The bug is not present in G++ 9.3, and it also is not present in G++ 10.1 in
-std=c++17 (or earlier) mode. This leads me to believe it may be related to the
new three-way comparison operator functionality.

[Bug libstdc++/92853] New: std::filesystem::path::operator+=(std::filesystem::path const&) corrupts the heap

2019-12-07 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92853

Bug ID: 92853
   Summary: std::filesystem::path::operator+=(std::filesystem::pat
h const&) corrupts the heap
   Product: gcc
   Version: 9.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name
  Target Milestone: ---

// BEGIN test.cpp

#include 

int main() {
using std::filesystem::path;
path p1{ "." }, p2{ "/" };
p1 += p2;   // corrupts heap
path p3{ p1 };  // CRASH!
return 0;
}

// END test.cpp


$ g++ -std=gnu++2a -o test test.cpp

$ ./test
malloc(): corrupted top size
Aborted

[Bug c++/90894] New: maybe_unused attribute is ignored on function parameters in explicitly instantiated templates

2019-06-17 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90894

Bug ID: 90894
   Summary: maybe_unused attribute is ignored on function
parameters in explicitly instantiated templates
   Product: gcc
   Version: 9.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name
  Target Milestone: ---

/* BEGIN bug.cpp */

template 
struct Base {
void func(int);
};

struct Derived : Base<0> { };

template 
void Base::func([[maybe_unused]] int n) { }  // WARNING

template class Base<0>;

/*-*/

template 
void func(int);

template void func<0>(int);

template 
void func([[maybe_unused]] int n) { }  // WARNING

/* END bug.cpp */


$ g++ -c -Wunused-parameter bug.cpp
bug.cpp: In instantiation of 'void Base::func(int) [with int X = 0]':
bug.cpp:11:16:   required from here
bug.cpp:9:6: warning: 'maybe_unused' attribute directive ignored [-Wattributes]
9 | void Base::func([[maybe_unused]] int n) { }  // WARNING
  |  ^~~
bug.cpp:3:12: warning: unused parameter 'n' [-Wunused-parameter]
3 |  void func(int);
  |^~~
bug.cpp: In instantiation of 'void func(int) [with int X = 0]':
bug.cpp:18:26:   required from here
bug.cpp:21:6: warning: 'maybe_unused' attribute directive ignored
[-Wattributes]
   21 | void func([[maybe_unused]] int n) { }  // WARNING
  |  ^~~~
bug.cpp:16:11: warning: unused parameter 'n' [-Wunused-parameter]
   16 | void func(int);
  |   ^~~


The first part of the test case (above the dashed line) demonstrates the
problem on a class template. Note that the warning disappears if the Derived
class definition is removed or is moved below the class template member
function definition.

The second part of the test case (below the dashed line) demonstrates the
problem on a function template. Note that the warning disappears if the
explicit function template instantiation is moved below the function template
definition.

[Bug c++/89519] POD data member fails to be packed; G++ incorrectly claims it is non-POD

2019-02-27 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89519

Matt Whitlock  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |WONTFIX

--- Comment #5 from Matt Whitlock  ---
I found this:

https://gcc.gnu.org/ml/gcc/2012-01/msg00056.html

It seems pretty resolute. I guess that means this report is a WONTFIX.

For what it's worth, having two conflicting definitions of "POD" is confusing.

[Bug c++/89519] POD data member fails to be packed; G++ incorrectly claims it is non-POD

2019-02-27 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89519

--- Comment #3 from Matt Whitlock  ---
(In reply to Andrew Pinski from comment #2)
> If there is a change, then using two sources one compiled with -std=c++98
> and one with -std=c++11 (or later) will not be ABI compatible.

ABI compatibility isn't guaranteed across C++ language standards anyway, is it?
For instance, the ABI of std::string differs between C++98 and C++11.

[Bug c++/89519] New: POD data member fails to be packed; G++ incorrectly claims it is non-POD

2019-02-27 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89519

Bug ID: 89519
   Summary: POD data member fails to be packed; G++ incorrectly
claims it is non-POD
   Product: gcc
   Version: 8.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name
  Target Milestone: ---

/* === BEGIN TEST CASE === */

#include 

class S {
int i;
};

struct P {
char c;
S s;
} __attribute__ ((packed));

static_assert(std::is_pod::value, "S should be a POD type");
static_assert(sizeof(P) == sizeof(char) + sizeof(S), "P should be packed");

/* === END TEST CASE === */


$ g++ -c test.cpp
test.cpp:9:4: warning: ignoring packed attribute because of unpacked non-POD
field 'S P::s'
  S s;
^
test.cpp:13:25: error: static assertion failed: P should be packed
 static_assert(sizeof(P) == sizeof(char) + sizeof(S), "P should be packed");
   ~~^~~


As you can see, S is indeed a POD type, as evidenced by std::is_pod::value
being true, yet the compiler fails to pack it.

This may be due to a discrepancy between C++'s definition of a POD type and
G++'s internal concept of "POD for the purpose of layout," as explained in Bug
83732 Comment 3.

Workaround: changing the access control of S::i to public (for example by
changing "class S" to "struct S") makes G++ pack P::s correctly. However, this
should not be necessary, as the standard only requires all non-static data
members in a standard-layout type to have the *same* access control, which need
not be public.

[Bug libstdc++/86008] std::quoted(std::basic_string_view) is missing

2018-06-04 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86008

--- Comment #2 from Matt Whitlock  ---
(In reply to Jonathan Wakely from comment #1)
> (In reply to Matt Whitlock from comment #0)
> > The following shim allows the code above to compile, although it is
> > sub-optimal because it captures a std::basic_string_view by reference.
> 
> Have you profiled to see if that matters?

No, mostly because I find micro-benchmarks to be unreliable indicators of
real-world performance. Instead, I prefer to compare the generated code.

I've made a simplified comparison that boils down the essence of what's going
on in the two cases.

/* BEGIN CODE */

#include 

struct sv_ref {
const std::string_view 
};

struct sv_val {
std::string_view sv;
};

std::ostream & operator << (std::ostream , const sv_ref ) {
// os.put('"');
for (auto c : svr.sv) {
if (c == '"' || c == '\\') {
os.put('\\');
}
os.put(c);
}
// os.put('"');
return os;
}

std::ostream & operator << (std::ostream , const sv_val ) {
// os.put('"');
for (auto c : svv.sv) {
if (c == '"' || c == '\\') {
os.put('\\');
}
os.put(c);
}
// os.put('"');
return os;
}

/* END CODE */

Plugging this code into Compiler Explorer (godbolt.org) reveals the following
relevant difference:

-operator<<(std::basic_ostream >&, sv_ref const&):
+operator<<(std::basic_ostream >&, sv_val const&):
   push r13
   push r12
   mov r12, rdi
   push rbp
   push rbx
   sub rsp, 8
-  mov rax, QWORD PTR [rsi] ; rax := 
-  mov rbp, QWORD PTR [rax+8]   ; rbp := ()->begin()
-  mov r13, QWORD PTR [rax] ; r13 := ()->size()
+  mov rbp, QWORD PTR [rsi+8]   ; rbp := svv.sv.begin()
+  mov r13, QWORD PTR [rsi] ; r13 := svv.sv.size()
   add r13, rbp
   cmp rbp, r13

As expected, the pass-by-reference case requires one additional indirect load
from memory versus the pass-by-value case.

However, this is offset by what happens on the calling side.

/* BEGIN CODE */

#include 
#include 

struct sv_ref {
const std::string_view 
};

struct sv_val {
std::string_view sv;
};

std::ostream & operator << (std::ostream , const sv_ref );
std::ostream & operator << (std::ostream , const sv_val );

const std::string_view sv;

void pass_by_ref() {
std::cout << sv_ref{ sv };
}

void pass_by_val() {
std::cout << sv_val{ sv };
}

/* END CODE */

Here we see tho following relevant difference:

-pass_by_ref():
+pass_by_val():
   sub rsp, 24
   mov edi, OFFSET FLAT:std::cout
-  mov QWORD PTR [rsp+8], OFFSET FLAT:sv
-  lea rsi, [rsp+8]
-  call operator<<(std::basic_ostream >&, sv_ref
const&)
+  mov rsi, rsp
+  mov QWORD PTR [rsp], 0
+  mov QWORD PTR [rsp+8], 0
+  call operator<<(std::basic_ostream >&, sv_val
const&)
   add rsp, 24
   ret

The pass-by-value case requires one additional indirect store to memory versus
the pass-by-reference case.

So it's a wash. And, in fact, when I combine the two above snippets of source
code into one compilation unit so that the optimizer can work its magic, the
only differences in the generated code between the two cases are the labels.
That's what I would expect too.

So you're right: although the pass-by-reference case is conceptually
sub-optimal, given the typical advice that std::string_view objects should be
passed by value, in practice it is identical.

[Bug libstdc++/86008] New: std::quoted(std::basic_string_view) is missing

2018-05-30 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86008

Bug ID: 86008
   Summary: std::quoted(std::basic_string_view) is missing
   Product: gcc
   Version: 8.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name
  Target Milestone: ---

The following code should compile without error in C++17 mode:


/* BEGIN TEST CODE */

#include 
#include 
#include 
#include 

using namespace std::literals;

int main() {
std::cout << std::quoted("foo") << '\n' // OK
  << std::quoted("bar"s) << '\n' // OK
  << std::quoted("baz"sv) << std::endl; // ERROR!
return 0;
}

/* END TEST CODE */


The following shim allows the code above to compile, although it is sub-optimal
because it captures a std::basic_string_view by reference.

#if __cpp_lib_quoted_string_io <= 201304
namespace std {
template
inline auto
quoted(const basic_string_view<_CharT, _Traits> &__sv,
   _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
{
return __detail::_Quoted_string<
const basic_string_view<_CharT, _Traits> &, _CharT>(
__sv, __delim, __escape);
}
}
#endif

The std::basic_string_view cannot be captured by value due to a static
assertion in std::__detail::_Quoted_string that requires the _String type
template argument to be a pointer or reference type.


The relevant C++ standard specifying std::quoted(std::basic_string_view) is:
https://cplusplus.github.io/LWG/issue2785

[Bug c++/58040] Cannot take address-of public using-declaration of member from protected base class

2015-12-25 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58040

--- Comment #5 from Matt Whitlock  ---
FYI, this is still a problem in G++ 5.3.0.

[Bug middle-end/192] String literals don't obey -fdata-sections

2015-05-07 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

--- Comment #17 from Matt Whitlock gcc at mattwhitlock dot name ---
(In reply to Segher Boessenkool from comment #16)

Thanks for the fix, Segher. Your patch seems more right than mine, although I
will point out that it doesn't precisely address this bug report, as it places
string literal data into unique sections only if -ffunction-sections is set,
whereas -fdata-sections has no impact. I can see arguments both ways, and
personally this distinction is irrelevant to me, as I always use for
-ffunction-sections and -fdata-sections, but the new behavior does seem
somewhat counter-intuitive to me.

Anyway, I tested your new patch (backported to GCC 4.9.2) with the use cases in
Comment 11 and Comment 15, and both produced the desired results (after I added
-ffunction-sections to the command lines in Comment 15). So I'm appeased.


[Bug middle-end/192] String literals don't obey -fdata-sections

2015-05-07 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

--- Comment #15 from Matt Whitlock gcc at mattwhitlock dot name ---
(In reply to Jakub Jelinek from comment #14)
 This doesn't really look like a good idea to me.  Instead, perhaps ld's
 --gc-sections or new special option should just remove unused string
 literals from mergeable sections.

I believe (I've read, but I haven't verified) that Gold already does this.

 With your patch, I bet you lose e.g. all tail merging.

Tail merging still works fine.

 Consider:
 const char *used1 () { return foo bar baz blah blah; }
 in one TU and
 const char *used2 () { return bar baz blah blah; }
 in another.

Okay, I'll use your example.

$ echo 'const char *used1 () { return foo bar baz blah blah; }'  tu1.c
$ echo 'const char *used2 () { return bar baz blah blah; }'  tu2.c
$ cat  main.c EOF
extern const char * used1(), * used2();
int main() { puts(used1()); puts(used2()); return 0; }
EOF

$ gcc -c -fdata-sections -fmerge-constants -o tu1.o tu1.c
$ gcc -c -fdata-sections -fmerge-constants -o tu2.o tu2.c
$ gcc -c -fdata-sections -fmerge-constants -o main.o main.c

$ objdump -s tu1.o tu2.o | fgrep -A2 .rodata
Contents of section .rodata.str1.1.b4d3fd7d:
  666f6f20 62617220 62617a20 626c6168  foo bar baz blah
 0010 20626c61 6800 blah.  
--
Contents of section .rodata.str1.1.a07ea0c2:
  62617220 62617a20 626c6168 20626c61  bar baz blah bla
 0010 6800 h.  

$ gcc -Wl,--gc-sections -o proof main.o tu1.o tu2.o

$ ./proof
foo bar baz blah blah
bar baz blah blah

$ objdump -s proof | fgrep -A2 .rodata
Contents of section .rodata:
 40061d 666f6f20 62617220 62617a20 626c6168  foo bar baz blah
 40062d 20626c61 6800 blah.  

As you can see, tail merging across translation units works fine.


[Bug middle-end/192] String literals don't obey -fdata-sections

2015-05-06 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

--- Comment #10 from Matt Whitlock gcc at mattwhitlock dot name ---
(In reply to Rahul from comment #9)
 I am also experiencing the same issue. Is there any solution for it?

You can wrap a preprocessor macro around string literals that you want to
subject to the linker's garbage collection:

  #define GCSTR(str) ({ static const char __str[] = str; __str; })

  void hello() {
  puts(GCSTR(111)); // NOT in .rodata
  puts(222);// in .rodata
  }

  int main() {
  puts(GCSTR(333)); // in .rodata
  puts(444);// in .rodata
  return 0;
  }

$ gcc -ffunction-sections -fdata-sections -Wl,--gc-sections -o gcstr gcstr.c

$ objdump -s -j .rodata gcstr

  gcstr: file format elf64-x86-64

  Contents of section .rodata:
   4005fd 32323200 34343400 3300   222.444.333.

The downside of this strategy, however, is that these strings then become
ineligible for merging, so if you have multiple *reachable* occurrences of the
same GCSTR in your code, then you'll have multiple copies of the string data in
the .rodata section of your linked binary.

These redundant copies would not be present if the compiler were correctly
outputting literal-initialized constant character arrays to sections with the
merge and strings flags set (which it should do only if
-fmerge-all-constants is set). You can simulate how this could/should work by
editing the compiler's assembly output so that it sets the section flags
appropriately.

Given this program, gcstr.c:

  #define GCSTR(str) ({ static const char __str[] = str; __str; })

  int main() {
  puts(GCSTR(111));
  puts(GCSTR(111));
  puts(111);
  return 0;
  }

Compile (but do not assemble) the program:

$ gcc -S -ffunction-sections -fdata-sections -fmerge-all-constants -o gcstr.s
gcstr.c

Edit the assembly code so that all .rodata.__str.* sections are declared with
the merge and strings flags and an entity size of 1:

$ sed -e
's/\(\.section\t\.rodata\.__str\..*\),a,\(@progbits\)$/\1,aMS,\2,1/' -i
gcstr.s

Now assemble and link the program:

$ gcc -Wl,--gc-sections -o gcstr gcstr.s

Dumping the .rodata section from the resulting executable reveals that the
linker did correctly perform string merging.

$ objdump -s -j .rodata gcstr

  gcstr: file format elf64-x86-64

  Contents of section .rodata:
   40060d 31313100 111.

Compare the above objdump output to that which results when skipping the sed
step:

   40060d 31313100 31313100 31313100   111.111.111.

The needed correction is that the compiler should, when -fmerge-all-constants
is set, emit literal-initialized constant character array data to a section
with flags aMS and entsize==sizeof(T), where T is the type of characters in
the array.

A further correction (and really the main request in this bug report) would be
for the compiler to emit string literals to discrete sections when
-fdata-sections is set.


[Bug middle-end/192] String literals don't obey -fdata-sections

2015-05-06 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

--- Comment #13 from Matt Whitlock gcc at mattwhitlock dot name ---
(In reply to H.J. Lu from comment #12)
 Would it better to use MD5 checksum on string contents?

MD5 would be slower for not much gain in uniqueness (assuming its output is
truncated to 32 bits). This application doesn't require a cryptographically
strong hash function, as the consequence of a collision is merely that a string
gets included in the binary when maybe it didn't need to be.

Actually, I would favor replacing the very old (1996) Lookup2 hash function
(implemented in libiberty/hashtab.c) with a more modern hash function, such as
MurmurHash3, CityHash, or even Lookup3, all of which are faster than Lookup2.

I would hesitate to use more than 32 bits, as the section names would start
getting rather long.


[Bug middle-end/192] String literals don't obey -fdata-sections

2015-05-06 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192

--- Comment #11 from Matt Whitlock gcc at mattwhitlock dot name ---
Created attachment 35479
  -- https://gcc.gnu.org/bugzilla/attachment.cgi?id=35479action=edit
put string literals into unique sections when -fmerge-constants -fdata-sections

This patch puts each string literal into a (probably) unique section when
compiling with -fmerge-constants -fdata-sections. The section name is
constructed from the character width and string alignment (as before) plus a
32-bit hash of the string contents.

Consider the following program:

  void used() {
  puts(keep me);
  puts(common);
  puts(string);
  puts(tail);
  }

  void not_used() {
  puts(toss me);
  puts(common);
  puts(ring);
  puts(entail);
  }

  int main() {
  used();
  return 0;
  }

$ gcc -ffunction-sections -fdata-sections -fmerge-constants \
  -Wl,--gc-sections -o test test.c

Compiling with an unpatched GCC produces a binary whose .rodata contains:

   40061d 6b656570 206d6500 636f6d6d 6f6e0073  keep me.common.s
   40062d 7472696e 6700746f 7373206d 6500656e  tring.toss me.en
   40063d 7461696c 00  tail.   

Compiling with a patched GCC produces a binary whose .rodata contains:

   40061d 6b656570 206d6500 636f6d6d 6f6e0073  keep me.common.s
   40062d 7472696e 67007461 696c00 tring.tail.


[Bug middle-end/54303] -fdata-sections -ffunction-sections and -fmerge-constants do not work well together

2015-05-06 Thread gcc at mattwhitlock dot name
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54303

--- Comment #16 from Matt Whitlock gcc at mattwhitlock dot name ---
Here's a working solution:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=192#c11


[Bug c++/58040] New: Cannot take address-of public using-declaration of member from protected base class

2013-08-01 Thread gcc at mattwhitlock dot name
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58040

Bug ID: 58040
   Summary: Cannot take address-of public using-declaration of
member from protected base class
   Product: gcc
   Version: 4.8.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: gcc at mattwhitlock dot name

$ cat EOF  test.cpp
struct Base {
void foo() { }
void bar() { }
};

struct Derived : protected Base {
void foo() { this-Base::foo(); }
using Base::bar;
};

int main() {
Derived d;
d.foo(); // OK
d.bar(); // OK
d.Derived::foo(); // OK
d.Derived::bar(); // OK
(d.*Derived::foo)(); // OK
(d.*Derived::bar)(); // error
}
EOF

$ g++-4.7.3 --version | head -n1
g++ (Gentoo 4.7.3 p1.0, pie-0.5.5) 4.7.3

$ g++-4.7.3 test.cpp
test.cpp: In function 'int main()':
test.cpp:18:19: error: 'Base' is an inaccessible base of 'Derived'

$ g++-4.8.1 --version | head -n1
g++-4.8.1 (Gentoo 4.8.1 p1.0, pie-0.5.6) 4.8.1

$ g++-4.8.1 test.cpp
test.cpp: In function 'int main()':
test.cpp:18:19: error: 'Base' is an inaccessible base of 'Derived'
 (d.*Derived::bar)(); // error
   ^