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










share|improve this question






















  • 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















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










share|improve this question






















  • 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













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










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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


















  • 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












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 );
}
)





share|improve this answer





















  • Boo to undefined behavior! Thanks for the detailed explanation.
    – memorableUserNameHere
    yesterday


















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.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    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

























    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 );
    }
    )





    share|improve this answer





















    • Boo to undefined behavior! Thanks for the detailed explanation.
      – memorableUserNameHere
      yesterday















    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 );
    }
    )





    share|improve this answer





















    • Boo to undefined behavior! Thanks for the detailed explanation.
      – memorableUserNameHere
      yesterday













    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 );
    }
    )





    share|improve this answer













    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 );
    }
    )






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 2 days ago









    John Bollinger

    76.5k63771




    76.5k63771












    • 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




    Boo to undefined behavior! Thanks for the detailed explanation.
    – memorableUserNameHere
    yesterday












    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.






    share|improve this answer

























      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.






      share|improve this answer























        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.






        share|improve this answer












        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 2 days ago









        zwol

        95.7k24167266




        95.7k24167266






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Sphinx de Gizeh

            Dijon

            Équipe cycliste