================
@@ -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

Reply via email to