[Bug ipa/105682] [12/13 Regression] Both `-Wsuggest-attribute=pure` and `-Wsuggest-attribute=const` on same function since r12-5177-g494bdadf28d0fb35

2022-09-05 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105682

--- Comment #8 from sagebar at web dot de ---
(In reply to Jan Hubicka from comment #6)
> I think the conlcusion here is correct.  callee has pure attribute and that
> means that it has no side effects except for reading global memory. So
> whatever volatile assembly does has to satisfy this.
> 
> Now since assembly is not declared as reading memory, GCC concludes that the
> function has no side effects and does not read global memory and this can be
> uprgraded to const.

This assumes that reading memory is the only thing inline assembly can do to
access (part of) the global state. But consider the following example where the
ARM FPU control word is read:

```
#include  // HINT: this is arm assembly
//#define _FPU_GETCW(cw) __asm__ __volatile__("vmrs %0, fpscr" : "=r" (cw))
//#define _FPU_SETCW(cw) __asm__ __volatile__("vmsr fpscr, %0" : : "r" (cw))

__attribute__((pure))
fpu_control_t getcw() {
fpu_control_t result;
_FPU_GETCW(result);
return result;
}

int main() {
fpu_control_t before, after;
before = getcw();
_FPU_SETCW(0x1234);
after = getcw()
printf("oldcw: %d\n", before);
printf("newcw: %d\n", after);
}
```

If you're saying that a `__asm__ __volatile__` that doesn't access memory
should be considered as `const`, then gcc should be allowed to remove the first
`getcw()` and simply assign the same value to `before` and `after` (since a
`const` function's return value only depends on its arguments, meaning it calls
can be removed and re-ordered however gcc pleases).

I think you can see how that would be a problem in the above.

However: I would understand gcc doing this if `_FPU_GETCW` was implemented
using `__asm__` instead of `__asm__ __volatile__`.

(If I'm misunderstanding how `pure` is meant to work, please correct me. But as
far as I understand it, the above is a correct usage examle)

[Bug c/105676] New: Bogus `-Wsuggest-attribute=pure` on function marked `__attribute__((const))`

2022-05-20 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105676

Bug ID: 105676
   Summary: Bogus `-Wsuggest-attribute=pure` on function marked
`__attribute__((const))`
   Product: gcc
   Version: 12.1.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

When compiling with `-Wsuggest-attribute=pure`, gcc warns about missing
`__attribute__((pure))` on functions declared as `__attribute__((const))`.

It is common knowledge that any function marked as `__attribute__((const))`
also implicitly has the behavior of a function marked as
`__attribute__((pure))` (const implies pure).

Therefor, it stands to reason that such a warning is bogus (also: earlier
version of gcc didn't emit a warning in this case; know: gcc-9 already
supported these warnings, but didn't emit `-Wsuggest-attribute=pure` on a
`__attribute__((const))` function).

Example (`gcc -Wsuggest-attribute=pure -c -O2 input.c`):

```
__attribute__((const))
extern int do_expensive_calculation(void);

__attribute__((const))
int getval(void) {
static int cache = -1;
if (cache == -1)
cache = do_expensive_calculation();
return cache;
}
```

>test.c: In function 'getval':
>test.c:5:5: warning: function might be candidate for attribute 'pure' 
>>[-Wsuggest-attribute=pure]
>5 | int getval(void) {
>  | ^~

When trying to declare as both pure+const:
>test.c:5:1: warning: ignoring attribute 'const' because it conflicts with 
>attribute 'pure' [-Wattributes]
>5 | int getval(void) {
>  | ^~~


 Explaination of why using `__attribute__((const))` is valid here 

I see why gcc might think that `getval()` is *only* `pure`, but there is
nothing wrong with the `__attribute__((const))` annotation since we don't "read
global memory" (emphasis on the "global"), and thus don't depend on the global
state (also: what counts as "global" vs. "non-global" isn't something that can
be quantified. - It depends on the application and how memory is used).

As such, the use of `__attribute__((const))` is very much valid (and gcc might
even consider suggesting `__attribute__((const))` instead of
`__attribute__((pure))`, since because `cache` is scoped-static, it not being
used outside of `getval()` can actually be proven, though that isn't what this
bug report is about...). However, so-long as it believes that the function is
pure, there is no reason to ever emit a about that fact so-long as `getval()`
remains annotated as `__attribute__((const))`.

 End of Explaination 

[Bug c/105682] New: Both `-Wsuggest-attribute=pure` and `-Wsuggest-attribute=const` on same function

2022-05-21 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105682

Bug ID: 105682
   Summary: Both `-Wsuggest-attribute=pure` and
`-Wsuggest-attribute=const` on same function
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

The following example causes both a `-Wsuggest-attribute=pure` and
`-Wsuggest-attribute=const` warning for the same function. Additionally, in
this example, only `-Wsuggest-attribute=pure` would be correct (the
`-Wsuggest-attribute=const` is completely bogus):

Compile with `gcc -c -O2 -Wsuggest-attribute=const -Wsuggest-attribute=pure
input.c`:

```
__attribute__((pure))
int callee(int x) {
unsigned int a;
__asm__ __volatile__("");
__asm__ __volatile__("" : "=X" (a));
x &= 1;
if (a & 2)
__asm__ __volatile__("" : "=m" (x));
return x & 4;
}

int caller(int x) {
return callee(x);
}
```

Output (gcc-12.1.0):
>input.c: In function 'caller':
>input.c:12:5: warning: function might be candidate for attribute 'pure' 
>[-Wsuggest-attribute=pure]
>   12 | int caller(int x) {
>  | ^~
>input.c:12:5: warning: function might be candidate for attribute 'const' 
>[-Wsuggest-attribute=const]

Output (gcc-11.2.0; expected behavior):
>input.c: In function 'caller':
>input.c:12:5: warning: function might be candidate for attribute 'pure' 
>[-Wsuggest-attribute=pure]
>   12 | int caller(int x) {
>  | ^~


=== After adding `__attribute__((pure))` to `caller` ===

```
__attribute__((pure))
int caller(int x) {
return callee(x);
}
```

gcc-12.1.0 (bogus warning: `caller()` has no right to be const; it calls a pure
function, and that function even contains inline assembly):
>infile.c: In function 'caller':
>infile.c:13:5: warning: function might be candidate for attribute 'const' 
>[-Wsuggest-attribute=const]
>   13 | int caller(int x) {
>  | ^~

gcc-11.2.0 (expected behavior):
> (No warnings)

===

NOTES:
- Not only does gcc suggest to add both pure & const to the same function, the
later wouldn't even make any sense in this scenario (though suggesting `pure`
is correct).
- The strange-looking body of `callee()` is required to reproduce the bug. -
Trying to further simplify it tends to make the warning go away, suggesting a
problem with some kind of heuristic.
- I know I also just reported
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105676, but that one is about a
bogus `-Wsuggest-attribute=pure` warning, while this one is about a bogus
`-Wsuggest-attribute=const` warning. The two bugs may be related, but simply
suppressing `-Wsuggest-attribute=pure` on const-functions wouldn't be enough to
fix the bug addressed in this report.

[Bug c/105684] New: Bogus `-Warray-bounds` in partially allocated struct

2022-05-21 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105684

Bug ID: 105684
   Summary: Bogus `-Warray-bounds` in partially allocated struct
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

Accessing the fields of a partially allocated struct results in
`-Warray-bounds`, even when all accessed fields lie within the allocated
portion of the struct (a fact that can be proven to be known to gcc by asking
it for `__builtin_object_size()`)

Example (compile with `gcc -c infile.c -O2 -Warray-bounds -S -o -`):

```
struct obj {
unsigned long long kind;
union {
struct {
unsigned long long a;
} data0;
struct {
unsigned long long a;
unsigned long long b;
} data1;
};
};

extern __attribute__((alloc_size(1))) void *my_malloc(unsigned long);
#define offsetafter(s, m) (__builtin_offsetof(s, m) + sizeof(((s *)0)->m))

struct obj *create_object_kind_0(void) {
struct obj *result;
result = (struct obj *)my_malloc(offsetafter(struct obj, data0));
__asm__ __volatile__("# Object size is: %p0" : : "X"
(__builtin_object_size(result, 0)));
result->kind= 0;
result->data0.a = 1;
return result;
}
```

Real-world use-case & rationale: the idea is that access to `data1` vs. `data0`
is governed by the value of `kind` (`obj` is a "typed variant"), and by
allocating only the relevant portion of the object, we can save memory, and
create an environment where buggy code that wrongfully accesses (e.g.) certain
fields of `data1` of a `kind=0` object might cause the program to crash (rather
than remain unnoticed as would be the case when simply using `sizeof(struct
obj)` as allocation size).

Expected behavior: no warnings should be generated

== Actual behavior (Truncated) ===
>[stderr]infile.c: In function 'create_object_kind_0':
>[stderr]infile.c:22:15: warning: array subscript 'struct obj[0]' is partly 
>outside array bounds of 'unsigned char[16]' [-Warray-bounds]
>[stderr]   21 | result->kind= 0;
>[stderr]  |   ^~
>[stderr]infile.c:20:32: note: object of size 16 allocated by 'my_malloc'
>[stderr]   19 | result = (struct obj *)my_malloc(offsetafter(struct 
>obj, data0));
>[stderr]  |
>^
>[stderr]infile.c:23:15: warning: array subscript 'struct obj[0]' is partly 
>outside array bounds of 'unsigned char[16]' [-Warray-bounds]
>[stderr]   22 | result->data0.a = 1;
>[stderr]  |   ^~
>[stderr]infile.c:20:32: note: object of size 16 allocated by 'my_malloc'
>[stderr]   19 | result = (struct obj *)my_malloc(offsetafter(struct 
>obj, data0));
>[stderr]  |
>^
>[stdout][...]
>[stdout]/  22 "infile.c" 1
>[stdout]# Object size is: 16
>[stdout]/  0 "" 2
>[stdout]/NO_APP
>[stdout]movl$0, (%eax)
>[stdout]movl$0, 4(%eax)
>[stdout]movl$1, 8(%eax)
>[stdout]movl$0, 12(%eax)
>[stdout]leave
>[stdout]ret
>[stdout][...]

As can be seen by `# Object size is: 16` (and repeated in warning messages),
gcc knows that the allocated size of the object is 16 bytes, and as can be seen
by the offsets used by the `movl` instructions, this limit is never exceeded.

Judging by what the warnings state (and confirmed by replacing
`offsetafter(struct obj, data0)` with `sizeof(struct obj)`), the
`-Warray-bounds` warning will always be generated for any accessed field
(irregardless of that field's offset) so-long as `__builtin_object_size(result,
0) < sizeof(struct obj)`.

I am uncertain about the intended semantics of `-Warray-bounds`, and
technically speaking, the warning is stating the truth: "'struct obj[0]' is
partly outside array bounds" (emphasis on the "partly"). However, as it stands
right now, warning about this situation is less than useful (a warning might
arguably be useful when passing `result` -- or a pointer to one of its members
-- to some other function, but even in that situation a warning would probably
be a false positive). So in my opinion, at `-Warray-bounds[=1]`, a warning
should only be generated exactly in those cases where an out-of-bounds access
*actually* happens (*possible* out-of-bounds warnings may appear at
`-Warray-bounds=2`, but definitely shouldn't at `-Warray-bounds=1`).

==


Additionally, after making the following changes to the above code (causing
`sizeof(struct obj) == offsetafter(struct obj, data0)`):

```
@@ -6,7 +6,7 @@
} data0;

[Bug ipa/105685] New: Still Bogus `-Wsuggest-attribute=cold` on function already marked as `__attribute__((cold))`

2022-05-21 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105685

Bug ID: 105685
   Summary: Still Bogus `-Wsuggest-attribute=cold` on function
already marked as `__attribute__((cold))`
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: ipa
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
CC: marxin at gcc dot gnu.org
  Target Milestone: ---

I would re-open https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93087, but I don't
think I can so a new bug report it is... - Anyways: while my test-case from
back then remains fixed, the same problem still happens for the following code:

Run (`gcc -c -O2 -Wsuggest-attribute=cold infile.c`)
```
extern void external_fun(char *, char const *, int);

__attribute__((cold)) char *my_cold_fun(int x) {
static char b[42];
external_fun(b, "Without me, the warning disappears?", x);
return b;
}

__attribute__((cold)) char *my_other_cold_fun(int x) {
return my_cold_fun(x);
}
```

 Output 
>infile.c: In function 'my_other_cold_fun':
>infile.c:9:29: warning: function might be candidate for attribute 'cold' 
>[-Wsuggest-attribute=cold]
>9 | __attribute__((cold)) char *my_other_cold_fun(int x) {
>  | ^


 Output (Expected) 
>

[Bug c/105689] New: Bogus `-Wstringop-overflow=` after accessing field, then containing struct (wrong "region size")

2022-05-22 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105689

Bug ID: 105689
   Summary: Bogus `-Wstringop-overflow=` after accessing field,
then containing struct (wrong "region size")
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

The following code wrongly produces a warning `[-Wstringop-overflow=`:

Compile (using `gcc -c -O2 infile.c`)

```
struct subobject {
int field1;
int field2;
};

struct myobject {
struct subobject sub;
};

extern void access_1(int *a);
extern __attribute__((access(read_write, 1))) void access_2(struct subobject
*);

void myfunc(struct myobject *me) {
// { void *p __attribute__((unused)) = &me->sub; }
access_1(&me->sub.field1);
access_2(&me->sub);
}
```

=== Output (gcc-12) ===
>infile.c: In function 'myfunc':
>infile.c:16:9: warning: 'access_2' accessing 8 bytes in a region of size 4 
>[-Wstringop-overflow=]
>   16 | access_2(&me->sub);
>  | ^~
>infile.c:11:52: note: in a call to function 'access_2' declared with attribute 
>'access (read_write, 1)'
>   11 | extern __attribute__((access(read_write, 1))) void access_2(struct 
> subobject *);
>  |^~~~

=== Output (expected) ===
>


=== Notes ===

- By uncommenting the line `{ void *p __attribute__((unused)) = &me->sub; }`,
the warning goes away, even though that line literally does nothing. (see
Theory below)
- I was able to observe this bug in gcc-12.1.0 and gcc-11.2.0


=== Theory ===

It seems that this has got something to do with some internal, hidden attribute
(relating to the "region size") attached to some field-expression the first
time that field is accessed, only that when accessing `me->sub.field1` (where
`offsetof(field1) == 0`) before `me->sub`, that "region size" attribute
wrongfully also gets attached to `me->sub`. Then, when an access to `me->sub`
actually happens, gcc seems to think that the "region size" of `me->sub` as a
whole matches the size of the previously accessed field (`me->sub.field1`).

This seems further compounded by the fact that this only happens when `field1`
is the first field of `subobject` (i.e. has offset 0). If we insert another
field `int field0;` before it, the warning also disappears (so something in
gcc's logic appears to make it think that `region_size_of()
== region_size_of()`)

[Bug tree-optimization/105684] Bogus `-Warray-bounds` in partially allocated struct

2022-05-23 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105684

--- Comment #3 from sagebar at web dot de ---
>The issue is that 'result->data0.a' is (*result).data0.a, and so to GCC you are
>accessing an object of type 'obj' for which there isn't enough allocated space.

Technically true, and yes: not dereferencing `result` while it's still a
`struct obj` makes the warning go away:
```
-   result->kind= 0;
-   result->data0.a = 1;
+   *(unsigned long long *)((char *)result + __builtin_offsetof(struct obj,
kind)) = 0;
+   *(unsigned long long *)((char *)result + __builtin_offsetof(struct obj,
data0.a)) = 1;
```

But that's like saying `int x = obj->field;` is the same as `int x = ({
typeof(*obj) c = *obj; c.field; })` (i.e. accessing 1 field is like accessing
_all_ fields) -- They're just not the same: accessing a single field simply
doesn't cause the rest of the containing struct to also be loaded (if there's
some weird arch where it does ???, fine; but then this should be an
arch-specific warning).



>A workaround might be to declare 'obj' as
>
>struct obj {
>   unsigned long long kind;
>   unsigned long long data[];
>};
>
>if in your case all data is really uniform 'unsigned long long'.  There's
>no way to union several different typed flexarrays though.

It would for the demo-code, but that's not the context where I encountered this
problem in the real world. For reference, the following is the "typed
variant"-style struct which lead me to create this bug report:
https://github.com/GrieferAtWork/KOSmk4/blob/master/kos/src/kernel/moddbx/include/ctype.h#L193

I simply crafted the minimal viable code that still causes the warning for the
sake of making this bug report.

[Bug debug/111080] New: restrict qualifier leaks debug info

2023-08-20 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111080

Bug ID: 111080
   Summary: restrict qualifier leaks debug info
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: debug
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

The the following code example, debug information is retained for `struct foo`
even though that structure doesn't end up used:

Compile as `gcc -g -S -o - in.c | grep field_number`

```
struct foo {
int field_number_1;
int field_number_2;
int field_number_3;
int field_number_4;
int field_number_5;
};

typedef int fun_t(struct foo *restrict);

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

Output:
gcc -g -S -o - test.c | grep field_number
.ascii "field_number_1\0"
.ascii "field_number_2\0"
.ascii "field_number_3\0"
.ascii "field_number_4\0"
.ascii "field_number_5\0"



When removing the `restrict` qualifier in the parameter of `funptr_t`, debug
information is not included in the produced assembly (as one would expect).

Here is a list of different declarations and where `struct foo` is leaked in
gcc 12.1.0:

> typedef int fun_t(struct foo *restrict);// Leak
> typedef int fun_t(struct foo *);// No leak
> typedef int (*fun_t)(struct foo *restrict); // Leak
> typedef int (*fun_t)(struct foo *); // No leak
> extern int fun_t(struct foo *restrict); // No leak
> extern int fun_t(struct foo *); // No leak
> extern int (*fun_t)(struct foo *restrict);  // Leak
> extern int (*fun_t)(struct foo *);  // No leak
> static int fun_t(struct foo *restrict); // No leak
> static int fun_t(struct foo *); // No leak
> static int (*fun_t)(struct foo *restrict);  // Leak
> static int (*fun_t)(struct foo *);  // Leak (even w/o restrict!)
> int fun_t(struct foo *restrict);// No leak
> int fun_t(struct foo *);// No leak
> int (*fun_t)(struct foo *restrict); // Leak
> int (*fun_t)(struct foo *); // Leak (even w/o restrict!)

There is no difference when using `__restrict` or `__restrict__` instead.

[Bug debug/111080] [11/12/13/14 Regression] restrict qualifier causes extra debug info to happen

2023-08-20 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111080

--- Comment #2 from sagebar at web dot de ---
@Andrew Pinski

Of course: yes. I did make a mistake there, but only for this case:

> int (*fun_t)(struct foo *); // Leak (even w/o restrict!)

asm:
...
.globl  fun_t
.section.bss
.align 4
.type   fun_t, @object
.size   fun_t, 4
fun_t:
.zero   4
...



In the other case:

> static int (*fun_t)(struct foo *);  // Leak (even w/o restrict!)

asm:
...
# No data-symbol is generated for `fun_t`
...



Gcc actually doesn't generate a .bss-symbol for the static variable (since it's
unused), but it still generates debug inforation for `struct foo`. So I guess
strike `int (*fun_t)(struct foo *);` from the list, but keep `static int
(*fun_t)(struct foo *);` which still leaks

[Bug driver/110607] New: Makefile.in build broken build-tools when CXXFLAGS is defined

2023-07-09 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110607

Bug ID: 110607
   Summary: Makefile.in build broken build-tools when CXXFLAGS is
defined
   Product: gcc
   Version: 12.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: driver
  Assignee: unassigned at gcc dot gnu.org
  Reporter: sagebar at web dot de
  Target Milestone: ---

This part in the main makefile:

> 177 # These variables must be set on the make command line for directories
> 178 # built for the build system to override those in BASE_FLAGS_TO_PASS.
> 179 EXTRA_BUILD_FLAGS = \
> 180 CFLAGS="$(CFLAGS_FOR_BUILD)" \
> 181 LDFLAGS="$(LDFLAGS_FOR_BUILD)"

Should instead be:

> 177 # These variables must be set on the make command line for directories
> 178 # built for the build system to override those in BASE_FLAGS_TO_PASS.
> 179 EXTRA_BUILD_FLAGS = \
> 180 CFLAGS="$(CFLAGS_FOR_BUILD)" \
> 181 CXXFLAGS="$(CXXFLAGS_FOR_BUILD)" \
> 182 LDFLAGS="$(LDFLAGS_FOR_BUILD)"

Since some components of the build system are compiled as c++, if one wants to
define custom CXX-flags in cross-compilation situations, these flags then also
get used when building build-tools (which causes breakage)

[Bug bootstrap/110607] Makefile.in builds broken build-tools when CXXFLAGS is defined

2023-07-09 Thread sagebar at web dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110607

--- Comment #2 from sagebar at web dot de ---
@Andrew Pinski

Sorry if this is a known bug. I simply checked the current gcc master
(https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=Makefile.tpl;h=d0fe7e2fb778b3c3fa2cc8742e06cf1f78fdc5f2;hb=HEAD#l183),
which is still affected. I was not aware that a fix was already pending but not
yet merged.