[Bug c/89408] No constant folding when dereferencing string literals

2022-02-24 Thread srk31 at srcf dot ucam.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89408

--- Comment #7 from Stephen Kell  ---
Thanks for the backstory. I understand that 'accept as much as possible' isn't
the goal, nor would it be wise.

The pedwarn message you quoted, which explicitly makes reference to integer
constant expressions, is a good one. What's not good is that the issued
diagnostic is not that. It is not coming from c/c-typeck.cc. It seems to be
coming from c-family/c-common.cc.

I now understand why this behaviour has arisen -- the pre-4.5 compatibility
hack, combined with whatever foldings the compiler happens to do. I would still
say it's not a desirable or desired behaviour.

Arguably more desirable would be a behaviour consistent with the analogous
extension that is allowed for initializers. Of course keeping the pedwarn --
and adding one for the initializer case, which currently lacks one. Being
neither stable nor documented is still fine for many purposes (including mine).

[Bug c/89408] No constant folding when dereferencing string literals

2022-02-23 Thread srk31 at srcf dot ucam.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89408

Stephen Kell  changed:

   What|Removed |Added

 CC||srk31 at srcf dot ucam.org

--- Comment #5 from Stephen Kell  ---
I just ran into this issue myself. Even though GCC is within the C language
spec in not supporting this case, there are at least the following reasons to
consider the reported behaviour a bug.

- GCC doesn't need to reject this code. C11 6.6 pt 10 says "An implementation
may accept other forms of constant expressions."

- The error message suggests that the omission is not intentional. If it really
was about language-lawyering, it should explicitly the C-language concept of
"integer constant expressions". Currently, what it says is actually false and
confusing, because the expression clearly *does* reduce to an integer constant.
It just isn't an "integer constant expression". To me it looks like the
compiler just happens not to be doing the necessary folding in that particular
case (no pun intended).

- GCC accepts these kinds of expressions in initializers, even though the C
language also does not require this to work (because they're not in the classes
of expression listed in C11 6.6 pt 7). Test case: int x = "C"[0];

- It makes the compiler more useful, has no apparent downside, Clang supports
it, etc etc. :-)

[Bug c/96221] New: Constructor attribute priority is ignored if additional prototypes omit attribute

2020-07-16 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96221

Bug ID: 96221
   Summary: Constructor attribute priority is ignored if
additional prototypes omit attribute
   Product: gcc
   Version: 8.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: srk31 at srcf dot ucam.org
  Target Milestone: ---

Created attachment 48882
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48882&action=edit
Minimal test case

I was surprised to find that my __attribute__((constructor(101))) on a function
was not giving it priority over another constructor whose attribute used a
higher number. It turns out this was owing to an additional prototype that did
not mention the function as a constructor.

This caused a really subtle initialization bug in my code, and was tough to
track down. At the least, I would expect a warning when the information is
discarded.

I haven't tried on 8.4, but didn't see any relevant changelog entries.

Note that this is not a duplicate of 87592, which is about when the priority is
specified multiple times.

$ cat test.c
// comment these for correct behaviour, i.e. 1 then 2
static void do_init1(void);
static void do_init2(void);

static void do_init2(void) __attribute__((constructor(102)));
static void do_init2(void)
{
printf("Init 2!\n");
}

static void do_init1(void) __attribute__((constructor(101)));
static void do_init1(void)
{
printf("Init 1!\n");
}

int main(void)
{
return 0;
}

$ cc -save-tempstest.c   -o test
$ ./test
Init 2!
Init 1!
$ grep -B2 init_array test.s
.LFE0:
.size   do_init2, .-do_init2
.section.init_array,"aw"
--
.LFE1:
.size   do_init1, .-do_init1
.section.init_array

The attribute's priority argument is being discarded. It should be visible in
the section name (".init_array.0101" etc.). If the extra prototypes are
removed, the programmer-intended behaviour is restored.

[Bug preprocessor/91025] cpp man page incorrectly describes -MD option

2019-12-02 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91025

--- Comment #2 from Stephen Kell  ---
Created attachment 47405
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47405&action=edit
Patch to cpp manual page's description of -MD

It took me long enough, but I'm fairly sure this patch results in a less-wrong
cpp man page than the current one.

[Bug preprocessor/91025] New: cpp man page incorrectly describes -MD option

2019-06-27 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91025

Bug ID: 91025
   Summary: cpp man page incorrectly describes -MD option
   Product: gcc
   Version: 7.4.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: preprocessor
  Assignee: unassigned at gcc dot gnu.org
  Reporter: srk31 at srcf dot ucam.org
  Target Milestone: ---

The cpp manual page's description of the -MD option is incorrect. It would be
correct as a description of gcc's -MD option... indeed it is phrased in terms
of "if -MD is used in conjunction with -E" and "the driver", neither of which
makes sense when running cpp directly.

As far as I can tell, when running "cpp" the "without -E" semantics always
apply: if -o is given then its filename is used but with a ".d" suffix
substituted; otherwise, the same substitution is done but on the input
filename. In other words, "-o" never directly specifies the dependency output
file, whether or not "-E" is on the command line (unlike when running gcc).

I'm happy in principle to produce a patch... but haven't quite got my head
around how the man pages are generated (from the texinfo?).

[Bug c++/81211] Unhelpful error messages using template instance with non-copyable type argument

2017-06-26 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81211

--- Comment #5 from Stephen Kell  ---
I take the point in general, and I see the specific difficulty in how result_of
works.

In this specific case, there still seems to be a more low-hanging solution.
Perhaps having a lambda that is not callable ought to raise a warning? That
seems like a more straightforward diagnostic. In particular, by addressing the
lambda rather than the std::function, the problem with pointers to member
functions doesn't arise.

As for the rule of five: a fine reference, but it's rather circular to say what
amounts to "don't make mistakes in your code". :-) This error came up after a
rather large bout of refactoring that deleted slightly too much stuff

[Bug c++/81211] Unhelpful error messages using template instance with non-copyable type argument

2017-06-26 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81211

--- Comment #3 from Stephen Kell  ---
I agree that this message is better (my bad for not trying a supported
release).

It'd be nice if I didn't have to guess that the reason it's not callable is
that I omitted the copy constructor. The rules for when constructors are
defaulted/deleted are baroque enough to catch anybody out from time to time.

[Bug c++/81211] New: Unhelpful error messages using template instance with non-copyable type argument

2017-06-26 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81211

Bug ID: 81211
   Summary: Unhelpful error messages using template instance with
non-copyable type argument
   Product: gcc
   Version: 6.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: srk31 at srcf dot ucam.org
  Target Milestone: ---

Created attachment 41631
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41631&action=edit
Small test case

The following code (also attached) fails to compile, and experiments show that
the fix is to make T copy-constructible or move-constructible.

The bug is that the error messages are worse than useless, because they are
about constructing a std::function rather than a T.

(It may also be a bug in libstdc++ that std::function should require this of
its argument type, although that's not completely bonkers.)

#include 
struct T
{
T() {}
// uncomment one of the  below to make the code compile
//T(const T&) {}
//T(T&& t) {}
T& operator=(const T& arg) { return *this; }
T& operator=(T&& arg) { return *this; }
};
int main(int argc, char **argv)
{
std::function f([](T x) -> bool {
return false;
});
return 0;
}


gcc 4.9 (Debian 4.9.2-10) says:

test.cc: In function ‘int main(int, char**)’:
test.cc:15:3: error: no matching function for call to
‘std::function::function(main(int, char**)::)’
  });
   ^
test.cc:15:3: note: candidates are:
In file included from test.cc:1:0:
/usr/include/c++/4.9/functional:2226:2: note: template
std::function<_Res(_ArgTypes ...)>::function(_Functor)
  function(_Functor);
  ^
