Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different attribute positions for 'noderef' has surprising behaviors #116242

Open
AaronBallman opened this issue Nov 14, 2024 · 3 comments
Open
Labels
bug Indicates an unexpected problem or unintended behavior clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@AaronBallman
Copy link
Collaborator

While working on an unrelated crash, I noticed that the noderef attribute is highly sensitive to syntactic position as a GNU-style attribute, and the behavior seems inconsistent.

// When written before the declaration, it works.
__attribute__((noderef)) int * a;
int w = *a;

// When written in this location on the type, it works.
int __attribute__((noderef)) * b;
int x = *b;

// But when written in this location on the type, it gets loudly ignored.
int * __attribute__((noderef)) c;
int y = *c;

// And when written on the declarator, it gets quietly ignored, but only
// sort of (note the AST dump).
int * d __attribute__((noderef));
int z = *d;

https://godbolt.org/z/hesz5M4K8

I'm mostly surprised by the behavior of c and d. I would expect c to work because the attribute is written on a pointer type and I would sort of expect d to ignore the attribute loudly because it's a type attribute written on a declarator (I could also see "sliding" the attribute to the type because this is a GNU-style spelling).

@AaronBallman AaronBallman added bug Indicates an unexpected problem or unintended behavior clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 14, 2024
@llvmbot
Copy link

llvmbot commented Nov 14, 2024

@llvm/issue-subscribers-bug

Author: Aaron Ballman (AaronBallman)

While working on an unrelated crash, I noticed that the `noderef` attribute is highly sensitive to syntactic position as a GNU-style attribute, and the behavior seems inconsistent. ``` // When written before the declaration, it works. __attribute__((noderef)) int * a; int w = *a;

// When written in this location on the type, it works.
int attribute((noderef)) * b;
int x = *b;

// But when written in this location on the type, it gets loudly ignored.
int * attribute((noderef)) c;
int y = *c;

// And when written on the declarator, it gets quietly ignored, but only
// sort of (note the AST dump).
int * d attribute((noderef));
int z = *d;

https://godbolt.org/z/hesz5M4K8

I'm mostly surprised by the behavior of `c` and `d`. I would expect `c` to work because the attribute is written on a pointer type and I would sort of expect `d` to ignore the attribute loudly because it's a type attribute written on a declarator (I could also see "sliding" the attribute to the type because this is a GNU-style spelling).
</details>

@llvmbot
Copy link

llvmbot commented Nov 14, 2024

@llvm/issue-subscribers-clang-frontend

Author: Aaron Ballman (AaronBallman)

While working on an unrelated crash, I noticed that the `noderef` attribute is highly sensitive to syntactic position as a GNU-style attribute, and the behavior seems inconsistent. ``` // When written before the declaration, it works. __attribute__((noderef)) int * a; int w = *a;

// When written in this location on the type, it works.
int attribute((noderef)) * b;
int x = *b;

// But when written in this location on the type, it gets loudly ignored.
int * attribute((noderef)) c;
int y = *c;

// And when written on the declarator, it gets quietly ignored, but only
// sort of (note the AST dump).
int * d attribute((noderef));
int z = *d;

https://godbolt.org/z/hesz5M4K8

I'm mostly surprised by the behavior of `c` and `d`. I would expect `c` to work because the attribute is written on a pointer type and I would sort of expect `d` to ignore the attribute loudly because it's a type attribute written on a declarator (I could also see "sliding" the attribute to the type because this is a GNU-style spelling).
</details>

@zygoloid
Copy link
Collaborator

Allowing c seems a bit scary, given that

typedef int * __attribute__((noderef)) p;
p a;
p *b;

might be expected to interpret the attribute in completely different ways. In general, I think we should be a bit cautious about sliding the attribute from pointer to pointee when it could be meaningful in both places.

We produce a warning on the declaration of p, saying that the attribute can't go there, but it actually does work and causes *b (and not *a) to produce warnings. I wonder if we should suppress that attribute when declaring a typedef.

Definitely makes sense to me to reject either the declaration of d (no sliding) or the dereference of it (sliding it some distance to the left).

Though as a general concern: moving attributes to somewhere other than where they were written is a semantically horrible thing to do, and I don't think it's good for our users. Doing it for GCC's attributes makes sense for compatibility (though it'd be nice to warn when we do so), but for Clang-only attributes maybe we should not do so as a matter of policy (regardless of whether GNU attribute syntax is used)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

3 participants