================
@@ -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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits