Skip to content

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<
"'%0' action ignored; '%1' action specified previously">;
def err_fe_invalid_alignment : Error<
"invalid value '%1' in '%0'; alignment must be a power of 2">;
def err_fe_invalid_exception_model
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Copy link
Contributor

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?

Copy link
Member Author

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*..

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)
<< SavedAction->getSpelling() << A->getSpelling();
break;
}
}
}
}

if (const Arg* A = Args.getLastArg(OPT_plugin)) {
Expand Down
7 changes: 7 additions & 0 deletions clang/test/Frontend/multiple-actions.c
Original file line number Diff line number Diff line change
@@ -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: '-S' action ignored; '-emit-llvm' action specified previously

// 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: '-emit-llvm-only' action ignored; '-S' action specified previously

// RUN: %clang_cc1 -S -main-file-name %s -emit-llvm -o /dev/null
Loading