awarzynski created this revision. Herald added a reviewer: sscalpone. awarzynski requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
This patch adds extra logic in Driver::ParseArgStrings so that `clang` (Clang's compiler driver) generates a warning when a Flang-only option is used. Previously it would throw an error: - `error: unknown argument: <option>` and exit immediately. That was flagged as problematic in [1]. The new behaviour is consistent with GCC: gcc -c -ffree-form file.c cc1: warning: command line option ‘-ffree-form’ is valid for Fortran but not for C It allows users to use `clang` as e.g. a linker driver, without worrying about passing Fortran specific flags to `clang`. These flags are often embedded in build systems and are hard to extract just for linking. An issue like this raised in [1]. This patch is an attempt to address this. The current approach is a bit verbose. Ideally we should extend the OptTable API to make accommodating for situations like this easier. In particular, I'm not sure whether we can add similar logic for Flang. In this patch we are relying on the `FlangOnlyOption` flag to identify problematic options. There's no equivalent flag for Clang-only options. I propose that we address this later, when this becomes a problem for Flang. [1] https://reviews.llvm.org/D95460 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99353 Files: clang/lib/Driver/Driver.cpp Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -223,7 +223,6 @@ InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask); - // Check for missing argument error. if (MissingArgCount) { Diag(diag::err_drv_missing_argument) @@ -263,20 +262,43 @@ } 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. + ExcludedFlagsBitmask &= ~options::FlangOnlyOption; + if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask) == 0) + DiagID = + Diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, + "command line option ‘%0’ is only valid " + "in Flang mode (i.e. for Fortran input)"); + } // TODO: Check whether this is a C-mode flag and report accordingly. + + Diags.Report(DiagID) << ArgString; } + ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > DiagnosticsEngine::Warning; }
Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -223,7 +223,6 @@ InputArgList Args = getOpts().ParseArgs(ArgStrings, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask); - // Check for missing argument error. if (MissingArgCount) { Diag(diag::err_drv_missing_argument) @@ -263,20 +262,43 @@ } 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. + ExcludedFlagsBitmask &= ~options::FlangOnlyOption; + if (getOpts().findNearest(ArgString, Nearest, IncludedFlagsBitmask, + ExcludedFlagsBitmask) == 0) + DiagID = + Diags.getCustomDiagID(clang::DiagnosticsEngine::Warning, + "command line option â%0â is only valid " + "in Flang mode (i.e. for Fortran input)"); + } // TODO: Check whether this is a C-mode flag and report accordingly. + + Diags.Report(DiagID) << ArgString; } + ContainsError |= Diags.getDiagnosticLevel(DiagID, SourceLocation()) > DiagnosticsEngine::Warning; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits