diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -194,6 +194,9 @@ def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; def err_drv_unknown_argument : Error<"unknown argument: '%0'">; +def warn_drv_flang_argument : Warning< + "command line option '%0' is only valid in Flang mode (i.e. for Fortran input)">, + InGroup; def err_drv_unknown_argument_with_suggestion : Error< "unknown argument '%0'; did you mean '%1'?">; def warn_drv_unknown_argument_clang_cl : Warning< @@ -202,7 +205,6 @@ def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< "unknown argument ignored in clang-cl '%0'; did you mean '%1'?">, InGroup; - def warn_drv_ycyu_different_arg_clang_cl : Warning< "support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">, InGroup; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4299,10 +4299,7 @@ //===----------------------------------------------------------------------===// // FLangOption + CoreOption + NoXarchOption //===----------------------------------------------------------------------===// -let Flags = [FlangOption, FlangOnlyOption, NoXarchOption, CoreOption] in { -def Xflang : Separate<["-"], "Xflang">, - HelpText<"Pass to the flang compiler">, MetaVarName<"">, - Flags<[NoXarchOption, CoreOption]>, Group; +let Flags = [FlangOption, FlangOnlyOption, FC1Option] in { } //===----------------------------------------------------------------------===// @@ -4315,6 +4312,8 @@ DocBrief<[{This option specifies where to put .mod files for compiled modules. It is also added to the list of directories to be searched by an USE statement. The default is the current directory.}]>; +def Xflang : Separate<["-"], "Xflang">, + HelpText<"Pass to the flang compiler">, MetaVarName<"">; def ffixed_form : Flag<["-"], "ffixed-form">, Group, HelpText<"Process source files in fixed form">; diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -222,7 +222,6 @@ InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask); - // Check for missing argument error. if (MissingArgCount) { Diag(diag::err_drv_missing_argument) @@ -262,20 +261,49 @@ } for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) { - unsigned DiagID; + // The default diagnostic when the option is unknow + unsigned DiagID = diag::err_drv_unknown_argument; + + // Try to find a good hint for the user auto ArgString = A->getAsString(Args); std::string Nearest; - if (getOpts().findNearest( - ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) > 1) { - DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl - : diag::err_drv_unknown_argument; - Diags.Report(DiagID) << ArgString; - } else { + unsigned Distance = getOpts().findNearest( + ArgString, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask); + assert(Distance != 0 && "This option should not be 'unknown'"); + + if (Distance == 1) { + // Found a good suggestion - propose that in the diagnostic DiagID = IsCLMode() ? diag::warn_drv_unknown_argument_clang_cl_with_suggestion : diag::err_drv_unknown_argument_with_suggestion; Diags.Report(DiagID) << ArgString << Nearest; + } else { + // No good suggestion was found - the diagnostic depends on the mode in + // which the driver operates + if (IsCLMode()) + // In CL mode just warn the user (MSVC consumes everything anyway) + DiagID = diag::warn_drv_unknown_argument_clang_cl; + else if (!IsFlangMode()) { + // In non-Flang mode, check whether this is a Flang flag and + // communicate accordingly. + unsigned ExcludedFlagsBitmaskWithFlang = + ExcludedFlagsBitmask & ~options::FlangOnlyOption; + + unsigned ExpectedDistance = 0; + // TODO: This currently doesn't work as information about aliases is + // lost when generating "unknown" options. + if (auto Alias = A->getAlias()) + ExpectedDistance = 1; + + if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmaskWithFlang) == + ExpectedDistance) + DiagID = diag::warn_drv_flang_argument; + } // TODO: Check whether this is a C-mode flag and report accordingly. + + Diags.Report(DiagID) << ArgString; } + ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > DiagnosticsEngine::Warning; } diff --git a/clang/test/Driver/flang-only-option-diags.c b/clang/test/Driver/flang-only-option-diags.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/flang-only-option-diags.c @@ -0,0 +1,28 @@ +// Test the behaviour of clang with a `FlangOnlyOption` and various diagnostics +// flags. We want to make sure that users can control whether Flang-only options + +// RUN: %clang -fsyntax-only -ffree-form %s 2>&1 | FileCheck %s --check-prefix=WARNING +// RUN: not %clang -fsyntax-only -Werror -ffree-form %s 2>&1 | FileCheck %s --check-prefix=ERROR +// RUN: %clang -fsyntax-only -Werror -Wno-unknown-argument -Wno-unused-command-line-argument -ffree-form %s 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-DIAGS + +//--------------------------- +// EXPECTED OUTPUT - WARNING +//--------------------------- +// WARNING: clang-{{[0-9]+}}: warning: command line option '-ffree-form' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// WARNING-NEXT: clang-{{[0-9]+}}: warning: argument unused during compilation: '-ffree-form' [-Wunused-command-line-argument] + +//------------------------ +// EXPECTED OUTPUT - ERROR +//------------------------ +// ERROR: clang-13: error: command line option '-ffree-form' is only valid in Flang mode (i.e. for Fortran input) [-Werror,-Wunknown-argument] + +//--------------------------------- +// EXPECTED OUTPUT - NO DIAGNOSTICS +//--------------------------------- +// NO-DIAGS-NOT: error +// NO-DIAGS-NOT: warning + +//------- +// INPUT +//------- +int a; diff --git a/clang/test/Driver/flang-only-options.c b/clang/test/Driver/flang-only-options.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/flang-only-options.c @@ -0,0 +1,70 @@ +// Verifies that Flang options marked as `FlangOnlyOption` are corectly recognised and warned about by Clang. +// +// TODO: Add aliases (once working) + +// RUN: %clang -fsyntax-only \ +// SKIP: -Xflang \ This option is currently parsed by Clang as OPT_X_Flang (i.e. `-X flang` rather than `-Xflang`) +// RUN: -ffree-form \ +// RUN: -ffixed-form \ +// RUN: -module-dir \ +// RUN: -ffixed-line-length=1 \ +// RUN: -fopenacc \ +// RUN: -fdefault-double-8 \ +// RUN: -fdefault-integer-8 \ +// RUN: -fdefault-real-8 \ +// RUN: -flarge-sizes \ +// RUN: -fbackslash \ +// RUN: -fno-backslash \ +// RUN: -fxor-operator \ +// RUN: -fno-xor-operator \ +// RUN: -flogical-abbreviations \ +// RUN: -fno-logical-abbreviations \ +// RUN: -fimplicit-none \ +// RUN: -fno-implicit-none \ +// RUN: -falternative-parameter-statement \ +// RUN: -fintrinsic-modules-path \ +// RUN: -test-io \ +// RUN: -fdebug-unparse \ +// RUN: -fdebug-unparse-with-symbols \ +// RUN: -fdebug-dump-symbols \ +// RUN: -fdebug-dump-parse-tree \ +// RUN: -fdebug-dump-provenance \ +// RUN: -fdebug-dump-parsing-log \ +// RUN: -fdebug-measure-parse-tree \ +// RUN: -fdebug-pre-fir-tree \ +// RUN: -fdebug-module-writer \ +// RUN: -fget-symbols-sources \ +// RUN: %s 2>&1 | FileCheck %s + +// CHECK: clang-{{[0-9]+}}: warning: command line option '-ffree-form' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-ffixed-form' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-module-dir' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-ffixed-line-length=1' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fopenacc' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdefault-double-8' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdefault-integer-8' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdefault-real-8' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-flarge-sizes' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fbackslash' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fno-backslash' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fxor-operator' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fno-xor-operator' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-flogical-abbreviations' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fno-logical-abbreviations' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fimplicit-none' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fno-implicit-none' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-falternative-parameter-statement' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fintrinsic-modules-path' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-test-io' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-unparse' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-unparse-with-symbols' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-dump-symbols' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-dump-parse-tree' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-dump-provenance' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-dump-parsing-log' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-measure-parse-tree' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-pre-fir-tree' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fdebug-module-writer' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] +// CHECK: clang-{{[0-9]+}}: warning: command line option '-fget-symbols-sources' is only valid in Flang mode (i.e. for Fortran input) [-Wunknown-argument] + +int a;