diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index bed2a56b00351..b12cd6098e7aa 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3648,6 +3648,9 @@ def fopenmp_cuda_blocks_per_sm_EQ : Joined<["-"], "fopenmp-cuda-blocks-per-sm="> Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>; def fopenmp_cuda_teams_reduction_recs_num_EQ : Joined<["-"], "fopenmp-cuda-teams-reduction-recs-num=">, Group, Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>; +def fopenmp_default_none : Flag<["-"], "fopenmp-default-none">, Group, + Visibility<[FlangOption, FC1Option]>, + HelpText<"Add DEFAULT(NONE) to all OpenMP directives that allow data-sharing clauses.">; //===----------------------------------------------------------------------===// // Shared cc1 + fc1 OpenMP Target Options diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index c98fdbd157bac..521ae90e0bd16 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -855,6 +855,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, // is experimental. D.Diag(diag::warn_openmp_experimental); + if (Args.hasArg((options::OPT_fopenmp_default_none))) + CmdArgs.push_back("-fopenmp-default-none"); + // FIXME: Clang supports a whole bunch more flags here. break; default: diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h index b04f6117ae965..218e05e53aee0 100644 --- a/flang/include/flang/Common/Fortran-features.h +++ b/flang/include/flang/Common/Fortran-features.h @@ -54,7 +54,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines, PolymorphicActualAllocatableOrPointerToMonomorphicDummy, RelaxedPureDummy, UndefinableAsynchronousOrVolatileActual, AutomaticInMainProgram, PrintCptr, SavedLocalInSpecExpr, PrintNamelist, AssumedRankPassedToNonAssumedRank, - IgnoreIrrelevantAttributes) + IgnoreIrrelevantAttributes, OpenMPDefaultNone) // Portability and suspicious usage warnings ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable, diff --git a/flang/lib/Common/Fortran-features.cpp b/flang/lib/Common/Fortran-features.cpp index c86432874b8d8..c6f818478b065 100644 --- a/flang/lib/Common/Fortran-features.cpp +++ b/flang/lib/Common/Fortran-features.cpp @@ -17,6 +17,7 @@ LanguageFeatureControl::LanguageFeatureControl() { disable_.set(LanguageFeature::OldDebugLines); disable_.set(LanguageFeature::OpenACC); disable_.set(LanguageFeature::OpenMP); + disable_.set(LanguageFeature::OpenMPDefaultNone); disable_.set(LanguageFeature::CUDA); // !@cuf disable_.set(LanguageFeature::CudaManaged); disable_.set(LanguageFeature::CudaUnified); diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 648b88e84051c..648ad224a26f6 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -1023,6 +1023,10 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args, res.getLangOpts().OpenMPVersion, diags)) { res.getLangOpts().OpenMPVersion = Version; } + if (args.hasArg(clang::driver::options::OPT_fopenmp_default_none)) { + res.getFrontendOpts().features.Enable( + Fortran::common::LanguageFeature::OpenMPDefaultNone); + } if (args.hasArg(clang::driver::options::OPT_fopenmp_force_usm)) { res.getLangOpts().OpenMPForceUSM = 1; } diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 39478b58a9070..602e858403882 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2268,6 +2268,11 @@ void OmpAttributeVisitor::CreateImplicitSymbols( void OmpAttributeVisitor::Post(const parser::Name &name) { auto *symbol{name.symbol}; + // if -fopenmp-default-none was given on the command line, act as if + // DEFAULT(NONE) was present at the directive. + bool haveOpenMPDefaultNone = context_.languageFeatures().IsEnabled( + common::LanguageFeature::OpenMPDefaultNone); + if (symbol && !dirContext_.empty() && GetContext().withinConstruct) { if (IsPrivatizable(symbol) && !IsObjectWithDSA(*symbol)) { // TODO: create a separate function to go through the rules for @@ -2276,7 +2281,8 @@ void OmpAttributeVisitor::Post(const parser::Name &name) { if (Symbol * found{currScope().FindSymbol(name.source)}) { if (symbol != found) { name.symbol = found; // adjust the symbol within region - } else if (GetContext().defaultDSA == Symbol::Flag::OmpNone && + } else if ((haveOpenMPDefaultNone || + GetContext().defaultDSA == Symbol::Flag::OmpNone) && !symbol->test(Symbol::Flag::OmpThreadprivate) && // Exclude indices of sequential loops that are privatised in // the scope of the parallel region, and not in this scope. diff --git a/flang/test/Semantics/OpenMP/resolve07.f90 b/flang/test/Semantics/OpenMP/resolve07.f90 new file mode 100644 index 0000000000000..4a898903fae43 --- /dev/null +++ b/flang/test/Semantics/OpenMP/resolve07.f90 @@ -0,0 +1,34 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-default-none + + +! Test that -fopenmp-default-none shows the same errors as DEFAULT(NONE) +subroutine default_none() + integer a(3) + integer, parameter :: D=10 + A = 1 + B = 2 + !$omp parallel private(c) + !ERROR: The DEFAULT(NONE) clause requires that 'a' must be listed in a data-sharing attribute clause + A(1:2) = 3 + !ERROR: The DEFAULT(NONE) clause requires that 'b' must be listed in a data-sharing attribute clause + B = 4 + C = 5 + D + !$omp end parallel +end subroutine default_none + +! Test that indices of sequential loops are privatised and hence do not error +! for -fopenmp-default-none. +subroutine default_none_seq_loop + integer :: i + + !$omp parallel do + do i = 1, 10 + do j = 1, 20 + enddo + enddo +end subroutine + +program mm + call default_none() + call default_none_seq_loop() +end