Issue 204298
Summary [Flang][OpenMP] Confusing interpretation of threadprivate procedure pointers
Labels flang:frontend, flang:openmp
Assignees
Reporter yus3710-fj
    ## Summary

Flang's interpretation of threadprivate procedure pointers appears to be incorrect. I'd like to illustrate two cases: one that should be accepted and one that should be rejected.

The following are excerpts from language specifications:

* 7.3 `threadprivate` Directive (OpenMP 6.0)

> * The `threadprivate` directive must appear in the declaration section of a scoping unit in which the common block or variable is declared.

> * A variable that appears as an argument in a `threadprivate` directive must be declared in the scope of a module or have the `SAVE` attribute, either explicitly or implicitly.

* 2 Glossary (OpenMP 6.0)

> **variable**
>> A referencing variable or a named data storage block, for which the value can be defined and redefined during the execution of a program; for C/C++, this includes **const**-qualified types when explicitly permitted.

* 15.2.2.4 Procedure pointers (Fortran 2023)

> A procedure pointer is a procedure that has the POINTER attribute.

* 8.5.16 SAVE attribute (Fortran 2023)

> A variable, common block, or procedure pointer declared in the scoping unit of a main program, module, or submodule implicitly has the SAVE attribute, which may be confirmed by explicit specification.


### Should be accepted

OpenMP 6.0 does not specify the order of statements or directives. Therefore, I believe the following code should be accepted.

* test.f90

```fortran
!module mod
  !save ::a,b,c,d,e

  !$omp threadprivate(a)
  external a
  pointer a

  !$omp threadprivate(b)
 pointer b
  external b

  !$omp threadprivate(c)
 procedure(),pointer::c

  !$omp threadprivate(d)
  procedure()::d
 pointer::d

  !$omp threadprivate(e)
  pointer::e
  procedure()::e

 external s
end
```

* commands

```console
$ flang --version
flang version 23.0.0git (https://github.com/llvm/llvm-project.git e84e480bb5a53c794f303683df6460ddb44bb7ac)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to/llvm/build/bin
Build config: +assertions
$ flang test.f90 -fopenmp -c
error: Semantic errors in test.f90
test.f90:4:23: error: 'a' is a data object and may not be EXTERNAL
    !$omp threadprivate(a)
 ^
test.f90:5:12: error: EXTERNAL attribute not allowed on 'a'
 external a
             ^
test.f90:4:23: Declaration of 'a'
    !$omp threadprivate(a)
                        ^
test.f90:8:23: error: 'b' is a data object and may not be EXTERNAL
    !$omp threadprivate(b)
 ^
test.f90:10:12: error: EXTERNAL attribute not allowed on 'b'
 external b
             ^
test.f90:8:23: Declaration of 'b'
    !$omp threadprivate(b)
                        ^
test.f90:13:24: error: 'c' is already declared as an object
    procedure(),pointer::c
 ^
test.f90:12:23: Declaration of 'c'
    !$omp threadprivate(c)
 ^
test.f90:16:16: error: 'd' is already declared as an object
    procedure()::d
                 ^
test.f90:15:23: Declaration of 'd'
    !$omp threadprivate(d)
 ^
test.f90:21:16: error: 'e' is already declared as an object
 procedure()::e
                 ^
test.f90:19:23: Declaration of 'e'
 !$omp threadprivate(e)
                        ^
```

The issue does not occur under the following conditions:
* Specifying `SAVE` attribute explicitly.
* Placing `threadprivate` directives after the declarations:
 ```diff
  @@ -1,24 +1,24 @@
   !module mod
     !save ::a,b,c,d,e
   
 -  !$omp threadprivate(a)
     external a
     pointer a
  +  !$omp threadprivate(a)
   
  -  !$omp threadprivate(b)
     pointer b
 external b
  +  !$omp threadprivate(b)
   
  -  !$omp threadprivate(c)
 procedure(),pointer::c
  +  !$omp threadprivate(c)
   
  -  !$omp threadprivate(d)
     procedure()::d
     pointer::d
  +  !$omp threadprivate(d)
   
  -  !$omp threadprivate(e)
     pointer::e
 procedure()::e
  +  !$omp threadprivate(e)
   
     external s
   end
 ```

### Should be rejected

