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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits