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 @@ -746,7 +746,7 @@ MarshallingInfoStringVector>; def Wwrite_strings : Flag<["-"], "Wwrite-strings">, Group, Flags<[CC1Option, HelpHidden]>; def Wno_write_strings : Flag<["-"], "Wno-write-strings">, Group, Flags<[CC1Option, HelpHidden]>; -def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option, CoreOption]>, +def W_Joined : Joined<["-"], "W">, Group, Flags<[CC1Option, CoreOption, FC1Option, FlangOption]>, MetaVarName<"">, HelpText<"Enable the specified warning">; def Xanalyzer : Separate<["-"], "Xanalyzer">, HelpText<"Pass to the static analyzer">, MetaVarName<"">, diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -44,7 +44,7 @@ Args.AddAllArgs(CmdArgs, {options::OPT_module_dir, options::OPT_fdebug_module_writer, options::OPT_fintrinsic_modules_path, options::OPT_pedantic, - options::OPT_std_EQ}); + options::OPT_std_EQ, options::OPT_W_Joined}); } void Flang::ConstructJob(Compilation &C, const JobAction &JA, diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h --- a/flang/include/flang/Frontend/CompilerInvocation.h +++ b/flang/include/flang/Frontend/CompilerInvocation.h @@ -71,6 +71,8 @@ bool debugModuleDir_ = false; + bool warnAsErr_ = false; + // Fortran Dialect options Fortran::common::IntrinsicTypeDefaultKinds defaultKinds_; @@ -98,6 +100,9 @@ bool &debugModuleDir() { return debugModuleDir_; } const bool &debugModuleDir() const { return debugModuleDir_; } + bool &warnAsErr() { return warnAsErr_; } + const bool &warnAsErr() const { return warnAsErr_; } + bool &enableConformanceChecks() { return EnableConformanceChecks_; } const bool &enableConformanceChecks() const { return EnableConformanceChecks_; @@ -126,6 +131,8 @@ void SetDebugModuleDir(bool flag) { debugModuleDir_ = flag; } + void SetWarnAsErr(bool flag) { warnAsErr_ = flag; } + /// Set the Fortran options to predifined defaults. These defaults are /// consistend with f18/f18.cpp. // TODO: We should map frontendOpts_ to parserOpts_ instead. For that, we diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -350,6 +350,26 @@ } } +/// Parses all diagnostics related arguments and populates the variables +/// options accordingly. +static void parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args, + clang::DiagnosticsEngine &diags) { + // -Werror option + // TODO: Currently throws a Diagnostic for anything other than -W, + // this has to change when other -W's are supported. + if (args.hasArg(clang::driver::options::OPT_W_Joined)) { + if (args.getLastArgValue(clang::driver::options::OPT_W_Joined) + .equals("error")) { + res.SetWarnAsErr(true); + } else { + const unsigned diagID = + diags.getCustomDiagID(clang::DiagnosticsEngine::Error, + "Only `-Werror` is supported currently."); + diags.Report(diagID); + } + } +} + /// Parses all Dialect related arguments and populates the variables /// options accordingly. static void parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args, @@ -445,6 +465,8 @@ parseSemaArgs(res, args, diags); // Parse dialect arguments parseDialectArgs(res, args, diags); + // Parse diagnostic arguments + parseDiagArgs(res, args, diags); return success; } @@ -574,5 +596,6 @@ semanticsContext_->set_moduleDirectory(moduleDir()) .set_searchDirectories(fortranOptions.searchDirectories) - .set_warnOnNonstandardUsage(enableConformanceChecks()); + .set_warnOnNonstandardUsage(enableConformanceChecks()) + .set_warningsAreErrors(warnAsErr()); } diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -64,7 +64,9 @@ // Prescan. In case of failure, report and return. ci.parsing().Prescan(currentInputPath, parserOptions); - if (ci.parsing().messages().AnyFatalError()) { + if (!ci.parsing().messages().empty() && + (ci.invocation().warnAsErr() || + ci.parsing().messages().AnyFatalError())) { const unsigned diagID = ci.diagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not scan %0"); ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); @@ -97,7 +99,9 @@ // Prescan. In case of failure, report and return. ci.parsing().Prescan(currentInputPath, parserOptions); - if (ci.parsing().messages().AnyFatalError()) { + if (!ci.parsing().messages().empty() && + (ci.invocation().warnAsErr() || + ci.parsing().messages().AnyFatalError())) { const unsigned diagID = ci.diagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not scan %0"); ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); @@ -109,7 +113,9 @@ // Parse. In case of failure, report and return. ci.parsing().Parse(llvm::outs()); - if (ci.parsing().messages().AnyFatalError()) { + if (!ci.parsing().messages().empty() && + (ci.invocation().warnAsErr() || + ci.parsing().messages().AnyFatalError())) { unsigned diagID = ci.diagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not parse %0"); ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); @@ -264,7 +270,9 @@ // Parse. In case of failure, report and return. ci.parsing().Parse(llvm::outs()); - if (ci.parsing().messages().AnyFatalError()) { + if (!ci.parsing().messages().empty() && + (ci.invocation().warnAsErr() || + ci.parsing().messages().AnyFatalError())) { unsigned diagID = ci.diagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "Could not parse %0"); ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90 --- a/flang/test/Driver/driver-help-hidden.f90 +++ b/flang/test/Driver/driver-help-hidden.f90 @@ -51,6 +51,7 @@ ! CHECK-NEXT: -std= Language standard to compile for ! CHECK-NEXT: -U Undefine macro ! CHECK-NEXT: --version Print version information +! CHECK-NEXT: -W Enable the specified warning ! CHECK-NEXT: -Xflang Pass to the flang compiler !------------------------------------------------------------- diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -51,6 +51,7 @@ ! HELP-NEXT: -std= Language standard to compile for ! HELP-NEXT: -U Undefine macro ! HELP-NEXT: --version Print version information +! HELP-NEXT: -W Enable the specified warning ! HELP-NEXT: -Xflang Pass to the flang compiler !------------------------------------------------------------- @@ -103,6 +104,7 @@ ! HELP-FC1-NEXT: -test-io Run the InputOuputTest action. Use for development and testing only. ! HELP-FC1-NEXT: -U Undefine macro ! HELP-FC1-NEXT: --version Print version information +! HELP-FC1-NEXT: -W Enable the specified warning !--------------- ! EXPECTED ERROR diff --git a/flang/test/Driver/werror_parse.f b/flang/test/Driver/werror_parse.f new file mode 100644 --- /dev/null +++ b/flang/test/Driver/werror_parse.f @@ -0,0 +1,33 @@ +! Ensure argument -Werror work as expected, this file checks for the functional correctness for +! actions that extend the PrescanAndSemaAction, particularly for Semantic warnings/errors. +! Multiple RUN lines are added to make sure that the behavior is consistent across multiple actions. + +! RUN: not %flang_fc1 -fsyntax-only -std=f2018 -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -std=f2018 -Werror -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -std=f2018 -Werror -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -std=f2018 -Werror -fdebug-unparse %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -std=f2018 -Werror -fdebug-dump-symbols %s 2>&1 | FileCheck %s --check-prefix=WITH + + +! RUN: %flang_fc1 -fsyntax-only -std=f2018 %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fdebug-unparse %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fdebug-dump-symbols %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT + +!----------------------------------------- +! EXPECTED OUTPUT WITH -Werror +!----------------------------------------- +! WITH: Could not parse + +!----------------------------------------- +! EXPECTED OUTPUT WITHOUT -Werror +!----------------------------------------- +! WITHOUT-NOT: Could not parse + +#ifndef _OM_NO_IOSTREAM +#ifdef WIN32 +#ifndef USE_IOSTREAM +#define USE_IOSTREAM +#endif USE_IOSTREAM +#endif WIN32 diff --git a/flang/test/Driver/werror_scan.f b/flang/test/Driver/werror_scan.f new file mode 100644 --- /dev/null +++ b/flang/test/Driver/werror_scan.f @@ -0,0 +1,25 @@ +! Ensure argument -Werror work as expected, this file checks for the functional correctness for +! actions that extend the PrescanAction +! Multiple RUN lines are added to make sure that the behavior is consistent across multiple actions. + +! RUN: not %flang_fc1 -fsyntax-only -E -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -fdebug-dump-parsing-log -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -fdebug-dump-provenance -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -fdebug-measure-parse-tree -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: %flang_fc1 -fsyntax-only -E %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-dump-parsing-log %s 2>&1 | FileCheck %s --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-dump-provenance %s 2>&1 | FileCheck %s --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-measure-parse-tree %s 2>&1 | FileCheck %s --check-prefix=WITHOUT + +!----------------------------------------- +! EXPECTED OUTPUT WITH -Werror +!----------------------------------------- +! WITH: Could not scan + +!----------------------------------------- +! EXPECTED OUTPUT WITHOUT -Werror +!----------------------------------------- +! WITHOUT-NOT: Could not scan + +1 continue +end diff --git a/flang/test/Driver/werror_sema.f90 b/flang/test/Driver/werror_sema.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/werror_sema.f90 @@ -0,0 +1,31 @@ +! Ensure argument -Werror work as expected, this file checks for the functional correctness for +! actions that extend the PrescanAndSemaAction, particularly for Semantic warnings/errors. +! Multiple RUN lines are added to make sure that the behavior is consistent across multiple actions. + +! RUN: not %flang_fc1 -fsyntax-only -Werror %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -Werror -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -Werror -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -Werror -fdebug-unparse %s 2>&1 | FileCheck %s --check-prefix=WITH +! RUN: not %flang_fc1 -fsyntax-only -Werror -fdebug-dump-symbols %s 2>&1 | FileCheck %s --check-prefix=WITH + + +! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-dump-parse-tree %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-unparse-with-symbols %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-unparse %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -fdebug-dump-symbols %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT + +!----------------------------------------- +! EXPECTED OUTPUT WITH -Werror +!----------------------------------------- +! WITH: Semantic errors in + +!----------------------------------------- +! EXPECTED OUTPUT WITHOUT -Werror +!----------------------------------------- +! WITHOUT-NOT: Semantic errors in + +PROGRAM werror +REAL, DIMENSION(20, 10) :: A +FORALL (J=1:N) A(I, I) = 1 +END PROGRAM werror diff --git a/flang/test/Driver/werror_wrong.f90 b/flang/test/Driver/werror_wrong.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/werror_wrong.f90 @@ -0,0 +1,9 @@ +! Ensure that only argument -Werror is supported. + +! RUN: not %flang_fc1 -fsyntax-only -Wall %s 2>&1 | FileCheck %s --check-prefix=WRONG +! RUN: not %flang_fc1 -fsyntax-only -WX %s 2>&1 | FileCheck %s --check-prefix=WRONG + +!----------------------------------------- +! EXPECTED OUTPUT WITH -W +!----------------------------------------- +! WRONG: Only `-Werror` is supported currently. diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -511,8 +511,14 @@ } else if (arg == "-fopenmp") { options.features.Enable(Fortran::common::LanguageFeature::OpenMP); predefinitions.emplace_back("_OPENMP", "201511"); - } else if (arg == "-Werror") { - driver.warningsAreErrors = true; + } else if (arg.find("-W") != std::string::npos) { + if (arg == "-Werror") + driver.warningsAreErrors = true; + else { + // Only -Werror is supported currently + llvm::errs() << "Only `-Werror` is supported currently.\n"; + return EXIT_FAILURE; + } } else if (arg == "-ed") { options.features.Enable(Fortran::common::LanguageFeature::OldDebugLines); } else if (arg == "-E") {