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< 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 @@ -262,20 +262,44 @@ } for (const Arg *A : Args.filtered(options::OPT_UNKNOWN)) { - unsigned DiagID; + // The default diagnostic when the option is unknown + 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 through a 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 - issue an error (default) or a warning. + // The actual 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, warn _if_ this is a Flang-only flag. Clang will + // reject/ignore these, but like in GCC, this shouldn't be an error. + // TODO: Currently this will only work for non-alias options. Options + // that are aliases are internally stored as their non-alias versions. + // When mixed with `OPT_UNKNOWN`, this seems to confuse `findNearest`. + unsigned ExcludedFlagsBitmaskWithFlang = + ExcludedFlagsBitmask & ~options::FlangOnlyOption; + if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmaskWithFlang) == 0) + DiagID = diag::warn_drv_flang_argument; + } // TODO: In Flang-mode, check whether this is a Clang-only flag. + + 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;