================ @@ -3929,6 +3929,14 @@ def CFICanonicalJumpTable : InheritableAttr { let SimpleHandler = 1; } +def CFISalt : DeclOrTypeAttr { + let Spellings = [Clang<"cfi_salt">]; + let Args = [StringArgument<"Salt">]; + let Subjects = SubjectList<[Function, Field, Var, TypedefName], ErrorDiag>; ---------------- AaronBallman wrote:
Yeah, it's specifically about the placement (it's complicated). If this is stuff you already know, feel free to ignore (not trying to mansplain, I just have no idea how much folks know about these kinds of details). For attributes spelled with `__attribute__(())`, syntactic placement is not super critical because the attribute will "slide" around to whatever makes the most sense (declaration or type). But for attributes spelled with `[[]]`, placement is actually critical to the semantics. The rules of thumb there are, the attribute appertains to whatever is immediately to the left of the attribute; if the attribute is at the start of the line then it is either a stand-alone attribute (like `[[fallthrough]]`) or appertains to each declaration in a declaration group. As a concrete example: ``` [[foo]] int func [[bar]] (int x) [[baz]]; ``` `foo` appertains to the declaration `func`, the only thing in the declaration group. `bar` also applies to `func` (as a declaration attribute as well). There is no difference in semantics between how either of those attributes are applied; you could put `[[foo, bar]]` in either place and it would mean exactly the same thing. `baz` appertains to the type `int (int)`. So based on this previously being a `DeclOrTypeAttr` and the `Subjects` list, I would expect the following: ``` #define attr [[cfi_salt("I'm being lazy and using a macro")]] attr void func(); // Appertains to the declaration of func void func() attr; // Appertains to the type void() attr int x, y, z; // Appertains to the declarations of x, y, and z struct S { attr int x; // Appertains to the declaration of member x }; typedef int attr foo; // Appertains to the type int, so anywhere you use foo, you get `int attr`. typedef int bar attr; // Appertains to the declaration of foo, so anywhere you spell `bar`, you get `bar attr` which is an alias to type `int` foo f; bar b; int i; f = b; // Requires a conversion from `int` to `int attr` i = b; // No conversions i = f; // Requires a conversion from `int attr` to `int` ``` but this behavior is specific to `[[]]` spellings; for `__attribute__` we could make different decisions if we wanted as to what the attribute actually appertains to. With your latest changes to use `TypeAttr`, that will never apply to a declaration and so I think the `Subjects` list should be `FunctionLike` (only) because it applies to either function types or function pointer types. For the typedef case, that means: ``` typedef void (*fp)() attr; // Applies to the function pointer type // Instead of: typedef void (*fp attr)(); // Applies to the declaration of `foo`, which would be diagnosed as an ignored attribute ``` (Again, this is specific to the behavior with the `[[]]` spelling.) CC @erichkeane as attributes code owner in case he disagrees with anything I'm saying above or has better explanations. https://github.com/llvm/llvm-project/pull/141846 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits