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:
- Why clang behaves so strangely? Why does its parser appear to depend on external libraries, like
libgomp
? - 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).