[PATCH] D110127: [Clang] Support typedef with btf_tag attributes

Yonghong Song via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 21 16:28:45 PDT 2021


yonghong-song added a comment.

In D110127#3012215 <https://reviews.llvm.org/D110127#3012215>, @aaron.ballman wrote:

>> First, to build linux kernel with btf_tag annotated user pointer, we have
>>
>> #define __user __attribute__((btf_tag("user")))
>> and the linux kernel contains code like below ([2])
>>
>> typedef __signalfn_t __user *__sighandler_t;
>> and the user attribute applies to typedef type sighandler_t.
>> So clang needs to support btf_tag attribute with typedef type
>> to avoid compilation error.
>
> I want to make sure we're clear on the semantics here. That defines `__sighandler_t` to be the type `__signalfn_t __user *`, so you expect this to annotate the type, not the declaration of the typedef. So this is about allowing `btf_tag` on types in addition to declarations?

This is a good question and below are some examples:
[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef __tag1 unsigned * __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1                                                   |
| `-RecordType 0x8234c70 'struct __va_list_tag'                                                                |
| `-Record 0x8234be8 '__va_list_tag'                                                                           |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *'                              |
|                                                                                                              | -PointerType 0x8279cc0 'unsigned int *' |
|                                                                                                              | `-BuiltinType 0x8234040 'unsigned int'  |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1"                                                            |
|

`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned __tag1 * __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1                                                   |
| `-RecordType 0x8234c70 'struct __va_list_tag'                                                                |
| `-Record 0x8234be8 '__va_list_tag'                                                                           |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *'                              |
|                                                                                                              | -PointerType 0x8279cc0 'unsigned int *' |
|                                                                                                              | `-BuiltinType 0x8234040 'unsigned int'  |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1"                                                            |
|

`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned * __tag1 __u;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1                                                   |
| `-RecordType 0x8234c70 'struct __va_list_tag'                                                                |
| `-Record 0x8234be8 '__va_list_tag'                                                                           |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:27> col:27 referenced __u 'unsigned int *'                              |
|                                                                                                              | -PointerType 0x8279cc0 'unsigned int *' |
|                                                                                                              | `-BuiltinType 0x8234040 'unsigned int'  |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1"                                                            |
|

`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef unsigned * __u __tag1;
__u u;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -TypedefDecl 0x8279c00 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]' |
| `-ConstantArrayType 0x8234e30 'struct __va_list_tag [1]' 1                                                   |
| `-RecordType 0x8234c70 'struct __va_list_tag'                                                                |
| `-Record 0x8234be8 '__va_list_tag'                                                                           |
| -TypedefDecl 0x8279d00 <t.c:2:1, col:20> col:20 referenced __u 'unsigned int *'                              |
|                                                                                                              | -PointerType 0x8279cc0 'unsigned int *' |
|                                                                                                              | `-BuiltinType 0x8234040 'unsigned int'  |
| `-BTFTagAttr 0x8279d58 <line:1:31, col:45> "tag1"                                                            |
|

`-VarDecl 0x8279df0 <line:3:1, col:5> col:5 u '__u':'unsigned int *'

You can see that it doesn't matter where the attribute is placed, the attribute is always attached to the typedef.
I think the reason is for declarations, we only allow the btf_tag attribute to be placed for record, field, var, func, typedef,
and "unsigned *" does not qualify, so the attribute is applied to typedef.

See below example for structure, the attribute can be applied to either structure or to typedef.

>> typedef struct { ... } target_type __btf_tag
>
> Similar here -- this applies the __btf_tag to the type, not to the declaration of the typedef, right?

In the above case, it actually applied to the typedef. See below example.

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef __tag1 struct { int a; } __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -RecordDecl 0x8279cb8 <t.c:2:16, col:32> col:16 struct definition               |
| `-FieldDecl 0x8279d78 <col:25, col:29> col:29 a 'int'                           |
| -TypedefDecl 0x8279e28 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
|                                                                                 | -ElaboratedType 0x8279dd0 'struct __s' sugar |
|                                                                                 | `-RecordType 0x8279d40 '__s'                 |
|                                                                                 | `-Record 0x8279cb8 ''                        |
| `-BTFTagAttr 0x8279e80 <line:1:31, col:45> "tag1"                               |
|

`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'

the attribute is attached to typedef.

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct __tag1 { int a; } __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -RecordDecl 0x8279cb8 <t.c:2:9, col:32> col:9 struct definition                 |
|                                                                                 | -BTFTagAttr 0x8279d60 <line:1:31, col:45> "tag1" |
| `-FieldDecl 0x8279de0 <line:2:25, col:29> col:29 a 'int'                        |
| -TypedefDecl 0x8279e88 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
| `-ElaboratedType 0x8279e30 'struct __s' sugar                                   |
| `-RecordType 0x8279d40 '__s'                                                    |
| `-Record 0x8279cb8 ''                                                           |
|

`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'

The attribute is attached to the structure.

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct { int a; } __tag1 __s;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -RecordDecl 0x8279c58 <t.c:2:9, col:25> col:9 struct definition                 |
|                                                                                 | -BTFTagAttr 0x8279dc8 <line:1:31, col:45> "tag1" |
| `-FieldDecl 0x8279d18 <line:2:18, col:22> col:22 a 'int'                        |
| -TypedefDecl 0x8279e88 <col:1, col:34> col:34 referenced __s 'struct __s':'__s' |
| `-ElaboratedType 0x8279e30 'struct __s' sugar                                   |
| `-RecordType 0x8279ce0 '__s'                                                    |
| `-Record 0x8279c58 ''                                                           |
|

`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'

the attribute is attached to the structure.

[$ ~/work/tests/llvm/btf_tag] cat t.c
#define __tag1 __attribute__((btf_tag("tag1")))
typedef struct { int a; } __s __tag1;
__s a;
[$ ~/work/tests/llvm/btf_tag] clang -Xclang -ast-dump -c t.c
...

| -RecordDecl 0x8279c58 <t.c:2:9, col:25> col:9 struct definition                 |
| `-FieldDecl 0x8279d18 <col:18, col:22> col:22 a 'int'                           |
| -TypedefDecl 0x8279e28 <col:1, col:27> col:27 referenced __s 'struct __s':'__s' |
|                                                                                 | -ElaboratedType 0x8279dd0 'struct __s' sugar |
|                                                                                 | `-RecordType 0x8279ce0 '__s'                 |
|                                                                                 | `-Record 0x8279c58 ''                        |
| `-BTFTagAttr 0x8279e80 <line:1:31, col:45> "tag1"                               |
|

`-VarDecl 0x8279f30 <line:3:1, col:5> col:5 a '__s':'__s'

The attribute is attached to typedef.

> I'm asking because this raises other questions. For example:
>
>   void func(int i);
>   void func(int __attribute__((btf_tag("__user"))) i);
>
> Is the second a valid redeclaration of the first? Additionally:

This should be okay as btf_tag is accumulative attribute.

>   __attribute__((overloadable)) void func(int i) { puts("one"); }
>   __attribute__((overloadable)) void func(int __attribute__((btf_tag("__user"))) i) { puts("two"); }
>
> Is this a valid overload set because of the type attribute? Along the same lines, does adding this attribute to the type cause any ABI differences in how the type is passed?

btf_tag is for C only so overload function case won't happen.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D110127/new/

https://reviews.llvm.org/D110127



More information about the cfe-commits mailing list