Skip to content

Make the -disable-free flag more full featured #136213

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

Merged
merged 1 commit into from
Apr 18, 2025

Conversation

chandlerc
Copy link
Member

This lets us pass -no-disable-free to re-enable freeing memory for example. This is especially helpful for library users of Clang where it is important to not slowly leak memory.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Apr 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 17, 2025

@llvm/pr-subscribers-clang-driver

Author: Chandler Carruth (chandlerc)

Changes

This lets us pass -no-disable-free to re-enable freeing memory for example. This is especially helpful for library users of Clang where it is important to not slowly leak memory.


Full diff: https://github.com/llvm/llvm-project/pull/136213.diff

2 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+7-3)
  • (modified) clang/test/Driver/clang-translation.c (+3)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e9acb20348654..830d3459a1320 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7889,9 +7889,13 @@ def code_completion_with_fixits : Flag<["-"], "code-completion-with-fixits">,
 def skip_function_bodies : Flag<["-"], "skip-function-bodies">,
   HelpText<"Skip function bodies when possible">,
   MarshallingInfoFlag<FrontendOpts<"SkipFunctionBodies">>;
-def disable_free : Flag<["-"], "disable-free">,
-  HelpText<"Disable freeing of memory on exit">,
-  MarshallingInfoFlag<FrontendOpts<"DisableFree">>;
+defm disable_free : BoolOption<"",
+  "disable-free",
+  FrontendOpts<"DisableFree">,
+  DefaultFalse,
+  PosFlag<SetTrue, [], [ClangOption], "Disable">,
+  NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
+  BothFlags<[], [ClangOption], " freeing of memory on exit">>;
 defm clear_ast_before_backend : BoolOption<"",
   "clear-ast-before-backend",
   CodeGenOpts<"ClearASTBeforeBackend">,
diff --git a/clang/test/Driver/clang-translation.c b/clang/test/Driver/clang-translation.c
index a7343ea18b213..1c9e3cfb2a5e5 100644
--- a/clang/test/Driver/clang-translation.c
+++ b/clang/test/Driver/clang-translation.c
@@ -10,6 +10,9 @@
 // I386: "-o"
 // I386: clang-translation
 
+// RUN: %clang -target i386-unknown-unknown -### -S -O0 -Os %s -o %t.s -fverbose-asm -fvisibility=hidden -no-disable-free 2>&1 | FileCheck -check-prefix=FREE %s
+// FREE-NOT: "-disable-free"
+
 // RUN: %clang -target i386-unknown-unknown -### -S %s -fasynchronous-unwind-tables -fno-unwind-tables 2>&1 | FileCheck --check-prefix=UNWIND-TABLES %s --implicit-check-not=warning:
 // UNWIND-TABLES: "-funwind-tables=2"
 

@llvmbot
Copy link
Member

llvmbot commented Apr 17, 2025

@llvm/pr-subscribers-clang

Author: Chandler Carruth (chandlerc)

Changes

This lets us pass -no-disable-free to re-enable freeing memory for example. This is especially helpful for library users of Clang where it is important to not slowly leak memory.


Full diff: https://github.com/llvm/llvm-project/pull/136213.diff

2 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+7-3)
  • (modified) clang/test/Driver/clang-translation.c (+3)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e9acb20348654..830d3459a1320 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -7889,9 +7889,13 @@ def code_completion_with_fixits : Flag<["-"], "code-completion-with-fixits">,
 def skip_function_bodies : Flag<["-"], "skip-function-bodies">,
   HelpText<"Skip function bodies when possible">,
   MarshallingInfoFlag<FrontendOpts<"SkipFunctionBodies">>;
-def disable_free : Flag<["-"], "disable-free">,
-  HelpText<"Disable freeing of memory on exit">,
-  MarshallingInfoFlag<FrontendOpts<"DisableFree">>;
+defm disable_free : BoolOption<"",
+  "disable-free",
+  FrontendOpts<"DisableFree">,
+  DefaultFalse,
+  PosFlag<SetTrue, [], [ClangOption], "Disable">,
+  NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
+  BothFlags<[], [ClangOption], " freeing of memory on exit">>;
 defm clear_ast_before_backend : BoolOption<"",
   "clear-ast-before-backend",
   CodeGenOpts<"ClearASTBeforeBackend">,
diff --git a/clang/test/Driver/clang-translation.c b/clang/test/Driver/clang-translation.c
index a7343ea18b213..1c9e3cfb2a5e5 100644
--- a/clang/test/Driver/clang-translation.c
+++ b/clang/test/Driver/clang-translation.c
@@ -10,6 +10,9 @@
 // I386: "-o"
 // I386: clang-translation
 
