Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -844,26 +844,71 @@ common::visitors{ [&](const parser::Designator &) { if (const auto *name{parser::Unwrap(ompObject)}) { - const auto &scope{context_.FindScope(name->symbol->name())}; - if (FindCommonBlockContaining(*name->symbol)) { + const auto &useScope{ + context_.FindScope(GetContext().directiveSource)}; + const auto &declScope{ + GetProgramUnitContaining(name->symbol->GetUltimate())}; + const auto *sym = + declScope.parent().FindSymbol(name->symbol->name()); + if (sym && + (sym->has() || + sym->has())) { + context_.Say(name->source, + "The module name or main program name cannot be in a %s " + "directive"_err_en_US, + ContextDirectiveAsFortran()); + } else if (name->symbol->GetUltimate().IsSubprogram()) { + if (GetContext().directive == + llvm::omp::Directive::OMPD_threadprivate) + context_.Say(name->source, + "The procedure name cannot be in a %s " + "directive"_err_en_US, + ContextDirectiveAsFortran()); + // TODO: Check for procedure name in declare target directive. + } else if (name->symbol->attrs().test(Attr::PARAMETER)) { + if (GetContext().directive == + llvm::omp::Directive::OMPD_threadprivate) + context_.Say(name->source, + "The entity with PARAMETER attribute cannot be in a %s " + "directive"_err_en_US, + ContextDirectiveAsFortran()); + else if (GetContext().directive == + llvm::omp::Directive::OMPD_declare_target) + context_.Say(name->source, + "The entity with PARAMETER attribute is used in a %s " + "directive"_en_US, + ContextDirectiveAsFortran()); + } else if (FindCommonBlockContaining(*name->symbol)) { context_.Say(name->source, "A variable in a %s directive cannot be an element of a " "common block"_err_en_US, ContextDirectiveAsFortran()); } else if (!IsSave(*name->symbol) && - scope.kind() != Scope::Kind::MainProgram && - scope.kind() != Scope::Kind::Module) { + declScope.kind() != Scope::Kind::MainProgram && + declScope.kind() != Scope::Kind::Module) { context_.Say(name->source, "A variable that appears in a %s directive must be " "declared in the scope of a module or have the SAVE " "attribute, either explicitly or implicitly"_err_en_US, ContextDirectiveAsFortran()); - } - if (FindEquivalenceSet(*name->symbol)) { + } else if (useScope != declScope) { + context_.Say(name->source, + "The %s directive must appear in the declaration section " + "of a scoping unit in which the common block or variable " + "is declared"_err_en_US, + ContextDirectiveAsFortran()); + } else if (FindEquivalenceSet(*name->symbol)) { context_.Say(name->source, "A variable in a %s directive cannot appear in an " "EQUIVALENCE statement"_err_en_US, ContextDirectiveAsFortran()); + } else if (name->symbol->test(Symbol::Flag::OmpThreadprivate) && + GetContext().directive == + llvm::omp::Directive::OMPD_declare_target) { + context_.Say(name->source, + "A THREADPRIVATE variable cannot appear in a %s " + "directive"_err_en_US, + ContextDirectiveAsFortran()); } } }, @@ -1407,6 +1452,53 @@ llvm::omp::Clause::OMPC_copyprivate, {llvm::omp::Clause::OMPC_nowait}); } + // [5.1] 2.21.2 Threadprivate Directive Restriction + OmpClauseSet threadprivateAllowedSet{llvm::omp::Clause::OMPC_copyin, + llvm::omp::Clause::OMPC_copyprivate, llvm::omp::Clause::OMPC_schedule, + llvm::omp::Clause::OMPC_num_threads, llvm::omp::Clause::OMPC_thread_limit, + llvm::omp::Clause::OMPC_if}; + for (auto it : GetContext().clauseInfo) { + llvmOmpClause type = it.first; + const auto *clause = it.second; + if (!threadprivateAllowedSet.test(type)) { + if (const auto *objList{GetOmpObjectList(*clause)}) { + for (const auto &ompObject : objList->v) { + std::visit( + common::visitors{ + [&](const parser::Designator &) { + if (const auto *name{ + parser::Unwrap(ompObject)}) { + if (name->symbol->GetUltimate().test( + Symbol::Flag::OmpThreadprivate)) + context_.Say(name->source, + "A THREADPRIVATE variable cannot be in %s " + "clause"_err_en_US, + parser::ToUpperCaseLetters( + getClauseName(type).str())); + } + }, + [&](const parser::Name &name) { + if (name.symbol) { + for (const auto &mem : + name.symbol->get().objects()) { + if (mem->GetUltimate().test( + Symbol::Flag::OmpThreadprivate)) + context_.Say(name.source, + "A THREADPRIVATE variable cannot be in %s " + "clause"_err_en_US, + parser::ToUpperCaseLetters( + getClauseName(type).str())); + break; + } + } + }, + }, + ompObject.u); + } + } + } + } + CheckRequireAtLeastOneOf(); } Index: flang/test/Semantics/omp-declarative-directive.f90 =================================================================== --- flang/test/Semantics/omp-declarative-directive.f90 +++ flang/test/Semantics/omp-declarative-directive.f90 @@ -44,9 +44,8 @@ contains subroutine foo !$omp declare target - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !WARNING: The entity with PARAMETER attribute is used in a DECLARE TARGET directive + !WARNING: The entity with PARAMETER attribute is used in a DECLARE TARGET directive !$omp declare target (foo, N, M) !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly Index: flang/test/Semantics/omp-declare-target02.f90 =================================================================== --- flang/test/Semantics/omp-declare-target02.f90 +++ flang/test/Semantics/omp-declare-target02.f90 @@ -64,14 +64,14 @@ !$omp declare target (arr3) !ERROR: Implicitly typed local entity 'blk2' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target (blk2) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block !$omp declare target (a2) !ERROR: Implicitly typed local entity 'blk3' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target (blk3) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block @@ -83,14 +83,14 @@ !$omp declare target to (arr3_to) !ERROR: Implicitly typed local entity 'blk2_to' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target to (blk2_to) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block !$omp declare target to (a2_to) !ERROR: Implicitly typed local entity 'blk3_to' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target to (blk3_to) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block @@ -102,14 +102,14 @@ !$omp declare target link (arr3_link) !ERROR: Implicitly typed local entity 'blk2_link' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target link (blk2_link) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block !$omp declare target link (a2_link) !ERROR: Implicitly typed local entity 'blk3_link' not allowed in specification expression - !ERROR: A variable that appears in a DECLARE TARGET directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp declare target link (blk3_link) !ERROR: A variable in a DECLARE TARGET directive cannot be an element of a common block Index: flang/test/Semantics/omp-declare-target03.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-declare-target03.f90 @@ -0,0 +1,44 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.14.7 Declare Target Directive + +module mod0 + integer :: mi + +contains + subroutine subm() + integer, save :: mmi + + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp declare target (mi) + mi = 1 + contains + subroutine subsubm() + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp declare target (mmi) + end + end +end + +module mod1 + integer :: mod_i +end + +program main + use mod1 + integer, save :: i + integer :: j + + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp declare target (mod_i) + +contains + subroutine sub() + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !ERROR: The DECLARE TARGET directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp declare target (i, j) + i = 1 + j = 1 + end +end Index: flang/test/Semantics/omp-declare-target04.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-declare-target04.f90 @@ -0,0 +1,17 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.14.7 Declare Target Directive + +module mod1 +end + +program main + use mod1 + + !ERROR: The module name or main program name cannot be in a DECLARE TARGET directive + !$omp declare target (mod1) + + !ERROR: The module name or main program name cannot be in a DECLARE TARGET directive + !$omp declare target (main) +end Index: flang/test/Semantics/omp-declare-target05.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-declare-target05.f90 @@ -0,0 +1,16 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.14.7 Declare Target Directive + +program main + integer, save :: x, y + + !$omp threadprivate(x) + + !ERROR: A THREADPRIVATE variable cannot appear in a DECLARE TARGET directive + !ERROR: A THREADPRIVATE variable cannot appear in a DECLARE TARGET directive + !$omp declare target (x, y) + + !$omp threadprivate(y) +end Index: flang/test/Semantics/omp-threadprivate02.f90 =================================================================== --- flang/test/Semantics/omp-threadprivate02.f90 +++ flang/test/Semantics/omp-threadprivate02.f90 @@ -41,7 +41,7 @@ !$omp threadprivate(/blk2/) !ERROR: Implicitly typed local entity 'blk2' not allowed in specification expression - !ERROR: A variable that appears in a THREADPRIVATE directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp threadprivate(blk2) !ERROR: A variable in a THREADPRIVATE directive cannot be an element of a common block @@ -50,7 +50,7 @@ !$omp threadprivate(/blk3/) !ERROR: Implicitly typed local entity 'blk3' not allowed in specification expression - !ERROR: A variable that appears in a THREADPRIVATE directive must be declared in the scope of a module or have the SAVE attribute, either explicitly or implicitly + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared !$omp threadprivate(blk3) !ERROR: A variable in a THREADPRIVATE directive cannot be an element of a common block Index: flang/test/Semantics/omp-threadprivate03.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-threadprivate03.f90 @@ -0,0 +1,44 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.21.2 Threadprivate Directive + +module mod0 + integer :: mi + +contains + subroutine subm() + integer, save :: mmi + + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp threadprivate(mi) + mi = 1 + contains + subroutine subsubm() + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp threadprivate(mmi) + end + end +end + +module mod1 + integer :: mod_i +end + +program main + use mod1 + integer, save :: i + integer :: j + + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp threadprivate(mod_i) + +contains + subroutine sub() + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !ERROR: The THREADPRIVATE directive must appear in the declaration section of a scoping unit in which the common block or variable is declared + !$omp threadprivate(i, j) + i = 1 + j = 1 + end +end Index: flang/test/Semantics/omp-threadprivate04.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-threadprivate04.f90 @@ -0,0 +1,17 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.21.2 Threadprivate Directive + +module mod1 +end + +program main + use mod1 + + !ERROR: The module name or main program name cannot be in a THREADPRIVATE directive + !$omp threadprivate(mod1) + + !ERROR: The module name or main program name cannot be in a THREADPRIVATE directive + !$omp threadprivate(main) +end Index: flang/test/Semantics/omp-threadprivate05.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-threadprivate05.f90 @@ -0,0 +1,48 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenmp +! OpenMP Version 5.1 +! Check OpenMP construct validity for the following directives: +! 2.21.2 Threadprivate Directive + +program main + integer :: i, N = 10 + integer, save :: x + common /blk/ y + + !$omp threadprivate(x, /blk/) + + !$omp parallel num_threads(x) + !$omp end parallel + + !$omp single copyprivate(x, /blk/) + !$omp end single + + !$omp do schedule(static, x) + do i = 1, N + y = x + end do + !$omp end do + + !$omp parallel copyin(x, /blk/) + !$omp end parallel + + !$omp parallel if(x > 1) + !$omp end parallel + + !$omp teams thread_limit(x) + !$omp end teams + + !ERROR: A THREADPRIVATE variable cannot be in PRIVATE clause + !ERROR: A THREADPRIVATE variable cannot be in PRIVATE clause + !$omp parallel private(x, /blk/) + !$omp end parallel + + !ERROR: A THREADPRIVATE variable cannot be in FIRSTPRIVATE clause + !ERROR: A THREADPRIVATE variable cannot be in FIRSTPRIVATE clause + !$omp parallel firstprivate(x, /blk/) + !$omp end parallel + + !ERROR: A THREADPRIVATE variable cannot be in SHARED clause + !ERROR: A THREADPRIVATE variable cannot be in SHARED clause + !$omp parallel shared(x, /blk/) + !$omp end parallel +end