[clang] [Clang][attr] Add 'kcfi_salt' attribute (PR #141846)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 31 05:05:20 PDT 2025
================
@@ -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
More information about the cfe-commits
mailing list