This is an archive of the discontinued LLVM Phabricator instance.

[-Wunsafe-buffer-usage] Stop generating incorrect fix-its for variable declarations with unsupported specifiers
ClosedPublic

Authored by ziqingluo-90 on Jul 24 2023, 6:15 PM.

Details

Summary

We have to give up on fixing a variable declaration if it has specifiers that are not supported yet. We cannot support them for now due to the combination of following challenges:

  • Sometimes we do not have accurate source range information for the type specifiers of a variable declaration, especially when cv-qualifiers are used (source location is not provided for type qualifiers). So it is hard to generate fix-its that only touch type specifiers for a declaration.
  • We do not have the source range information for most declaration specifiers, such as storage specifiers. So it is hard to tell whether a fix-it may quietly remove a specifier by accidentally overwriting it.
  • When the declarator is not a trivial identifier (e.g., int a[] as a parameter decl), we have to replace the whole declaration in order to fix it (e.g., to std::span<int> a). If there are other specifiers involved, they may be accidentally removed (e.g., fix int [[some_type_attribute]] a[] to std::span<int> a is incorrect).

We could support these specifiers incrementally using the same approach as how we deal with cv-qualifiers. If a fixing variable declaration has a storage specifier, instead of trying to find out the source location of the specifier or to avoid touching it, we add the keyword to a canonicalized place in the fix-it text that replaces the whole declaration.

For example, storage specifiers could be always placed at the beginning of a declaration. So both const static int * x and static const int * x will be fixed to static std::span<const int> x.

Diff Detail

Event Timeline

ziqingluo-90 created this revision.Jul 24 2023, 6:15 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 24 2023, 6:15 PM
ziqingluo-90 requested review of this revision.Jul 24 2023, 6:15 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 24 2023, 6:15 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
jkorous added inline comments.Jul 25 2023, 7:23 AM
clang/lib/Analysis/UnsafeBufferUsage.cpp
1422

typo: "accurate"

NoQ accepted this revision.Jul 25 2023, 1:44 PM

LGTM!

Yeah I agree that we can eventually support a lot of these incrementally, but it's great to establish a safe baseline first.

If there are other specifiers involved, they may be accidentally removed (e.g., fix int [[some_type_attribute]] a[] to std::span<int> a is incorrect).

Note that your patch doesn't actually address type attributes, only declaration attributes.

I'd love to learn if we handle type attributes like int *_Nonnull and int *_Nonnull *_Nonnull correctly. How do we even handle that correctly? This is no longer about preserving the attribute, it's about the very ability to put the same attribute on a span itself or on its template parameter. And in case of _Nonnull it doesn't sound like we have anything like that: there is no standard container that acts like span but is never null (and even if there was, that's not what _Nonnull really means), and we probably also can't do span<int *_Nonnull> because that's actually the same type as span<int *> (https://godbolt.org/z/oehTMbvrz).

So it's likely that we have to give up on unsupported type attributes very early, even before the fixit stage. Maybe on hasPointerType() stage; in such cases we aren't even sure that's a pointer, what if it's like an int *__attribute__((vector_size(8)))? (This actually can't happen; you can't have vectors of pointers. But something similar totally could.)

So both const static int * x and static const int * x will be fixed to static std::span<const int> x.

Ugh, const static int sounds awful because constapplies to the pointee, static applies to the pointer, then int applies to the pointee again. I hope we'll never see such code, but it's great that it works correctly!

This revision is now accepted and ready to land.Jul 25 2023, 1:44 PM

Note that your patch doesn't actually address type attributes, only declaration attributes.

It does not address type attribute. We can address it in a follow-up patch.

So it's likely that we have to give up on unsupported type attributes very early, even before the fixit stage. Maybe on hasPointerType() stage; in such cases we aren't even sure that's a pointer, what if it's like an int *__attribute__((vector_size(8)))? (This actually can't happen; you can't have vectors of pointers. But something similar totally could.)

This is a good idea!

This revision was landed with ongoing or failed builds.Aug 21 2023, 4:39 PM
This revision was automatically updated to reflect the committed changes.
ziqingluo-90 marked an inline comment as done.