GCC has an extension on machaines with cxx_implicit_extern_c (what used to be !NO_IMPLICIT_EXTERN_C).

On such targets we'll treat 'extern "C" void Foo ()' as-if the argument list is variadic. (or something approximating that)

perhaps that is confusing things?

nathan

On 9/6/20 4:43 PM, Iain Sandoe wrote:
Jonathan Wakely via Gcc <gcc@gcc.gnu.org> wrote:

On Sun, 6 Sep 2020 at 16:23, Iain Sandoe <i...@sandoe.co.uk> wrote:

g++.dg/abi/guard3.C

has:

extern "C" int __cxa_guard_acquire();

Which might not be a suitable declaration, depending on how the ‘extern
“C”’ is supposed to affect the function signature generated.

IF, the extern C should make this parse as a “K&R” style function - then
the TYPE_ARG_TYPES should be NULL (and the testcase is OK).

However, we are parsing the decl as int __cxa_guard_acquire(void) (i.e. C++
rules on the empty parens), which makes the testcase not OK.

That is the correct parse. Using extern "C" doesn't mean the code is
C, it only affects mangling. It still has to follow C++ rules.

In practice you can still link to the definition, because its name is
just "__cxa_guard_acquire" irrespective of what parameter list is
present in the declaration.

Linking isn’t the problem in this case.

The problem is that we arrive at “expand_call” with a function decl that
says  f(void) .. and a call parmeter list containing a pointer type.

We happily pass the pointer in the place of the ‘void’ - because the code
only counts the number of entries and there’s one - so it happens to work.

.. that’s not true in the general case and for all calling conventions.

(this is what I mean by it happens to work by luck below).

This means that the declaration is now misleading (and it’s just luck that
expand_call happens to count the length of the TYPE_ARG_TYPES  list without
looking to see what the types are) - in this case it happens to work out
from this luck - since there’s only one arg so the length of the void args
list agrees with what we want.

——

So .. the question is “which is wrong, the test-case or the assignment of
the TYPE_ARG_TYPES”?

[we can’t easily diagnose this at this point, but I do have a patch to
diagnose the case where we pass a void-list to expand_call and then try to
expand a call to the callee with an inappropriate set of parms]

(it’s trivial to fix the test-case  as extern "C" int
__cxa_guard_acquire(__UINT64_TYPE__ *);, I guess)

But PR 45603 is ice-on-invalid triggered by the incorrect declaration
of __cxa_guard_acquire. So the incorrect declaration is what
originally reproduced the bug, and "fixing" it would make the test
useless.

Ah OK.

It's probably worth adding a comment about that in the test.

Yes - that would help (will add it to my TODO).

Maybe the test should give a compile-time error and XFAIL, but fixing
the declaration doesn't seem right.

I guess (because the code is invalid) there’s not much motivation to make it
more robust - e.g. diagnose the mismatch in the call(s) synthesized to
__cxa_guard_acquire.

It seems we only try to build these function decl(s) once - lazily - so that a
wrong one will persist for the whole TU (and we don’t seem to check that
the decl matches the itanium ABI - perhaps that’s intentional tho).

cheers
Iain




--
Nathan Sidwell

Reply via email to