/usr/include/c++/4.9/functional:2226:2: note:   template argument
deduction/substitution failed:
/usr/include/c++/4.9/functional:2201:7: note: std::function<_Res(_ArgTypes
...)>::function(std::function<_Res(_ArgTypes ...)>&&) [with _Res = bool;
_ArgTypes = {T}]
   function(function&& __x) : _Function_base()
   ^
/usr/include/c++/4.9/functional:2201:7: note:   no known conversion for
argument 1 from ‘main(int, char**)::’ to ‘std::function&&’
/usr/include/c++/4.9/functional:2404:5: note: std::function<_Res(_ArgTypes
...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = bool;
_ArgTypes = {T}]
 function<_Res(_ArgTypes...)>::
 ^
/usr/include/c++/4.9/functional:2404:5: note:   no known conversion for
argument 1 from ‘main(int, char**)::’ to ‘const
std::function&’
/usr/include/c++/4.9/functional:2181:7: note: std::function<_Res(_ArgTypes
...)>::function(std::nullptr_t) [with _Res = bool; _ArgTypes = {T};
std::nullptr_t = std::nullptr_t]
   function(nullptr_t) noexcept
   ^
/usr/include/c++/4.9/functional:2181:7: note:   no known conversion for
argument 1 from ‘main(int, char**)::’ to ‘std::nullptr_t’
/usr/include/c++/4.9/functional:2174:7: note: std::function<_Res(_ArgTypes
...)>::function() [with _Res = bool; _ArgTypes = {T}]
   function() noexcept
   ^
/usr/include/c++/4.9/functional:2174:7: note:   candidate expects 0 arguments,
1 provided


Meanwhile, g++ 6 (Debian 6.3.0-18) says basically the same thing.

Naively at least, I'd expect the error trace to reveal something about trying
to copy a T, presumably in some non-viable constructor of std::function.

[Bug lto/78407] New: LTO breaks separate overriding of symbol aliases

2016-11-17 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78407

Bug ID: 78407
   Summary: LTO breaks separate overriding of symbol aliases
   Product: gcc
   Version: 5.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: lto
  Assignee: unassigned at gcc dot gnu.org
  Reporter: srk31 at srcf dot ucam.org
  Target Milestone: ---

Created attachment 40073
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=40073&action=edit
Test case tarball

I have a library which tests, in a constructor function, whether another
library is overriding one of its symbols. If so, it skips initialization (since
the other library is taking care of it). This is necessary because constructors
cannot meaningfully be overridden.

To do this test, I create a hidden alias of the overridable symbol. This will
always point to our copy, even if the global alias gets overridden.

int foo = 0;

extern int our_foo __attribute__((visibility("hidden"),alias("foo")));

static void (__attribute__((constructor)) init)(void)
{
if (&our_foo != &foo)
{
/* skip init */
}
else
{
/* do init */
}
}

Building this library with LTO works fine on gcc 4.9.3 and earlier. On 5.x and
6.x the address comparison gets wrongly optimised away (tested on 5.2.1 and
6.2.0). In 4.9.x I get:

06c0 :
 6c0:   55  push   %rbp
 6c1:   48 89 e5mov%rsp,%rbp
 6c4:   48 8d 05 5e 09 20 00lea0x20095e(%rip),%rax 
 6cb:   48 8b 15 06 09 20 00mov0x200906(%rip),%rdx 
 6d2:   48 39 d0cmp%rdx,%rax
 6d5:   74 1a   je 6f1 
...

i.e. a cmp instruction, whereas with 5.2.1 there is none.

06b0 :
 6b0:   55  push   %rbp
 6b1:   48 89 e5mov%rsp,%rbp
 6b4:   48 8d 35 f5 ff ff fflea-0xb(%rip),%rsi# 6b0 
 6bb:   48 8d 3d 17 00 00 00lea0x17(%rip),%rdi# 6d9 <_fini+0x9>
 6c2:   b8 00 00 00 00  mov$0x0,%eax
 6c7:   e8 c4 fe ff ff  callq  590 
 6cc:   5d  pop%rbp
 6cd:   c3  retq   

Unless I'm mistaken: for any two ELF symbol aliases, if at least one has global
visibility, LTO cannot assume they will remain aliased at run time.

Tarball attached. On doing "make run", "lib1" should only claim to initialize
itself once, but it happens twice on 5.x+.

[Bug target/63373] New: ELF symbol sizes for variable-length objects are too small

2014-09-25 Thread srk31 at srcf dot ucam.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63373

Bug ID: 63373
   Summary: ELF symbol sizes for variable-length objects are too
small
   Product: gcc
   Version: 4.9.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: srk31 at srcf dot ucam.org

Created attachment 33569
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33569&action=edit
Source files used in the bug description

Suppose I have an object file containing a data object of some variable-length
type.

$ cat section-size-test.c 
struct blah
{
float foo;
int i[];
};

struct blah b = { 42.0, { 1, 2, 3, 4, 0 } };

$ cc -c -o section-size-test.o section-size-test.c

Now I have an object of size 24 bytes. From ELF's point of view, we have a
section of size 24 but a symbol of size only 4.

$ readelf -Ss section-size-test.o

There are 9 section headers, starting at offset 0xc8:

Section Headers:
  [Nr] Name  Type Address   Offset
   Size  EntSize  Flags  Link  Info  Align
  [ 0]   NULL   
        0 0 0
  [ 1] .text PROGBITS   0040
       AX   0 0 1
  [ 2] .data PROGBITS   0040
   0018    WA   0 0 4
  [ 3] .bss  NOBITS     0058
       WA   0 0 1
  [ 4] .comment  PROGBITS   0058
   0024  0001  MS   0 0 1
  [ 5] .note.GNU-stack   PROGBITS   007c
        0 0 1
  [ 6] .shstrtab STRTAB     007c
   0045     0 0 1
  [ 7] .symtab   SYMTAB     0308
   00c0  0018   8 7 8
  [ 8] .strtab   STRTAB     03c8
   0017     0 0 1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Symbol table '.symtab' contains 8 entries:
   Num:Value  Size TypeBind   Vis  Ndx Name
 0:  0 NOTYPE  LOCAL  DEFAULT  UND 
 1:  0 FILELOCAL  DEFAULT  ABS section-size-test.c
 2:  0 SECTION LOCAL  DEFAULT1 
 3:  0 SECTION LOCAL  DEFAULT2 
 4:  0 SECTION LOCAL  DEFAULT3 
 5:  0 SECTION LOCAL  DEFAULT5 
 6:  0 SECTION LOCAL  DEFAULT4 
 7:  4 OBJECT  GLOBAL DEFAULT2 b


The bug is that when copy relocations are used, the variable-length part of the
object will get thrown away. I think the symbol size should also be 24 (hence
filing a gcc bug not a binutils bug).

Continuing: I create a shared library out of this object file, and an
executable that depends on my object.

$ cat exe.c
struct blah
{
float foo;
int i[];
};

extern struct blah b;

int main(void)
{
return (unsigned long long) &b % 32;
}


$ cc -shared -o section-size-test.so section-size-test.o
$ cc -o exe exe.c section-size-test.so

Now the executable is using a copy reloc to address my variable-length object.

$ objdump -RT exe

exe: file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
  w   D  *UND*   
_ITM_deregisterTMCloneTable
  DF *UND*    GLIBC_2.2.5 __libc_start_main
  w   D  *UND*    __gmon_start__
  w   D  *UND*   
_Jv_RegisterClasses
  w   D  *UND*   
_ITM_registerTMCloneTable
00601038 gD  .data    Base_edata
00601040 gD  .bss     Base_end
00601038 gD  .bss     Base__bss_start
00400550 gDF .init    Base_init
00601038 gDO .bss   0004  b
00400724 gDF .fini    Base_fini


DYNAMIC RELOCATION RECORDS
OFFSET   TYPE  VALUE 
00600ff8 R_X86_64_GLOB_DAT  __gmon_start__
00601038 R_X86_64_COPY b
0