Procedure pointers are defined as procedures **with the POINTER attribute**. Without this attribute, these entities are not considered variables. Therefore, I believe the following code should be rejected.

* test2.f90

```fortran
module m
  procedure() :: b
  !$omp threadprivate(b)

  external    :: d
  !$omp threadprivate(d)

 integer,external :: f
  !$omp threadprivate(f)
end

program main
 procedure() :: bb
  !$omp threadprivate(bb)

  external    :: dd
  !$omp threadprivate(dd)

  integer,external :: ff
  !$omp threadprivate(ff)
end
```

* commands

```console
$ flang --version
flang version 23.0.0git (https://github.com/llvm/llvm-project.git b51054818b78dc395cd4d33f17cfb6e98a36a76d)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /path/to/llvm/build/bin
Build config: +assertions
$ flang test2.f90 -fopenmp && ./a.out
$
```

## Other Compilers

* GFortran
 ```console
  $ gfortran --version
  GNU Fortran (GCC) 15.2.0
  Copyright (C) 2025 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  $ gfortran test.f90 -fopenmp -c
  $ gfortran test2.f90 -fopenmp && ./a.out
  $
 ```

* Intel Fortran
  ```console
  $ ifx --version
  ifx (IFX) 2025.3.2 20260112
  Copyright (C) 1985-2026 Intel Corporation. All rights reserved.
 
  $ ifx -O0 test.f90 -qopenmp -c
  test.f90(5): error #6406: Conflicting attributes or multiple declaration of name.   [A]
    external a
 -----------^
  test.f90(10): error #6406: Conflicting attributes or multiple declaration of name.   [B]
    external b
  -----------^
  test.f90(13): error #6406: Conflicting attributes or multiple declaration of name.   [C]
 procedure(),pointer::c
  -----------------------^
  test.f90(16): error #6406: Conflicting attributes or multiple declaration of name.   [D]
 procedure()::d
  ---------------^
  test.f90(21): error #6406: Conflicting attributes or multiple declaration of name.   [E]
    procedure()::e
 ---------------^
  test.f90(4): error #7909: A variable that appears in a THREADPRIVATE directive and is not declared in the scope of a module must have the SAVE attribute.   [A]
    !$omp threadprivate(a)
 ----------------------^
  test.f90(8): error #7909: A variable that appears in a THREADPRIVATE directive and is not declared in the scope of a module must have the SAVE attribute.   [B]
    !$omp threadprivate(b)
 ----------------------^
  test.f90(12): error #7909: A variable that appears in a THREADPRIVATE directive and is not declared in the scope of a module must have the SAVE attribute.   [C]
    !$omp threadprivate(c)
 ----------------------^
  test.f90(15): error #7909: A variable that appears in a THREADPRIVATE directive and is not declared in the scope of a module must have the SAVE attribute.   [D]
    !$omp threadprivate(d)
 ----------------------^
  test.f90(19): error #7909: A variable that appears in a THREADPRIVATE directive and is not declared in the scope of a module must have the SAVE attribute.   [E]
    !$omp threadprivate(e)
 ----------------------^
  compilation aborted for test.f90 (code 1)
  $ ifx -O0 test2.f90 -qopenmp && ./a.out
  test2.f90(3): error #6409: This name has already been used as an external procedure name.   [B]
    !$omp threadprivate(b)
  ----------------------^
  test2.f90(6): error #6409: This name has already been used as an external procedure name.   [D]
 !$omp threadprivate(d)
  ----------------------^
  test2.f90(9): error #6423: This name has already been used as an external function name.   [F]
 !$omp threadprivate(f)
  ----------------------^
  test2.f90(9): error #7655: A variable is required in this OpenMP* context.   [F]
    !$omp threadprivate(f)
  ----------------------^
  test2.f90(14): error #6409: This name has already been used as an external procedure name.   [BB]
 !$omp threadprivate(bb)
  ----------------------^
  test2.f90(17): error #6409: This name has already been used as an external procedure name. [DD]
    !$omp threadprivate(dd)
  ----------------------^
 test2.f90(20): error #6423: This name has already been used as an external function name.   [FF]
    !$omp threadprivate(ff)
 ----------------------^
  test2.f90(20): error #7655: A variable is required in this OpenMP* context.   [FF]
    !$omp threadprivate(ff)
 ----------------------^
  compilation aborted for test2.f90 (code 1)
 ```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to