zkoza
zkoza

Reputation: 2869

OpenMP + clang sometimes fail with a variable declared from structured binding

Here's a minimal, reproducible example:

#include <tuple>

int main()
{
  std::pair<int, int> pair {1, 2};
  int sum = 0;
#pragma omp parallel for
  for (int i = 1; i < 10; i++)
  {
      auto [a, b] = pair;
#pragma omp critical 
      sum += a + b;
  }
}

Now, g++ (10.2.0) compiles clean

g++ 1.cpp -std=c++17 -fopenmp -pedantic

Replacing g++ with clang++ (11.0.0) results in:

> clang++ 1.cpp -std=c++17 -fopenmp -pedantic
1.cpp:12:14: error: reference to local binding 'a' declared in enclosing context
      sum += a + b;
             ^
1.cpp:10:13: note: 'a' declared here
      auto [a, b] = pair;
            ^
1.cpp:12:18: error: reference to local binding 'b' declared in enclosing context
      sum += a + b;
                 ^
1.cpp:10:16: note: 'b' declared here
      auto [a, b] = pair;
               ^
2 errors generated.

Now comes a real surprise. In my Linux (Manjaro) I need to link clang++ with libgomp to use OpenMP,

clang++ 1.cpp -std=c++17 -fopenmp=libgomp -pedantic

and now the program compiles with no error, no warning.

I found it in a larger program written in QtCreator. The problem is that now QtCreator shows a red bullet to warn me against an error, but the program compiles without warning (g++).

Two questions:

  1. Why clang behaves so strangely? Why does its parser appear to depend on external libraries, like libgomp?
  2. Is there a way to silence the error warning in QtCreator without disabling the "error: reference to local binding 'XXX' declared in enclosing context" altogether, other then by rewriting the code?

See also (similar question, but with lambdas instead OpenMP): Lambda implicit capture fails with variable declared from structured binding

EDIT: Full output of clang with -v:

> clang++ 1.cpp -fopenmp  -std=c++17 -v -pedantic
clang version 11.0.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/10.2.0
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/10.2.0
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
 "/usr/bin/clang-11" -cc1 -triple x86_64-pc-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name 1.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/lib/clang/11.0.0 -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0 -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/x86_64-pc-linux-gnu -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -pedantic -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/zkoza/so -ferror-limit 19 -fopenmp -fopenmp-cuda-parallel-target-regions -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -fcolor-diagnostics -faddrsig -o /tmp/1-45b8f4.o -x c++ 1.cpp
clang -cc1 version 11.0.0 based upon LLVM 11.0.0 default target x86_64-pc-linux-gnu
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0
 /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/x86_64-pc-linux-gnu
 /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../include/c++/10.2.0/backward
 /usr/local/include
 /usr/lib/clang/11.0.0/include
 /usr/include
End of search list.
1.cpp:12:14: error: reference to local binding 'a' declared in enclosing context
      sum += a + b;
             ^
1.cpp:10:13: note: 'a' declared here
      auto [a, b] = pair;
            ^
1.cpp:12:18: error: reference to local binding 'b' declared in enclosing context
      sum += a + b;
                 ^
1.cpp:10:16: note: 'b' declared here
      auto [a, b] = pair;
               ^
2 errors generated.

EDIT 2: The error disappears if I comment out the critical section. Apparently clang 11's module controlling program names is a bit in conflict with a similar module that must be implemented for OpenMP (to decide which variables inside parallel regions are thread-local and which are shared).

Upvotes: 1

Views: 724

Answers (1)

Jim Cownie
Jim Cownie

Reputation: 2869

I cannot answer why clang 11.0.1 does not like this code, though one can see the effect in Compiler Explorer (https://godbolt.org/z/qTTcGf.

However, one can also see there why adding the perverse flag which you think is enabling use of libgomp makes the code compile. The reason is that that flag is disabling OpenMP completely. You can see that there are no calls to OpenMP runtime routines in https://godbolt.org/z/o3TaGz . I have no idea why that flag is not rejected, since it makes absolutely no sense to ask Clang to link against libgomp, as Clang cannot generate the calls into the GCC OpenMP RTL (these interfaces are different). It is also not documented as a reasonable thing to do (see https://clang.llvm.org/docs/UsersManual.html#openmp-features ) which does not show -fopenmp taking any argument.

You can also see (at https://godbolt.org/z/7hcdrr) that the mainline Clang now accepts your code (without disabling OpenMP) and generates code that includes calls into the OpenMP runtime.

So, overall

  1. Clang 11 has a bug which has been fixed in mainline.
  2. You are passing an unsupported argument to clang and it is then turning off OpenMP compilation.

Upvotes: 3

Related Questions