This is an archive of the discontinued LLVM Phabricator instance.

Add a new flag and attributes to control static destructor registration
ClosedPublic

Authored by erik.pilkington on Aug 20 2018, 1:32 PM.

Details

Summary

See the recent thread here: http://lists.llvm.org/pipermail/cfe-dev/2018-July/058494.html

This patch adds the flag -fno-c++-static-destructors, which disables registration of exit-time destructors of static or thread storage duration variables. This patch also adds [[clang::no_destroy]] and [[clang::always_destroy]] attributes for disabling dtors in -fc++-static-destructors mode, and enabling dtors in -fno-c++-static-destructors mode, respectively. This patch was based on @bruno's https://reviews.llvm.org/D22474.

rdar://21734598

Thanks for taking a look!
Erik

Diff Detail

Repository
rL LLVM

Event Timeline

jfb added inline comments.Aug 20 2018, 1:47 PM
clang/include/clang/AST/Decl.h
1472 ↗(On Diff #161548)

This is only valid for static variables, right? It's probably better to document the function name that way, e.g. isStaticWithNoDestroy.

clang/include/clang/Basic/Attr.td
2999 ↗(On Diff #161548)

Ditto for these, I think the names of the variables should clarify that it's only for static. Note that I wouldn't rename the attributes themselves! Usage in context is unambiguous, and the docs should be clear. I just think the variable names don't provide the required context.

clang/include/clang/Basic/AttrDocs.td
3494 ↗(On Diff #161548)

"its"

3495 ↗(On Diff #161548)

"does nothing" is more "is the default".

3503 ↗(On Diff #161548)

"its"

3504 ↗(On Diff #161548)

"static and thread"

clang/lib/Sema/SemaDeclAttr.cpp
5931 ↗(On Diff #161548)

This allows a variable with both attributes :)
Looking at the code above it seems like having both attributes is equivalent to no-destroy.

rsmith added inline comments.Aug 20 2018, 2:37 PM
clang/include/clang/AST/Decl.h
1472 ↗(On Diff #161548)

I think the question (and hence current function name) is meaningful for any variable, but it just happens that the answer will always be "no" for non-static variables (for now, at least). Are you concerned that people will think calls to this function are missing from codepaths that only deal with automatic storage duration variables with the current name?

clang/include/clang/Basic/Attr.td
2999 ↗(On Diff #161548)

Our convention is that the Attr name matches the source spelling, so I think this is appropriate as-is.

clang/include/clang/Basic/DiagnosticSemaKinds.td
1813 ↗(On Diff #161548)

"must" -> "can only". (There is no requirement to apply the attribute to anything.)

clang/include/clang/Basic/LangOptions.def
311 ↗(On Diff #161548)

Should be a BENIGN_LANGOPT because it doesn't affect AST construction, only the generated code.

clang/lib/Frontend/CompilerInvocation.cpp
2769–2771 ↗(On Diff #161548)

-fc++-static-destructors is not a CC1 flag, so this should just be a hasArg call.

jfb added inline comments.Aug 20 2018, 2:48 PM
clang/include/clang/AST/Decl.h
1472 ↗(On Diff #161548)

Yeah it seems like "this variable has no destructor". I guess even trivial automatic variables have a (trivial) destructor, so maybe it's not ambiguous? Up to y'all :)

erik.pilkington marked 7 inline comments as done.

In this new patch:

  • Fix some grammar errors in the documentation.
  • Add a testcase for both attributes appearing on a variable.
  • Just use hasArg() in the driver.
  • Improve the diagnostic.

Thanks for the feedback!

clang/include/clang/AST/Decl.h
1472 ↗(On Diff #161548)

If anyone has a strong preference I'd be happy either way!

clang/include/clang/Basic/LangOptions.def
311 ↗(On Diff #161548)

It does affect AST construction though, we don't mark a static VarDecl's type's destructor referenced in this mode, or check it's access (because we aren't actually using it). Do you think this is the wrong choice of semantics?

clang/lib/Sema/SemaDeclAttr.cpp
5931 ↗(On Diff #161548)

handleSimpleAttributeWithExclusions handles that automagically, i.e.:

$ cat t.cpp
[[clang::no_destroy]] [[clang::always_destroy]] int x;
$ ~/dbg-bld/bin/clang t.cpp
t.cpp:1:25: error: 'always_destroy' and 'no_destroy' attributes are not compatible
[[clang::no_destroy]] [[clang::always_destroy]] int x;
                        ^
t.cpp:1:3: note: conflicting attribute is here
[[clang::no_destroy]] [[clang::always_destroy]] int x;
  ^
1 error generated.

I'll add a test to prove this though...

rsmith accepted this revision.Aug 20 2018, 3:55 PM

Seems fine to me, once you add the test for always_destroy + no_destroy.

clang/include/clang/Basic/LangOptions.def
311 ↗(On Diff #161548)

Ah, no, good point. This is right, then. (And I think avoiding checking the destructor is also appropriate, so that a private or deleted destructor can be used to "remind" people to use the attribute.)

This revision is now accepted and ready to land.Aug 20 2018, 3:55 PM
jfb accepted this revision.Aug 20 2018, 4:09 PM
jfb added inline comments.
clang/include/clang/AST/Decl.h
1472 ↗(On Diff #161548)

Considering what Richard pointed out below w.r.t. naming convention, this is good with me.

clang/lib/Sema/SemaDeclAttr.cpp
5931 ↗(On Diff #161548)

Ah nice!

This revision was automatically updated to reflect the committed changes.
This revision was automatically updated to reflect the committed changes.

Some minor nits that can be handled post-commit.

lib/Sema/SemaDeclAttr.cpp
5921 ↗(On Diff #161757)

There is no need to check VarDecl here -- that's already done for you by the subject.

5927–5931 ↗(On Diff #161757)

Elide braces.

test/SemaCXX/no_destroy.cpp
33–34 ↗(On Diff #161757)

Please also add tests demonstrating that the attribute does not appertain to things that don't look like variables (like a function or struct declaration) and that it does not accept arguments.

Sure, done in 340311!