-
Notifications
You must be signed in to change notification settings - Fork 13.5k
cc1: Report an error for multiple actions unless separated by -main-file-name #91140
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
cc1: Report an error for multiple actions unless separated by -main-file-name #91140
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-clang Author: Fangrui Song (MaskRay) ChangesWhen multiple actions are specified, the last one is used and others are
However, we want to continue supporting overriding the driver action with -Xclang:
As an exception, we allow -ast-dump* options to be composed together Full diff: https://github.com/llvm/llvm-project/pull/91140.diff 3 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index fcffadacc8e631..48c174cfa9e8a5 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -134,6 +134,8 @@ def err_fe_no_pch_in_dir : Error<
"no suitable precompiled header file found in directory '%0'">;
def err_fe_action_not_available : Error<
"action %0 not compiled in">;
+def err_fe_invalid_multiple_actions : Error<
+ "action %0 is specified, another action is not allowed: %1">;
def err_fe_invalid_alignment : Error<
"invalid value '%1' in '%0'; alignment must be a power of 2">;
def err_fe_invalid_exception_model
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8312abc3603953..4a4c02b03ce938 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2841,6 +2841,30 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
}
Opts.ProgramAction = *ProgramAction;
+
+ // Catch common mistakes when multiple actions are specified for cc1 (e.g.
+ // -S -emit-llvm means -emit-llvm while -emit-llvm -S means -S). However, to
+ // support driver `-c -Xclang ACTION` (-cc1 -emit-llvm file -main-file-name
+ // X ACTION), we suppress the error when the two actions are separated by
+ // -main-file-name.
+ //
+ // As an exception, accept composable -ast-dump*.
+ if (!A->getSpelling().starts_with("-ast-dump")) {
+ const Arg *SavedAction = nullptr;
+ for (const Arg *AA :
+ Args.filtered(OPT_Action_Group, OPT_main_file_name)) {
+ if (AA->getOption().matches(OPT_main_file_name)) {
+ SavedAction = nullptr;
+ } else if (!SavedAction) {
+ SavedAction = AA;
+ } else {
+ if (!A->getOption().matches(OPT_ast_dump_EQ))
+ Diags.Report(diag::err_fe_invalid_multiple_actions)
+ << A->getSpelling() << SavedAction->getSpelling();
+ break;
+ }
+ }
+ }
}
if (const Arg* A = Args.getLastArg(OPT_plugin)) {
diff --git a/clang/test/Frontend/multiple-actions.c b/clang/test/Frontend/multiple-actions.c
new file mode 100644
index 00000000000000..5dd9ac3c8754f7
--- /dev/null
+++ b/clang/test/Frontend/multiple-actions.c
@@ -0,0 +1,7 @@
+// RUN: not %clang_cc1 -S -emit-llvm -main-file-name %s 2>&1 | FileCheck %s --check-prefix=ERR1 --implicit-check-not=error:
+// ERR1: error: action -emit-llvm is specified, another action is not allowed: -S
+
+// RUN: not %clang_cc1 -main-file-name %s -emit-llvm-only -emit-llvm -S 2>&1 | FileCheck %s --check-prefix=ERR2 --implicit-check-not=error:
+// ERR2: error: action -S is specified, another action is not allowed: -emit-llvm-only
+
+// RUN: %clang_cc1 -S -main-file-name %s -emit-llvm -o /dev/null
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
// -main-file-name. | ||
// | ||
// As an exception, accept composable -ast-dump*. | ||
if (!A->getSpelling().starts_with("-ast-dump")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason why use string-based prefix instead of checking for the OPT_
enums?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-ast-dump -ast-dump-lookups
and -ast-dump-lookups -ast-dump
are composable. llvm/utils/update_cc_test_checks.py
appends -ast-dump=json
when the cc1 command line may contain another action option.
Since there are 3+ -ast-dump*
options that need an exception, I feel that starts_with("-ast-dump"))
is simpler than listing all OPT_ast_dump*
..
This sounds good in principle, but some tests are failing in CI, so this might need more refinement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CI seems to have noticed what I feared :) This is going to hit a good amount of our internal tests, there is no way our copy-paste cargo-cult didn't come up with this before.
@@ -134,6 +134,8 @@ def err_fe_no_pch_in_dir : Error< | |||
"no suitable precompiled header file found in directory '%0'">; | |||
def err_fe_action_not_available : Error< | |||
"action %0 not compiled in">; | |||
def err_fe_invalid_multiple_actions : Error< | |||
"action %0 is specified, another action is not allowed: %1">; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"action %0 is specified, another action is not allowed: %1">; | |
"'%1' action ignored; '%0' action specified previously">; |
Maybe something like this? I dont think the original fits very well? Also the single ticks around the actions is, IMO, better for readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. I adopted it by swapping %1 and %0 ...
Created using spr 1.3.5-bogner
There were |
I've fixed all upstream tests. This one-liner might be useful to auto fix some downstream tests...
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me, please give this a day or so for any conversations to die down.
I don't really understand the rationale for this, and it's kind of annoying. Most of the compiler's flags behave in the "last one wins" fashion (such as |
@bogner Some action options are shared between driver and cc1 but the behaviors could be quite different. See my example in the description.
The strictness helps ensure that |
So the oddity here really is the driver, which translates both I suppose that it's somewhat reasonable to warn users that |
The driver behavior isn't that odd. "Last option wins" applies to The Before this patch and the associated cleanups, a lot of tests had more than one actions and the authors were unaware of the issue, e.g. |
Follow-up to a previous simplification 2473b1a. The xor difference between a SHT_NOTE and a read-only SHT_PROGBITS (previously >=NOT_SPECIAL) should be smaller than RF_EXEC. Otherwise, for the following section layout, `findOrphanPos` would place .text before note. ``` // simplified from linkerscript/custom-section-type.s non orphans: progbits 0x8060c00 NOT_SPECIAL note 0x8040003 orphan: .text 0x8061000 NOT_SPECIAL ```
When multiple actions are specified, the last one is used and others are
overridden. This might lead to confusion if the user is used to driver's
-S -emit-llvm
behavior.However, we want to continue supporting overriding the driver action with -Xclang:
clang -c -Xclang -ast-dump a.c
(%clang -cc1 -emit-obj ... -main-file-name a.c ... -ast-dump
)clang -c -xc++ -Xclang -emit-module stl.modulemap
As an exception, we allow -ast-dump* options to be composed together
(e.g.
-ast-dump -ast-dump-lookups
in AST/ast-dump-lookups.cpp).