https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91517
--- Comment #2 from Peter Boyle <paboyle at ph dot ed.ac.uk> --- GCC preprocessor moves location of _Pragma operator in sequence in a variadic macro: Simpler case: #define thread_for( i, num, ... ) for ( uint64_t i=0;i<num;i++) { __VA_ARGS__ } thread_for(i,N,{ _Pragma("omp critical") { a+=i; } }); for(uint64_t i=0;i<N;i++) { _Pragma("omp critical"){ a+=i;} } Produces: # 1 "tmp.cc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tmp.cc" #pragma omp critical # 3 "tmp.cc" for ( uint64_t i=0;i<N;i++) { { { a+=i; } } } ; for(uint64_t i=0;i<N;i++) { # 8 "tmp.cc" #pragma omp critical # 8 "tmp.cc" { a+=i;} } Clang preprocessor preserves _Pragma in right place: # 1 "tmp.cc" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 374 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "tmp.cc" 2 for ( uint64_t i=0;i<N;i++) { { # 3 "tmp.cc" #pragma omp critical # 3 "tmp.cc" { a+=i; }} }; for(uint64_t i=0;i<N;i++) { # 8 "tmp.cc" #pragma omp critical # 8 "tmp.cc" { a+=i;} }