This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Add Fuchsia checker for visibility attributes
AbandonedPublic

Authored by juliehockett on Feb 16 2018, 8:47 AM.

Details

Summary

Adding a checker to find a function given its name and add a given visibility attribute if none is present (i.e. __attribute__((visibility("hidden"))).

Diff Detail

Event Timeline

juliehockett created this revision.Feb 16 2018, 8:47 AM
aaron.ballman added inline comments.Feb 16 2018, 9:37 AM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
33

Would it make more sense to store a list of names and then find all of them at once, rather than a single name at a time?

35

It'd be nice to pick a slightly better string literal to use.

41

This diagnostic doesn't really tell the user what's wrong with their code.

test/clang-tidy/fuchsia-add-visibility.cpp
11

I'd also like to see tests where the attribute is already present on the definition (to ensure it doesn't get added), or is already present on the declaration and is inherited on the definition.

What should happen with code like this:

__attribute__((visibility("internal"))) void f();

void f() {

}

Will this check attempt to add __attribute__((visibility("hidden"))) to the definition?

Eugene.Zelenko added inline comments.
docs/ReleaseNotes.rst
60

Please move into new checks section.

63

Check to find -> Finds.

docs/clang-tidy/checks/fuchsia-add-visibility.rst
7

Check to find -> Finds.

I'd like a test for #pragma GCC visibility push(hidden) which should cause each symbol to be treated as though it were explicitly hidden.

clang-tidy/fuchsia/AddVisibilityCheck.cpp
33

+1 on this we generally want to make this change to many different functions at the same time.

I'd like a test for #pragma GCC visibility push(hidden) which should cause each symbol to be treated as though it were explicitly hidden.

To clarify, this check should still give a warning if the specified variable doesn't actually have that in source code. e.g. simply because "#pragma GCC visibility push(hidden)" was at the top dosn't mean these functions should get a pass.

juliehockett marked 7 inline comments as done.
juliehockett edited the summary of this revision. (Show Details)
  1. Added visibility parameter
  2. Updated Name parameter to be a list of names, as opposed to a single name
  3. Fixed comments and documentation
aaron.ballman added inline comments.Feb 16 2018, 1:22 PM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
37–40

Rather than do this, you should use parseStringList() from OptionsUtils.h. This will also ensure you don't use the wrong separator (we use semi-colons for this, not commas).

49

You should use serializeStringList() for this.

See InefficientVectorOperationCheck for an example of parsing and serializing the string lists.

57

Rather than a for loop, you can pass the list to hasAnyName().

64

Once you drop the for loop, you can pick a single name to bind to -- the check() function will be called once for each match anyway, so you don't need an explicit loop checking all of the name.

66–67

You should use a Twine to construct this in place.

69

How about: "function expected to be annotated with '%0' visibility"

I'm mostly worried about the case where the function has a visibility attribute, but it has the *wrong* visibility specified. The current wording would be confusing in that circumstance. Or is that not a scenario you care about, just that *any* visibility is specified on the function?

clang-tidy/fuchsia/AddVisibilityCheck.h
22

The backtick is in the wrong place.

jakehehrlich added inline comments.Feb 16 2018, 2:07 PM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
69

The use case for this check is forcing code bases to carefully control what symbols are exported rather than just exporting everything. So if someone took the time to explicitly set the visibility of one of these symbols we care about then we should assume they knew what they were doing.

The specific use case I care about for this check is using -fvisibility=hidden and then checking to make sure a certain curated list of symbols has explicit default visibility.

aaron.ballman added inline comments.Feb 17 2018, 7:00 AM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
69

Ah, so a mismatch is unimportant, that's good to know. How about: "function expected to be annotated with the 'visibility' attribute"?

juliehockett marked 10 inline comments as done.

Updating check to allow for #pragma and command line visibility specs, and updating tests

clang-tidy/fuchsia/AddVisibilityCheck.cpp
69

So in implementing a way to handle #pragma and command line directives, it became clear that the more comprehensive check (that replaces existing attrs) was a trivial implementation on top of that, so I put it in. If we just want to ignore those cases, I can take out the conditional path.

aaron.ballman added inline comments.Feb 21 2018, 5:15 AM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
24–26

Can remove these comments.

53–54

Can you use makeArrayRef() rather than using a SmallVector that allocates?

63

const auto *

67

Why are you passing D as well?

73

Why are you passing in both VisAttr and D?

test/clang-tidy/fuchsia-add-visibility.cpp
26

Should this test case diagnose, assuming foo is in the list of functions to check?

__attribute__((visibility("default"))) void foo(int);
void foo(double); // Diagnose?

How about this case?

template <typename Ty>
__attribute__((visibility("default"))) void foo(Ty);

template <>
void foo<int>(int); // Diagnose?
alexfh edited reviewers, added: ilya-biryukov; removed: alexfh.Feb 21 2018, 6:05 AM
juliehockett marked 6 inline comments as done.

After discussion, the goal of this checker slightly changed to target definitions in header files, rather than declarations. As a result, the check now adds the attribute to any definition (declaration or not) that appears in a header file.

Also updating tests.

clang-tidy/fuchsia/AddVisibilityCheck.cpp
53–54

Type-wise it gets funky -- makeArrayRef() creates an ArrayRef<std::string>, and the matcher wants a container of StringRefs. Is there a good way to do that without allocating?

jakehehrlich added inline comments.Feb 26 2018, 12:55 PM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
26

What are these comments doing here?

49

What about internal?

64

Something in the list that simply has explicit visibility should pass I think. For instance saying you have a blacklist of symbols instead of a whitelist. Sometimes internal or hidden might be used but we might want to add "hidden" by default. So "Vis" might be DefaultVisibility but we don't want to raise an error/change something labeled with internal visibility to hidden.

Can you add a test for when #pragma GCC visibility push(hidden) is used and the visibility attribute is hidden?

aaron.ballman added inline comments.Feb 27 2018, 7:21 AM
clang-tidy/fuchsia/AddVisibilityCheck.cpp
40

This works for now, but it would be nice to expose "driver diagnostics" for sanity checking clang-tidy configuration options. These diagnostics would not be required to pass in a source location, merely the diagnostic text. We already support thing kind of things for driver-generated diagnostics, but it's not exposed to clang-tidy yet.

49

Might be a good use of StringSwitch.

53–54

I think there is, but it is orthogonal to your patch to make that many changes, so you can ignore my suggestion. I didn't see the type shenanigans there.

75

Capitalization

juliehockett abandoned this revision.Mar 22 2018, 9:51 AM
juliehockett marked 9 inline comments as done.