+// RUN: %clang -target i386-unknown-unknown -### -S -O0 -Os %s -o %t.s -fverbose-asm -fvisibility=hidden -no-disable-free 2>&1 | FileCheck -check-prefix=FREE %s
+// FREE-NOT: "-disable-free"
+
 // RUN: %clang -target i386-unknown-unknown -### -S %s -fasynchronous-unwind-tables -fno-unwind-tables 2>&1 | FileCheck --check-prefix=UNWIND-TABLES %s --implicit-check-not=warning:
 // UNWIND-TABLES: "-funwind-tables=2"
 

This lets us pass `-no-disable-free` to re-enable freeing memory for
example. This is especially helpful for library users of Clang where it
is important to not slowly leak memory.
Comment on lines +7892 to +7898
defm disable_free : BoolOption<"",
"disable-free",
FrontendOpts<"DisableFree">,
DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Disable">,
NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
BothFlags<[], [ClangOption], " freeing of memory on exit">>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently defined in a block of CC1-only options. If we want to expose this as a driver option, that should be done by moving it elsewhere in the file rather than by specifying [ClangOption] here. Though it's not clear to me if this is intended to be a driver option: ClangOption suggests yes, but the test using -Xclang suggests no.

If this is supposed to be a driver flag, those are usually namespaced by their initial letter, so I think it's worth considering if a namespace would make sense here too. If this only controls the behavior of the frontend then using a -f prefix might make sense, but I suppose we might also want to make this control the behavior of the driver itself, so maybe an unnamespaced flag is appropriate. GCC interprets -disable-free as enabling debugging dumps at phases i, s, a, b, ... of processing, so there's not a collision to worry about there.

The double-negative in -no-disable-free also seems a bit funny, but it's probably fine :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, this remains a CC1 flag (same as the below flag), and just allows us to invert it.

I wasn't suggesting lifting it all the way up, just making it have the more complete logical set of operations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I did check, and this remains rejected from the main driver, and only is allow at the CC1 layer, which works for my use case.)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, it looks like the enclosing let Visibility = ... is entirely overriding the effect of the [ClangOption] here and below. So that's all just dead (and misleading) code. Great. I guess we should at least be consistent with it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll send a PR to at least remove the dead code as a follow-up.

Comment on lines +7892 to +7898
defm disable_free : BoolOption<"",
"disable-free",
FrontendOpts<"DisableFree">,
DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Disable">,
NegFlag<SetFalse, [], [ClangOption], "Don't disable">,
BothFlags<[], [ClangOption], " freeing of memory on exit">>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, it looks like the enclosing let Visibility = ... is entirely overriding the effect of the [ClangOption] here and below. So that's all just dead (and misleading) code. Great. I guess we should at least be consistent with it.

@chandlerc chandlerc merged commit feb1fb5 into llvm:main Apr 18, 2025
9 of 11 checks passed
@MaskRay
Copy link
Member

MaskRay commented Apr 18, 2025

You might want to change the DisableFree default for library uses so that users don't need to specify -no-disable-free.

  // Clang calls BuryPointer on the internal AST and CodeGen-related elements like TargetMachine.
  // This will cause memory leaks if `compile` is executed many times.
  ci->getCodeGenOpts().DisableFree = false;
  ci->getFrontendOpts().DisableFree = false;

@chandlerc
Copy link
Member Author

Follow-up PR as requested: #136271

@chandlerc
Copy link
Member Author

You might want to change the DisableFree default for library uses so that users don't need to specify -no-disable-free.

  // Clang calls BuryPointer on the internal AST and CodeGen-related elements like TargetMachine.
  // This will cause memory leaks if `compile` is executed many times.
  ci->getCodeGenOpts().DisableFree = false;
  ci->getFrontendOpts().DisableFree = false;

Not really sure what default change you're thinking about?

The default that was causing me problems was the driver adding -disable-free to the CC1 flags by default -- but I think that's probably the correct default. I just wanted a way to override it in a library where the behavior would be problematic. Having the flag support appending -no-disable-free to the CC1 flags seemed like the cleanest solution that keeps the best defaults for the most common cases, but gives a path to handle the case of CC1 flags. Does that make sense?

IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
This lets us pass `-no-disable-free` to re-enable freeing memory for
example. This is especially helpful for library users of Clang where it
is important to not slowly leak memory.
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
This lets us pass `-no-disable-free` to re-enable freeing memory for
example. This is especially helpful for library users of Clang where it
is important to not slowly leak memory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants