Incorrect Substitution of OpenMP Pragma in Macro Expansion
up vote
2
down vote
favorite
When an OpenMP pragma is used as part of an argument for a macro, it gets incorrectly substituted.
In this code:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
I would expect that it would be expanded to:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
However, (according to gcc -E) it becomes expanded to:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
Is this correct behavior?
How can I get the expected behavior, preferably without changing the arguments to the macro?
Does this happen with all pragmas?
Is this an effect of the variadic macro?
Do other compilers perform the same substitution?
Using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
c gcc macros openmp variadic-macros
add a comment |
up vote
2
down vote
favorite
When an OpenMP pragma is used as part of an argument for a macro, it gets incorrectly substituted.
In this code:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
I would expect that it would be expanded to:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
However, (according to gcc -E) it becomes expanded to:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
Is this correct behavior?
How can I get the expected behavior, preferably without changing the arguments to the macro?
Does this happen with all pragmas?
Is this an effect of the variadic macro?
Do other compilers perform the same substitution?
Using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
c gcc macros openmp variadic-macros
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal{}like a normal person.
– John Bollinger
2 days ago
1
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
When an OpenMP pragma is used as part of an argument for a macro, it gets incorrectly substituted.
In this code:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
I would expect that it would be expanded to:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
However, (according to gcc -E) it becomes expanded to:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
Is this correct behavior?
How can I get the expected behavior, preferably without changing the arguments to the macro?
Does this happen with all pragmas?
Is this an effect of the variadic macro?
Do other compilers perform the same substitution?
Using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
c gcc macros openmp variadic-macros
When an OpenMP pragma is used as part of an argument for a macro, it gets incorrectly substituted.
In this code:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
I would expect that it would be expanded to:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
However, (according to gcc -E) it becomes expanded to:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
Is this correct behavior?
How can I get the expected behavior, preferably without changing the arguments to the macro?
Does this happen with all pragmas?
Is this an effect of the variadic macro?
Do other compilers perform the same substitution?
Using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
c gcc macros openmp variadic-macros
c gcc macros openmp variadic-macros
asked 2 days ago
memorableUserNameHere
1607
1607
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal{}like a normal person.
– John Bollinger
2 days ago
1
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday
add a comment |
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal{}like a normal person.
– John Bollinger
2 days ago
1
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal
{} like a normal person.– John Bollinger
2 days ago
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal
{} like a normal person.– John Bollinger
2 days ago
1
1
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
add a comment |
up vote
1
down vote
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
add a comment |
up vote
1
down vote
accepted
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
answered 2 days ago
John Bollinger
76.5k63771
76.5k63771
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
add a comment |
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
Boo to undefined behavior! Thanks for the detailed explanation.
– memorableUserNameHere
yesterday
add a comment |
up vote
1
down vote
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
add a comment |
up vote
1
down vote
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
add a comment |
up vote
1
down vote
up vote
1
down vote
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
answered 2 days ago
zwol
95.7k24167266
95.7k24167266
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53402468%2fincorrect-substitution-of-openmp-pragma-in-macro-expansion%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I'm curious: what's the real target use case? The example presented in the question cannot be it, because it would be simpler and less troublesome to put in literal
{}like a normal person.– John Bollinger
2 days ago
1
The real use case is a code timing library that inserts timer stop, start, and time elapsed reporting code around the code section. It's been working quite well so far but this OpenMP example unfortunately breaks things. To get around this I'll add some macros for those individual components so the code section is not a macro argument.
– memorableUserNameHere
yesterday