[Bug c++/114643] New: Call to a template function emitted but without the code for the template function itself

2024-04-08 Thread abbeyj+gcc at gmail dot com via Gcc-bugs
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

2024-03-05 Thread abbeyj+gcc at gmail dot com via Gcc-bugs
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

2023-10-09 Thread abbeyj+gcc at gmail dot com via Gcc-bugs
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

2019-08-21 Thread abbeyj+gcc at gmail dot com
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

2019-08-16 Thread abbeyj+gcc at gmail dot com
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

2018-04-23 Thread abbeyj+gcc at gmail dot com
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#"

2017-07-31 Thread abbeyj+gcc at gmail dot com
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

2017-04-05 Thread abbeyj+gcc at gmail dot com
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

2016-08-19 Thread abbeyj+gcc at gmail dot com
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

2016-08-19 Thread abbeyj+gcc at gmail dot com
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

2016-08-18 Thread abbeyj+gcc at gmail dot com
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

2016-07-21 Thread abbeyj+gcc at gmail dot com
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

2016-05-16 Thread abbeyj+gcc at gmail dot com
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

2016-05-16 Thread abbeyj+gcc at gmail dot com
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.