[Bug c++/114643] New: Call to a template function emitted but without the code for the template function itself
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114643 Bug ID: 114643 Summary: Call to a template function emitted but without the code for the template function itself Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- When building the following example, a linker error is produced. ``` void foo(); template class DynArray { public: virtual void SetAlloc(unsigned); int *m_pElems; unsigned m_nNumElems; unsigned m_nNumAlloc; long m_nChunkSize; }; void *DoRealloc(void *, long); template void DynArray::SetAlloc(unsigned new_size) { if (m_nChunkSize) new_size = m_nChunkSize * m_nChunkSize - 1 / m_nChunkSize; else if (m_nNumAlloc) if (new_size > m_nNumAlloc / 2) new_size = new_size > m_nNumAlloc + 1 ? new_size : m_nNumAlloc * 1.5 + 1; if (m_nNumElems && m_nNumAlloc && (new_size || m_pElems)) m_pElems = (T *)DoRealloc(m_pElems, 0); } struct object { DynArray d; void f(int size); }; template void deser(int size, T ) { x.SetAlloc(0); if (size) { x.SetAlloc(size); foo(); } } void object::f(int size) { deser(size, d); } ``` Build with: $ g++ -fPIC -O3 -Wall -Werror -fvisibility=hidden reloc.cxx -shared Output: > /usr/bin/ld: /tmp/ccLaKma6.o: relocation R_X86_64_PC32 against undefined > symbol `_ZN8DynArrayIiE8SetAllocEj' can not be used when making a shared > object; recompile with -fPIC > /usr/bin/ld: final link failed: Bad value > collect2: error: ld returned 1 exit status The symbol in the above error message demangles to `DynArray::SetAlloc(unsigned int)`. The error message suggests to compile with `-fPIC` but this is already being compiled with `-fPIC`. The issue seems to be that GCC emits a call to `DynArray::SetAlloc` but doesn't emit code for `DynArray::SetAlloc` itself. The reproducer was minimized with the help of C-Reduce. Very minor changes to the code result in the problem not reproducing anymore. This is the smallest that I could manage to get it. Godbolt link: https://godbolt.org/z/1Ynz1Khac This appears to have started sometime around GCC 8.1 and still happens on the trunk version that's currently available on Godbolt.
[Bug lto/114241] New: False-positive -Wodr warning when using -flto and -fno-semantic-interposition
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114241 Bug ID: 114241 Summary: False-positive -Wodr warning when using -flto and -fno-semantic-interposition Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: lto Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- When building the following example, a `-Wodr` warning is shown. I don't think the code violates the ODR so this warning is unexpected. This reproducer consists of 3 files. d.h: ``` class A { public: virtual ~A(); virtual void a1(); }; class B : public A { public: void a1(); virtual void b1() = 0; virtual void b2() = 0; }; class C : public B { }; class D : public C { public: void b1(); void b2(); }; ``` foo.cpp: ``` #include "d.h" void foo() { D x; } ``` bar.cpp: ``` #include "d.h" void B::a1() { } void bar() { D y; } ``` Build using: g++ -fPIC -fno-semantic-interposition -flto -c foo.cpp g++ -fPIC -fno-semantic-interposition -flto -c bar.cpp g++ -shared foo.o bar.o -o lib.so Output: > d.h:14:7: warning: virtual table of type ‘struct C’ violates one definition > rule [-Wodr] >14 | class C : public B { > | ^ > d.h:14:7: note: the conflicting type defined in another translation unit has > virtual table with more entries >14 | class C : public B { > | ^ The warning message here is not great as it refers to "another translation unit" but never names either of the two translation units involved. In this reduced example there are only two translation units but when there are many translation units involved it is more difficult to figure out where the problem is coming from. The bigger issue is that I don't think this warning should have been issued at all. I can't see any way that the code is violating the ODR. The earliest version that I've been able to reproduce with is 8.4 Godbolt link: https://godbolt.org/z/ncnqPMdzq
[Bug tree-optimization/111750] New: Spurious -Warray-bounds warning when using member function pointers
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111750 Bug ID: 111750 Summary: Spurious -Warray-bounds warning when using member function pointers Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 56086 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=56086=edit Reproducer The source code below generates a -Warray-bounds warning which I believe is incorrect. Compile with `g++ -c -Wall -O2`. ``` struct MyClass { void my_method(); }; MyClass g; void pre(); inline void FetchValue(MyClass& c, void(MyClass::*func)()) { pre(); (c.*func)(); } int get_int(); inline int Check() { static const int ret = get_int(); return ret; } inline void ReadValue(MyClass& c, void(MyClass::*func)()) { Check(); FetchValue(c, func); } void Main() { ReadValue(g, ::my_method); } ``` This produces: ``` In function 'void FetchValue(MyClass&, void (MyClass::*)())', inlined from 'void ReadValue(MyClass&, void (MyClass::*)())' at :23:15, inlined from 'void Main()' at :27:14: :11:14: warning: array subscript 'int (**)(...)[0]' is partly outside array bounds of 'MyClass [1]' [-Warray-bounds=] 11 | (c.*func)(); | ~^~ : In function 'void Main()': :5:9: note: object 'g' of size 1 5 | MyClass g; | ^ ``` Godbolt link: https://godbolt.org/z/6YsWd9xhr That this source produces a -Warray-bounds warning is somewhat surprising since it contains no arrays, no array indexing, and no pointer arithmetic. Small changes such as removing the static variable or manually inlining a function into its caller make the warning go away. The earliest version that I've been able to reproduce this with is GCC 11.1 and it still reproduces on the trunk version that's currently available on godbolt.org.
[Bug c++/91506] New: Incorrectly issued error: parameter may not have variably modified type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91506 Bug ID: 91506 Summary: Incorrectly issued error: parameter may not have variably modified type Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Compiling: double test(int *arr, int x) { double ret(double(arr[x]) + 1); return ret; } produces: : In function 'double test(int*, int)': :2:23: error: parameter may not have variably modified type 'double [x]' 2 | double ret(double(arr[x]) + 1); | ^~~ It looks like this could be a Most Vexing Parse situation but clang, ICC and MSVC accept it. GCC accepts this similar code which doesn't seem like it should be treated differently from the above: double test(int *arr, int x) { int y = x; double ret(double(arr[y]) + 1); return ret; } Compiling with -std=c++03 changes things so GCC accepts the testcase. Compiling with -Wvla gets you an additional warning: :2:23: warning: variable length array 'arr' is used [-Wvla] 2 | double ret(double(arr[x]) + 1); | ^~~ This makes it seem like GCC is parsing this as a function declaration. But after the error is issued GCC ends up treating `ret` as having type `double`, not as a function; changing the code to something like `return ret.foo();` produces an error saying `... 'ret', which is of non-class type 'double'`. Testing on godbolt.org shows that this is reproducible all the way back to 4.6.4 (if using `-std=c++0x`). Version 4.5.3 does not exhibit the problem. Possibly related to bug 41786 ?
[Bug c++/91476] New: const reference variables sharing the same name in two anonymous namespaces cause a multiple definition error
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91476 Bug ID: 91476 Summary: const reference variables sharing the same name in two anonymous namespaces cause a multiple definition error Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- There is a problem when having two different variables both of which are const references and which have the same name but are in different anonymous namespaces. You'll need at least two files to reproduce this, say a.cpp and b.cpp. a.cpp: namespace { const int = 1; } int main() {} b.cpp: namespace { const int = 2; } Then compile and link: $ g++ -c a.cpp b.cpp $ g++ a.o b.o b.o:(.rodata+0x0): multiple definition of `_ZGRN12_GLOBAL__N_13fooE_' a.o:(.rodata+0x0): first defined here collect2: error: ld returned 1 exit status This works fine in older versions of GCC and in clang. Looking at the output on https://gcc.godbolt.org/z/A6LxAG shows the following differences: - The mangled name for "reference temporary #0 for (anonymous namespace)::foo" changed from _ZGRN12_GLOBAL__N_13fooE0 to _ZGRN12_GLOBAL__N_13fooE_. Interestingly, godbolt.org is unable to demangle the second name. - There is an additional line `.globl _ZGRN12_GLOBAL__N_13fooE_`. This seems like the part causing the issue. I originally found this when using objects of class type with user-defined constructors. I reduced it down to using `int` for this bug report. Any proposed fix should probably be tested with such types in addition to plain `int`. gcc version 9.1.0 (GCC) Target: x86_64-pc-linux-gnu
[Bug c++/85505] New: Code accepted despite a variable using the same name as a parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85505 Bug ID: 85505 Summary: Code accepted despite a variable using the same name as a parameter Product: gcc Version: 8.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- The following code is accepted by GCC although I believe it should not be. This happens on all versions and all platforms currently available on https://gcc.godbolt.org/ Test case: class C { public: ~C(); }; void Foo(int data) { switch (0) { case 0:; } C b; float data; } I would have expected an error here like: error: declaration of 'float data' shadows a parameter Note that you do get this error if you comment out (seemingly unrelated) lines from the test case. Shout out to https://embed.cs.utah.edu/creduce/ for providing the above reduced test case.
[Bug c++/81636] New: Confusing warning message containing "#‘obj_type_ref’ not supported by expression#"
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81636 Bug ID: 81636 Summary: Confusing warning message containing "#‘obj_type_ref’ not supported by expression#" Product: gcc Version: 7.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- This occurs with any version of GCC that I've tried that recognizes -std=c++11. It seems to affect all versions v4.7.1 through v7.1 according to https://gcc.godbolt.org/ Test case: class C { virtual int MyVirtual(); void Foo(); }; void C::Foo() { int x{ MyVirtual() / 2.0 }; } $ g++-4.9.4 -std=c++11 -c test.cpp test.cpp: In member function ‘void C::Foo()’: test.cpp:7:22: warning: narrowing conversion of ‘((double)(#‘obj_type_ref’ not supported by expression#)(this) / 2.0e+0)’ from ‘double’ to ‘int’ inside { } [-Wnarrowing] int x{ MyVirtual() / 2.0 }; ^ I believe that GCC is correct to issue a warning here. But the text of the warning message is not friendly, especially the "#‘obj_type_ref’ not supported by expression#" part.
[Bug c++/80320] New: Constructor executed twice for the same static member when using -fno-implicit-templates
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80320 Bug ID: 80320 Summary: Constructor executed twice for the same static member when using -fno-implicit-templates Product: gcc Version: 7.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 41130 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41130=edit Testcase With the attached testcase, the constructor for Foo::bar is run twice in a row with the same `this` pointer both times. bar is a static member of Foo. At exit the destructor is run twice as well. This only happens when using -fno-implicit-templates. $ make g++ -Wall -fno-implicit-templates -c -o main.o main.cpp g++ -Wall -fno-implicit-templates -c -o foo.o foo.cpp g++ main.o foo.o -o double $ ./double Bar this=0x601041 Bar this=0x601041 frob this=0x601041 ~Bar this=0x601041 ~Bar this=0x601041 I would have expected the output to look instead like: $ ./double Bar this=0x601041 frob this=0x601041 ~Bar this=0x601041 foo.cpp explicitly instantiates Foo so I'd expect foo.o to have a call to the constructor. There is one there in __static_initialization_and_destruction_0. Before the call there is a check against "guard variable for Foo::bar". main.cpp only references Foo::bar. Like in foo.o, main.o also calls Bar::Bar() from its __static_initialization_and_destruction_0. Unlike in foo.o, there is no check against "guard variable for Foo::bar". I don't know exactly what's supposed to happen with -fno-implicit-templates and static members. I initially expected that main.o would not try to construct any static members since they were not explicitly instantiated. If that were the case then the static would only be constructed by foo.o and things would work correctly. Possibly that's not the desired behavior and static members are intended to be instantiated implicitly even with -fno-implicit-templates in effect. If that is the case then the generated code seems buggy since it doesn't include the check against the guard variable. I've tested this on various versions of GCC and it occurs on 4.4.7, 4.9.2, 6.3.0 and a copy of 7.0.1 built from trunk so this does not seem like a recent regression.
[Bug c++/77306] Unable to specify visibility for explicit template instantiations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77306 --- Comment #1 from James Abbatiello <abbeyj+gcc at gmail dot com> --- Created attachment 39478 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39478=edit Patch
[Bug c++/77306] New: Unable to specify visibility for explicit template instantiations
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77306 Bug ID: 77306 Summary: Unable to specify visibility for explicit template instantiations Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 39477 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39477=edit Reproducer This bug is being filed as a request for a more limited form of attributes than that which was rejected in bug #71154. That bug requested any attribute be allowed on an explicit template instantiation. This bug limits the scope to just __attribute__((visibility)) which should hopefully be more acceptable. The visibility attribute is somewhat different from other attributes in that it doesn't affect the layout or semantics of the type. Trying to apply a visibility("default") attribute to an explicit template instantiation does not work if the type has been previously mentioned in the translation unit. STR: == $ cat main.cpp template class C { void foo(); }; C g_c_int; C g_c_double; template void C::foo() {} template class __attribute__((visibility("default"))) C; template class C; $ g++ -fvisibility=hidden -fPIC -shared main.cpp -o main.so main.cpp:13:55: warning: type attributes ignored after type is already defined [-Wattributes] template class __attribute__((visibility("default"))) C; ^~ $ nm -C main.so | grep foo 061c t C::foo() 0610 t C::foo() == Note that C::foo() is marked as local (lowercase t) when the intent was to make it global (uppercase). When compiled with clang++ instead there are no warnings and nm reports: 0510 t C::foo() 0500 W C::foo() where C::foo() is global as desired. Similar code, with the __attribute__ replaced with __declspec(dllexport), works as expected with MSVC 2012. That is, C::foo() is exported from the DLL and C::foo() is not. I have a patch for this which I will attach. It relaxes the existing check to allow attributes on a type that has already been defined as long as the attribute is a visibility attribute.
[Bug c++/77291] New: False positive for -Warray-bounds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77291 Bug ID: 77291 Summary: False positive for -Warray-bounds Product: gcc Version: 6.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 39473 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39473=edit Test case Testcase: struct Rec { unsigned char data[1]; // actually variable length }; union U { unsigned char buf[42]; struct Rec rec; }; int Load() { union U u; return u.rec.data[1]; } == When compiled with either of $ gcc -c -O2 -Warray-bounds array_bounds.c or $ g++ -c -O2 -Warray-bounds array_bounds.cpp produces array_bounds.c: In function ‘Load’: array_bounds.c:13:20: warning: array subscript is above array bounds [-Warray-bounds] return u.rec.data[1]; ~~^~~ There's an exception for accessing beyond the end of an array if that array is the last member in a struct. In that case it is assumed the user is using the so-called "struct hack". So, for instance, this doesn't warn: int F(struct Rec *r) { return r->data[1]; } But the warning *is* issued if the variable is allocated as an auto stack variable since then the compiler knows the exact size allocated. So this example does warn: int G() { struct Rec r; return r.data[1]; } I'm assuming that the compiler is treating the test case more like this last example since u.rec is on the stack. But I believe the warning is incorrect since the union should provide enough space. Would it be possible to disable this warning if the struct is on the stack but is also part of a union? I guess you could even try to figure out from the union how much space is available and what the largest allowable index is but that seems like a lot of effort to spend on what is going to be a rare case. Please ignore the reading of uninitialized data in the testcase. This can be remedied by initializing before reading but the initialization must be done in a separate translation unit. If it is done in this translation unit the optimizer causes the warning to disappear. To keep the testcase to one file, I left the initialization out.
[Bug c++/71154] Attributes for an explicit template instantiation are ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71154 --- Comment #3 from James Abbatiello <abbeyj+gcc at gmail dot com> --- Andrew Pinsky, I'm not sure I understand your comment. Why would the visibility of D be affected by the visibility of C? If I change your test case so that C is declared as hidden before the definition of D then I get this warning: warning: ‘D’ declared with greater visibility than the type of its field ‘D::a’ [-Wattributes] But it is just a warning and it does not cause D to have hidden visibility. Did you have some different test in mind? I've also tried your testcase with clang++ and it acts as I would expect (D is visible, C is hidden). So it seems that it is possible to support this behavior even if it might be difficult within g++ for some reason. Can you please unresolve this bug? Limit it just the visibility attribute if you need to but I still want this change.
[Bug c++/71154] Attributes for an explicit template instantiation are ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71154 --- Comment #1 from James Abbatiello <abbeyj+gcc at gmail dot com> --- Created attachment 38502 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38502=edit Too simple patch
[Bug c++/71154] New: Attributes for an explicit template instantiation are ignored
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71154 Bug ID: 71154 Summary: Attributes for an explicit template instantiation are ignored Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 38501 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38501=edit Reproducer Trying to apply attributes (like visibility("default")) to an explicit template instantiation does not work if the type has been previously mentioned in the translation unit. This was previously reported as part of bug #50044. But that bug was eventually marked as a duplicate of bug #40068 which only seems to cover the problem with typeinfo. The part about the problem with attributes seems to have been lost so I'm opening this bug to cover it. STR: == $ cat main.cpp template class C { void foo(); }; C g_c_int; C g_c_double; template void C::foo() {} template class __attribute__((visibility("default"))) C; template class C; $ g++ -fvisibility=hidden -fPIC -shared main.cpp -o main.so main.cpp:13:55: warning: type attributes ignored after type is already defined [-Wattributes] template class __attribute__((visibility("default"))) C; ^~ $ nm -C main.so | grep foo 061c t C::foo() 0610 t C::foo() == Note that C::foo() is marked as local (lowercase t) when the intent was to make it global (uppercase). When compiled with clang++ instead there are no warnings and nm reports: 0510 t C::foo() 0500 W C::foo() where C::foo() is global as desired. Similar code, with the __attribute__ replaced with __declspec(dllexport), works as expected with MSVC 2012. That is, C::foo() is exported from the DLL and C::foo() is not. I have a patch for this which I will attach. It just removes the relevant checks entirely. This seems likely to cause problems elsewhere but perhaps it gives somebody an idea on where to start.