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 @@ -3535,8 +3535,8 @@ def pass_exit_codes : Flag<["-", "--"], "pass-exit-codes">, Flags<[Unsupported]>; def pedantic_errors : Flag<["-", "--"], "pedantic-errors">, Group, Flags<[CC1Option]>, MarshallingInfoFlag>; -def pedantic : Flag<["-", "--"], "pedantic">, Group, Flags<[CC1Option]>, - MarshallingInfoFlag>; +def pedantic : Flag<["-", "--"], "pedantic">, Group, Flags<[CC1Option,FlangOption,FC1Option]>, + HelpText<"Warn on language extensions">, MarshallingInfoFlag>; def pg : Flag<["-"], "pg">, HelpText<"Enable mcount instrumentation">, Flags<[CC1Option]>, MarshallingInfoFlag>; def pipe : Flag<["-", "--"], "pipe">, @@ -3638,7 +3638,7 @@ def static_libstdcxx : Flag<["-"], "static-libstdc++">; def static : Flag<["-", "--"], "static">, Group, Flags<[NoArgumentUnused]>; def std_default_EQ : Joined<["-"], "std-default=">; -def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, +def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option,FlangOption,FC1Option]>, Group, HelpText<"Language standard to compile for">, ValuesCode<[{ const char *Values = 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 @@ -43,7 +43,8 @@ void Flang::AddOtherOptions(const ArgList &Args, ArgStringList &CmdArgs) const { Args.AddAllArgs(CmdArgs, {options::OPT_module_dir, options::OPT_fdebug_module_writer, - options::OPT_fintrinsic_modules_path}); + options::OPT_fintrinsic_modules_path, options::OPT_pedantic, + options::OPT_std_EQ}); } 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 @@ -74,6 +74,8 @@ // Fortran Dialect options Fortran::common::IntrinsicTypeDefaultKinds defaultKinds_; + bool EnableConformanceChecks_ = false; + public: CompilerInvocation() = default; @@ -96,6 +98,11 @@ bool &debugModuleDir() { return debugModuleDir_; } const bool &debugModuleDir() const { return debugModuleDir_; } + bool &enableConformanceChecks() { return EnableConformanceChecks_; } + const bool &enableConformanceChecks() const { + return EnableConformanceChecks_; + } + Fortran::common::IntrinsicTypeDefaultKinds &defaultKinds() { return defaultKinds_; } @@ -111,6 +118,9 @@ llvm::ArrayRef commandLineArgs, clang::DiagnosticsEngine &diags); + // Enables the std=f2018 conformance check + void set_EnableConformanceChecks() { EnableConformanceChecks_ = true; } + /// Useful setters void SetModuleDir(std::string &moduleDir) { moduleDir_ = moduleDir; } 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 @@ -389,6 +389,26 @@ res.frontendOpts().features_.Enable( Fortran::common::LanguageFeature::OpenMP); } + + //-fpedantic + if (args.hasArg(clang::driver::options::OPT_pedantic)) { + res.set_EnableConformanceChecks(); + } + // -std=f2018. Current behaviour is same as -fpedantic + // TODO: Set proper options when more fortran standards + // are supported. + if (args.hasArg(clang::driver::options::OPT_std_EQ)) { + auto standard = args.getLastArgValue(clang::driver::options::OPT_std_EQ); + // We only allow f2018 as the given standard + if (standard.equals("f2018")) { + res.set_EnableConformanceChecks(); + } else { + const unsigned diagID = + diags.getCustomDiagID(clang::DiagnosticsEngine::Error, + "Only -std=f2018 is allowed currently."); + diags.Report(diagID); + } + } return; } @@ -539,6 +559,11 @@ if (frontendOptions.instrumentedParse_) fortranOptions.instrumentedParse = true; + + // Set the standard + if (enableConformanceChecks()) { + fortranOptions.features.WarnOnAllNonstandard(); + } } void CompilerInvocation::setSemanticsOpts( @@ -549,5 +574,6 @@ defaultKinds(), fortranOptions.features, allCookedSources); semanticsContext_->set_moduleDirectory(moduleDir()) - .set_searchDirectories(fortranOptions.searchDirectories); + .set_searchDirectories(fortranOptions.searchDirectories) + .set_warnOnNonstandardUsage(enableConformanceChecks()); } 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 @@ -47,6 +47,8 @@ ! CHECK-NEXT: -I Add directory to the end of the list of include search paths ! CHECK-NEXT: -module-dir Put MODULE files in ! CHECK-NEXT: -o Write output to +! CHECK-NEXT: -pedantic Warn on language extensions +! CHECK-NEXT: -std= Language standard to compile for ! CHECK-NEXT: -U Undefine macro ! CHECK-NEXT: --version Print version information ! 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 @@ -47,6 +47,8 @@ ! HELP-NEXT: -I Add directory to the end of the list of include search paths ! HELP-NEXT: -module-dir Put MODULE files in ! HELP-NEXT: -o Write output to +! HELP-NEXT: -pedantic Warn on language extensions +! HELP-NEXT: -std= Language standard to compile for ! HELP-NEXT: -U Undefine macro ! HELP-NEXT: --version Print version information ! HELP-NEXT: -Xflang Pass to the flang compiler @@ -96,6 +98,8 @@ ! HELP-FC1-NEXT: -I Add directory to the end of the list of include search paths ! HELP-FC1-NEXT: -module-dir Put MODULE files in ! HELP-FC1-NEXT: -o Write output to +! HELP-FC1-NEXT: -pedantic Warn on language extensions +! HELP-FC1-NEXT: -std= Language standard to compile for ! 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 diff --git a/flang/test/Driver/std2018.f90 b/flang/test/Driver/std2018.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/std2018.f90 @@ -0,0 +1,28 @@ +! Ensure argument -std=f2018 works as expected. + +!----------------------------------------- +! FRONTEND FLANG DRIVER (flang-new -fc1) +!----------------------------------------- +! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT +! RUN: %flang_fc1 -fsyntax-only -std=f2018 %s 2>&1 | FileCheck %s --check-prefix=GIVEN +! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s --check-prefix=GIVEN + +!----------------------------------------- +! EXPECTED OUTPUT WITHOUT +!----------------------------------------- +! WITHOUT-NOT: A DO loop should terminate with an END DO or CONTINUE + +!----------------------------------------- +! EXPECTED OUTPUT WITH +!----------------------------------------- +! GIVEN: A DO loop should terminate with an END DO or CONTINUE + +subroutine foo2() + do 01 m=1,2 + select case (m) + case default + print*, "default", m + case (1) + print*, "start" +01 end select +end subroutine diff --git a/flang/test/Driver/std2018_wrong.f90 b/flang/test/Driver/std2018_wrong.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Driver/std2018_wrong.f90 @@ -0,0 +1,12 @@ +! REQUIRES: new-flang-driver +! Ensure argument -std=f2018 works as expected. + +!----------------------------------------- +! FRONTEND FLANG DRIVER (flang-new -fc1) +!----------------------------------------- +! RUN: not %flang_fc1 -std=90 %s 2>&1 | FileCheck %s --check-prefix=WRONG + +!----------------------------------------- +! EXPECTED OUTPUT WITH WRONG +!----------------------------------------- +! WRONG: Only -std=f2018 is allowed 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 @@ -487,7 +487,8 @@ options.features.Enable( Fortran::common::LanguageFeature::BackslashEscapes, true); } else if (arg == "-Mstandard" || arg == "-std=f95" || - arg == "-std=f2003" || arg == "-std=f2008" || arg == "-std=legacy") { + arg == "-std=f2003" || arg == "-std=f2008" || arg == "-std=legacy" || + arg == "-std=f2018" || arg == "-pedantic") { driver.warnOnNonstandardUsage = true; } else if (arg == "-fopenacc") { options.features.Enable(Fortran::common::LanguageFeature::OpenACC);