[Bug c++/49609] No code emitted for address-taken instances of function templates

2011-07-01 Thread srk31 at srcf dot ucam.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

--- Comment #4 from Stephen Kell  2011-07-01 
18:09:07 UTC ---
(In reply to comment #2)
> That paragraph says that if template argument deduction succeeds then an
> instantiation is generated. In your case deduction doesn't succeed because the
> target type is not available.  The note added by DR 115 says that the
> specialization can be identified if there's a template argument list, which is
> what happens in your example, but it doesn't say that the function template is
> instantiated in that case.

Ah, I see... I was thinking that the error was spurious because I hadn't
overloaded the function, but I guess the template argument-dependence defines a
family of overloads.

> > You can make it work by using an explicit type conversion to the correct 
> > type
> > before doing the reinterpret_cast:
> > 
> > void *(*my_function_ptr)(void*, void *)
> >  = reinterpret_cast(
> > (void*(*)(float*,float*))&(value_convert_function) );
> 
> You can also make it work by not specifying an explicit template argument list
> and letting them be deduced:
> 
> void *(*my_function_ptr)(void*, void *)
>   = reinterpret_cast(
> (void*(*)(float*,float*))&value_convert_function);

Cool -- thanks for this! That teaches me for thinking I can get away without
ever using C-style casts in C++


[Bug c++/49609] New: No code emitted for address-taken instances of function templates

2011-07-01 Thread srk31 at srcf dot ucam.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49609

   Summary: No code emitted for address-taken instances of
function templates
   Product: gcc
   Version: 4.7.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassig...@gcc.gnu.org
ReportedBy: sr...@srcf.ucam.org


In the following code

template 
inline
void *
value_convert_function(From *from, To *to)
{
return 0;
}

void *(*my_table[])(void *, void *) = {
reinterpret_cast(&(value_convert_function)),
0
};

void *(*my_function_ptr)(void*, void *)
 = reinterpret_cast(&(value_convert_function));

void *(*my_uncast_function_ptr)(bool *, bool *)
 = &(value_convert_function);


... I expect to see code output for each of the three template instances that I
take the address of. But only the last one is actually generated. 

$ objdump -t test.o | c++filt

test.o: file format elf64-x86-64

SYMBOL TABLE:
 ldf *ABS*   test.cc
 ld  .text   .text
 ld  .data   .data
 ld  .bss    .bss
 ld  .text._Z22value_convert_functionIbbEPvPT_PT0_ 
 .text._Z22value_convert_functionIbbEPvPT_PT0_
 ld  .note.GNU-stack
.note.GNU-stack
 ld  .eh_frame   .eh_frame
 ld  .comment    .comment
 ld  .group  .group
 g O .data  0010 my_table
 *UND*   void*
value_convert_function(double*, double*)
0010 g O .data  0008 my_function_ptr
 *UND*   void*
value_convert_function(float*, float*)
0018 g O .data  0008 my_uncast_function_ptr
  wF .text._Z22value_convert_functionIbbEPvPT_PT0_ 
0013 void* value_convert_function(bool*, bool*)


I notice that in g++ 4.4, the code for the first two is rejected with a clearly
bogus error ("address of overloaded function with no contextual type
information").  In 4.5.1 and later, it is accepted but yields an undefined
symbol (causing link errors in my actual use-case). This also happens in the
latest sources I've tried, which are a fairly recent subversion checkout:

$ g++ --version | head -n1
g++  (GCC) 4.7.0 20110417 (experimental)

One attempted workaround was to type my table entries as void *, insert no cast
and compile with -fpermissive (to get the implicit conversion to void*). But
that reverts to the 4.4-style bogus error, even in later versions:

void *my_voidptr_table[] = { &value_convert_function, 0 };

test.cc:20: error: cannot resolve overloaded function ‘value_convert_function’
based on conversion to type ‘void*’

My workaround for now is to separately instantiate everything I want to put in
the table, by defining a bunch of static function pointers. 

Thanks for reading!