22

What is the scope of a pragma directive? For example, if I say #pragma warning(disable: 4996) in a header file A that is included from a different file B, will that also disable all those warnings inside B? Or should I enable the warning at the end of file A again?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
  • 3
    Isn't this something you can test yourself? – Leigh Feb 22 '11 at 13:24
  • Anyway don't use "enable" - use "push"/"pop" - http://stackoverflow.com/q/4193476/57428 – sharptooth Feb 22 '11 at 13:27
  • 6
    @Leigh: Testing only reveals how some particular version behaves in your particular test scenario. That's very different from getting an overview of how it is supposed to work. – sbi Feb 22 '11 at 13:33
  • @sbi: We all know "how it works" and "how it's supposed to work" don't always match up. Not saying you're wrong, I just didn't read the question as "How is #pragma **supposed** to work". – Leigh Feb 22 '11 at 13:39

3 Answers3

22

It is till the end of the translation unit. Informally, a TU is the source file with its include files.

The usual pattern is this:

#pragma warning (push) //save
#pragma warning (disable: xxxx)
#pragma warning (disable: yyyy)
...

//code

#pragma warning (pop) //restore prev settings

for example

//A.h
#pragma once
#pragma warning (disable: 1234)
#include "b.h"

//b.h
#pragma once
//when included after a.h 1234 will be disabled

//c.cpp
#include "a.h" //warnings 1234 from b.h is disabled

//d.cpp
#include "b.h" //warnings 1234 from b.h are not disabled
#include "a.h"
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    `+1`, because "end of TU" is right and the mandatory hint to "push"/"pop" is given. – sbi Feb 22 '11 at 13:35
  • 3
    +1, I would still mention that `pragma` are compiler specific and that though this is a "common" implementation but no-one is bounded to it. In particular... templates and other inline functions can play havoc with pragmas. Do you use the pragma stack of the template definition or the current one ? Neither option is satisfactory :/ – Matthieu M. Feb 22 '11 at 13:54
  • @armen There can be exceptions to your scope rules, I believe. See:http://stackoverflow.com/questions/8107844/how-can-i-work-around-warning-c4505-in-third-party-libraries – Chris Morris Mar 12 '12 at 19:06
  • @ChrisMorris: I read the question and the answers you linked to, but I don't see how they are in any way exceptions to "my" scope rules. I think they fit perfectly. – Armen Tsirunyan Mar 12 '12 at 19:11
  • @ArmenTsirunyan The linked page explains that pushing the pragma state, disabling a warning (for C4505, at least), and then popping the pragma state leads to warning C4505 not being disabled at all. Doesn't that violate your scope rules? Basically, there are exceptions to your scope rules (for certain warning), right? – Chris Morris Mar 12 '12 at 19:38
  • 2
    @Chris: The ***scope*** of any pragma directive is from its definition/declaration till the end of the translation unit. But how the pragma actually ***works*** is another matter (not covered by the C++ standard). In the linked question, the warning always occurs at the end of the translation unit(which, as explained in the accepted answer), is logical. The scope of pragma doesn't change. It's rather about the scope of the warning... – Armen Tsirunyan Mar 12 '12 at 19:58
  • @ArmenTsirunyan Thank you for the clarification. I now see that it is the warning that has an exceptional scope, not the pragma statement, itself. – Chris Morris Mar 12 '12 at 20:07
  • @Chris: You're welcome. I'm glad we came to a common understanding – Armen Tsirunyan Mar 12 '12 at 20:28
8

Pragmas are specific for the compiler and platform in use. So the best bet is to look at compiler's documentation.

For IBM compilers, for example:

Many pragma directives can be specified at any point within the source code in a compilation unit; others must be specified before any other directives or source code statements. In the individual descriptions for each pragma, the "Usage" section describes any constraints on the pragma's placement.

In general, if you specify a pragma directive before any code in your source program, it applies to the entire compilation unit, including any header files that are included. For a directive that can appear anywhere in your source code, it applies from the point at which it is specified, until the end of the compilation unit.

You can further restrict the scope of a pragma's application by using complementary pairs of pragma directives around a selected section of code. For example, using #pragma options source and #pragma options nosource directives as follows requests that only the selected parts of your source code be included in your compiler listing:

#pragma options source 

/*  Source code between the source and nosource pragma
    options is included in the compiler listing                */

#pragma options nosource

Many pragmas provide "pop" or "reset" suboptions that allow you to enable and disable pragma settings in a stack-based fashion; examples of these are provided in the relevant pragma descriptions.

Generally, pragma should have effect right after its declaration, no matter from what header it comes, until the end of translation unit. However, there are some pragmas that affect the whole program. For example, Microsoft-specific "link" pragma that adds dependency on some library to the translation unit and all its "users".

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
1

Yes, it will also disable the warnings inside B.

A translation unit is a .cpp file and all its included files expanded out into one great big file. That pragma will last to the end of the translation unit, or until another #pragma warning changes the setting. Or, if you're compiler supports #pragma push and #pragma pop, it will last until the next #pragma pop.

'#pragma push' and '#pragma pop' allow you to create scopes. #pragma warnings within such a scope will apply to the end of the scope.

Scott Langham
  • 58,735
  • 39
  • 131
  • 204