Bug 108231 - malloc and cleanup attributes vs extern "C" in a namespace and global and using of one in the namespace in the global one and builtins
Summary: malloc and cleanup attributes vs extern "C" in a namespace and global and usi...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2022-12-27 07:30 UTC by Bruno Haible
Modified: 2022-12-28 19:58 UTC (History)
2 users (show)

See Also:
Host: x86_64-linux-gnu
Target: x86_64-linux-gnu
Build: x86_64-linux-gnu
Known to work:
Known to fail: 11.3.0, 12.2.0
Last reconfirmed: 2022-12-27 00:00:00


Attachments
test case (182 bytes, text/plain)
2022-12-27 07:30 UTC, Bruno Haible
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bruno Haible 2022-12-27 07:30:40 UTC
Created attachment 54156 [details]
test case

The attached code, i1.cc, contains two equivalent function declarations for the function 'free'. They are equivalent because they have the same signature and both have "C" linkage.

In lines 9, 10, 12, 13, referencing the function 'free' works fine.

However, referencing it in line 17, as part of a
__attribute__ ((__malloc__ (free, 1)))
attribute, leads to an error "‘malloc’ attribute argument 1 is ambiguous".

I would expect no error, no warning.

How to reproduce:
$ g++ -S i1.cc
i1.cc:17:67: error: ‘malloc’ attribute argument 1 is ambiguous
   17 | __attribute__ ((__malloc__)) __attribute__ ((__malloc__ (free, 1)));
      |                                                                   ^
i1.cc:17:67: note: use a cast to the expected type to disambiguate
Comment 1 Andrew Pinski 2022-12-27 07:45:01 UTC
A little more reduced:
```
namespace g {
extern "C" void free(void *);
}
using g::free;
extern "C" void free (void *);

void foo1 (void *p) { free (p); }
void (*foo2) (void *) = free;
extern "C" {
void foo3 (void *p) { free (p); }
void (*foo4) (void *) = free;
}

extern "C" wchar_t * wcsdup (const wchar_t *s) 
__attribute__ ((__malloc__)) __attribute__ ((__malloc__ (free, 1)));
```
Comment 2 Andrew Pinski 2022-12-27 08:04:34 UTC
The problem is related to that free is a builtin rather than the extern "C" really.
-fno-builtin fixes the error too.
Comment 3 Andrew Pinski 2022-12-27 08:11:05 UTC
Here is another example of the same issue but with cleanup attribute instead:
```
namespace std {
extern "C" int printf (const char*, ...);
}
using std::printf;
extern "C" int printf (const char*, ...);
void foo (const char *) { printf ("%s\n", __PRETTY_FUNCTION__); }

void bar () {
    const char a __attribute__ ((cleanup (printf))) = 0;
    printf ("%s calling ", __PRETTY_FUNCTION__);
    foo (&a);
    printf ("cleanup calling ");
}

int main ()
{
    bar ();
}
```

Note if you order swap the order of declarations of printf it works.
Same with free in the original testcase for malloc.