Bug creation and email sending has been disabled, file new bugs at gcc.gnu.org/bugzilla
Bug 302 - UDA @attributes can not be applied to function types
Summary: UDA @attributes can not be applied to function types
Status: ASSIGNED
Alias: None
Product: GDC
Classification: Unclassified
Component: gdc (show other bugs)
Version: 8,x
Hardware: All All
: --- normal
Assignee: Iain Buclaw
URL:
Depends on:
Blocks:
 
Reported: 2018-08-15 18:54 CEST by ARaspiK
Modified: 2018-08-23 22:52 CEST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description ARaspiK 2018-08-15 18:54:55 CEST
I'm trying to port the UEFI `gnu-efi` package, for which I've found `@attribute("ms_abi")` to be immensely helpful. Unfortunately, this does not work:
```
@attribute("ms_abi") size_t function(int, int) foo; // Example, calling does not use ms_abi
size_t function(int, int) @attribute("ms_abi") foo; // ERROR: user defined attributes cannot appear as postfixes
```
Should work according to D spec at https://dlang.org/spec/declaration.html#BasicType2X function type, but does not.

```
$ gdc --verbose
Using built-in specs.
COLLECT_GCC=gdc
COLLECT_LTO_WRAPPER=/usr/local/gcc-8/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc-8.2.0/configure --enable-languages=c,c++,d --prefix=/usr/local/gcc-8 --disable-nls --enable-multilib --enable-checking=release
Thread model: posix
gcc version 8.2.0 (GCC)
```
Comment 1 Iain Buclaw 2018-08-15 20:03:58 CEST
> Should work according to D spec at https://dlang.org/spec/declaration.html#BasicType2X function type, but does not.

Nope, the error is correct and in accordance to the spec.  Only built-in attributes are allowed as postfixes - UDAs are not built-in.


> @attribute("ms_abi") size_t function(int, int) foo; // Example, calling does not use ms_abi

That could be a failing of the front-end to propagate UDAs to variables.

https://github.com/D-Programming-GDC/GDC/blob/c2fc3dbf5dc844583344f9cc6e1d4ba32bd736bf/gcc/d/decl.cc#L1321-L1328

I'll have to check.
Comment 2 ARaspiK 2018-08-15 20:42:06 CEST
Oh, OK. Thanks for responding so fast.

About that section: I have no idea what it does, but I think it looks right. I'me reading it as "If userAttributes, getAttributes, then `decl_attributes(csym, build_attributes(getAttributes)`"
There might be something at the `decl_attributes`, but it looks okay. Not sure why this is happening.

Could it be that the attribute is affecting the storage space and not the function pointer?
Comment 3 Iain Buclaw 2018-08-15 23:54:36 CEST
OK, looks like ms_abi is an attribute of the function type, not the declaration itself, and this attribute information gets lost when calling the variable, as the original type gets cast away.
Comment 4 Iain Buclaw 2018-08-16 00:05:23 CEST
Perhaps rather than using `@attribute("ms_abi")` we could extend `extern(Windows)` instead to have a special meaning on 64bit.


extern(Windows) size_t function(int, int) foo;  // Marked as 'ms_abi'.
Comment 5 ARaspiK 2018-08-16 07:30:26 CEST
Perhaps a new extern(MS_ABI) or similar is needed. After all, the spec has declared extern(Windows) to be the same as extern(C) except in case of 32-bit, where it then uses stdcall.

On other vendors, LDC will use ms_abi when compiled with -mtriple=x86_64-unknown-windows-coff, where ms_abi is specified with extern(C).
Comment 6 Iain Buclaw 2018-08-16 08:27:05 CEST
(In reply to ARaspiK from comment #5)
> Perhaps a new extern(MS_ABI) or similar is needed. After all, the spec has
> declared extern(Windows) to be the same as extern(C) except in case of
> 32-bit, where it then uses stdcall.
> 

I'm not sure if it does warrant a new calling convention, but I can see that there needs to be more careful handling of gcc type attributes through the codegen pass.  Though only function types are really affected, other kinds of type either have their own unique type decl (struct, class, enum), or we don't expose any kind of type attributes to because the language has a feature that provides for it (i.e vector attributes).

Such examples of careful handling includes emitting a warning if you assign a function with type attributes to a function pointer that has none.  Of course, if this information is part of the function type linkage in the frontend, then a compiler error will happen before the codegen stage.

Alternatively we could start disallowing assigning type attributes to functions, as there's no simple way to ensure that it will stick.

Explanation:

// Frontend attaches @ms_abi to the fdecl and fptr declarations.
// GCC codegen attaches them to the type, creating a new type variant.
@ms_abi T fdecl();
@ms_abi T function() fptr = &fdecl;

// Frontend will pass the equivalent code: (cast(T)*fptr)();
// Where T is original function type without attributes.
// This is where the information is getting lost.
fptr();


> On other vendors, LDC will use ms_abi when compiled with
> -mtriple=x86_64-unknown-windows-coff, where ms_abi is specified with
> extern(C).

That is the same for gcc also. The suggestion makes a difference only for non-windows platforms.
Comment 7 ARaspiK 2018-08-16 13:54:41 CEST
Also, this fails too, not just postfixes:
module test;

import gcc.attribute;

alias func = @attribute("ms_abi") void function(int, int);

func foo;

void main() {
  foo(2, 4);
}

gdc test.d -c -o test.o
test.d:5:35: error: user defined attributes not allowed for alias declarations
 alias func = @attribute("ms_abi") void function(int, int);
                                   ^

At least some UDAs should be allowed.