Changes between Initial Version and Version 1 of Guidelines/WarningsGuidelines


Ignore:
Timestamp:
Apr 13, 2010, 11:01:40 AM (13 years ago)
Author:
Paul A. Bristow
Comment:

Moved from Editing guildings/Maintenance guidlelines section

Legend:

Unmodified
Added
Removed
Modified
  • Guidelines/WarningsGuidelines

    v1 v1  
     1== Managing Warnings from Compilers (and other tools) == #warnings
     2
     3=== Avoid warnings, Eliminate warning, Suppress Warnings, or Document. ===
     4
     5Boost aims to avoid warnings messages as far as is reasonably practicable,
     6even when compiled with the highest and most pedantic warning level,
     7avoiding vendor specific extensions if possible.
     8
     9Warnings often indicate real problems.  Sometimes they only manifest
     10on a particular platform, revealing a portability issue.  Sometimes
     11they indicate that the code doesn't account for a runtime condition,
     12like overflow, which the warning can only suggest as a possibility.
     13
     14Suppressing a warning without altering code may simply mask a problem.
     15The right approach is to determine why the warning occurs is to decide
     16whether it is correct in the context, and if so, apply appropriate remediation.
     17If the warning is not correct in the context, only then should it be suppressed.
     18
     19Because developers don't have the same knowledge, even among Boost
     20developers, Boost is amassing information to help them know when a
     21warning is significant and not.  That information can show cases in
     22which a warning is legitimate and when it isn't.  For the former,
     23there is help to understand how to change the code portably to
     24account for the problem revealed by the warning.  For the latter,
     25there is information on how to suppress the warning in a portable way.
     26
     27Changing code can lead to bugs.  Thus, changing code to eliminate a warning might create a bug.  That's unfortunate.
     28From a maintenance standpoint, however, most would prefer to see altered code to a
     29glob of preprocessor and pragma line noise that suppresses a warning in the unchanged code.
     30
     31Testing will reveal the bug.  If it doesn't, the testing is insufficient.
     32If the bug appears on an untested platform, then more testers are needed to be able to detect such bugs in the future.
     33
     34Breifly, for some users, any warning '''is''' a bug.
     35
     36See also [https://svn.boost.org/trac/boost/wiki/WarningFixes] for progress made on warning fixes/suppression.[[BR]]
     37
     38'''Reasons to eliminate or suppress warnings:'''
     39
     401  To allow users, whose environment requires no warnings, to use Boost code.
     41
     422  To avoid the nuisance, perhaps overwhelming, of spurious warning messages.
     43
     443  To improve code quality by focusing library writers' attention on potential problems.
     45
     464  To improve portability by focusing developer attention on potentially non-portable code.
     47
     485  To improve compliance with the C++ Standard.
     49
     506  To permit users to set high warning levels when using Boost libraries without being overwhelmed with a barrage of library warnings.
     51
     527  To document that warnings have been considered by the library author or maintainer
     53and are considered not significant.
     54
     558  For Boost, making the suppression local is more important than only suppressing a specific warning.
     56
     57'''What to do'''
     58
     591  Test compilation with the most pedantic setting for the compiler, and non-debug mode.
     60
     61'''For Microsoft Visual Studio''', this means setting level to 4 (command line /W4).[[BR]]
     62For code that doesn't deliberately use Microsoft language extensions, disable them with Disable MS extensions = Yes, command line option /Za[[BR]]
     63
     64To a jamfile add  <toolset>msvc:<cxxflags>/Za # disable MS extensions.[[BR]]
     65
     66If it proves impossible to compile with the /Za option (it is reported to cause trouble with the MS compiler, sometimes), just document this, including in the build jamfile.
     67
     68If only one (or a few) modules in a test (or other) build require MS extensions, you can selectively 'switch off' this 'disable' in the 'requirements' in the jamfile, for example:
     69
     70{{{
     71# pow test requires type_of that MS extensions.
     72run pow_test.cpp ../../test/build//boost_test_exec_monitor
     73        : # command line
     74        : # input files
     75        : # requirements
     76          -<toolset>msvc:<cxxflags>/Za # Requires type_of which requires MS extensions, so cancel /Za.
     77        : test_pow
     78;
     79
     80Note the leading - switches off the compiler switch /Za, producing output thus:
     81
     82compile-c-c++ ..\..\..\bin.v2\libs\math\test\test_pow.test\msvc-9.0\debug\asynch-exceptions-on\threading-multi\pow_test.obj
     83pow_test.cpp
     84using native typeof
     85
     86}}}
     87
     88
     89(You might also consider using Microsoft /Wall if available.  You may find
     90[http://www.geoffchappell.com/viewer.htm?doc=studies/msvc/cl/c1xx/warnings/index.htm&tx=2,27&ts=0,3820]
     91a helpful guide to the byzantine complexity of warnings).[[BR]]
     92
     93(If you wish to make '''all''' of your VS projects in ''' all''' VS solutions compile with other options '''by default''', you might consider (carefully) editing (with a text editor, very carefully, after keeping a copy of the original) the file C:\Program Files\Microsoft Visual Studio 9.0\VC\VCWizards\1033\common.js to change from the Microsoft defaults.  This does not seem to be officially documented as far as I know.  It may save you changing the project properties repeatedly.
     94
     95{{{
     96function AddCommonConfig(oProj, strProjectName,bAddUnicode,bForEmptyProject) in the sections for debug and/or release
     97
     98CLTool.DisableLanguageExtensions = true; // add to make the default NO MS extensions.
     99
     100LinkTool.LinkIncremental = linkIncrementalNo; // add
     101
     102CLTool.WarningLevel = WarningLevel_4; // change from 3 to 4 to making the default warning level 4
     103
     104}}}
     105
     106'''For GCC''' this means -Wall -pendantic 
     107
     108but you might consider adding specific warnings that are to be suppressed, for example:
     109
     110-pedantic -Wall -Wno-long-long -Wno-unused-value
     111
     112but this is a global setting, so you need to document that these warnings must be suppressed by users of this module.  This may be acceptable if they are building a library of entirely Boost modules.
     113
     114Using bjam add warnings=all to the invocation command line.
     115
     116Putting options in jam files allows setting to be made for one or more specified compiler(s).
     117
     118Some sample options in jamfile.v2 are:
     119
     120{{{
     121project 
     122    : requirements
     123      <toolset>gcc:<cxxflags>-Wno-missing-braces
     124      <toolset>darwin:<cxxflags>-Wno-missing-braces
     125      <toolset>acc:<cxxflags>+W2068,2461,2236,4070,4069 # Comments on warning message help readers who do not have ACC documentation to hand.
     126      <toolset>intel:<cxxflags>-nologo
     127      <toolset>msvc:<warnings>all # == /W4
     128      -<toolset>msvc:<define>_DEBUG # Undefine DEBUG.
     129      <toolset>msvc:<define>NDEBUG # Define NO debug, or release.
     130      <toolset>msvc:<asynch-exceptions>on # Needed for Boost.Test
     131      <toolset>msvc:<cxxflags>/Za # Disable MS extensions.
     132      #-<toolset>msvc:<cxxflags>/Za # (Re-)Enable MS extensions if these are definitely required for specific module.
     133      #  The define of macros below prevent warnings about the checked versions of SCL and CRT libraries.
     134      #  Most Boost code does not need these versions (as they are markedly slower).
     135      <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
     136      <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
     137      <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
     138      <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
     139      <toolset>msvc:<define>_CRT_NONSTDC_NO_DEPRECATE # Suppresses other warnings about using standard POSIX and C9X.
     140      #  Alternatively, you can just suppress the warnings (perhaps not the best way).
     141      <toolset>msvc:<cxxflags>/wd4996 # 'putenv': The POSIX name for this item is deprecated.
     142      <toolset>msvc:<cxxflags>/wd4512 # assignment operator could not be generated.
     143      <toolset>msvc:<cxxflags>/wd4224 # nonstandard extension used : formal parameter 'arg' was previously defined as a type.
     144      <toolset>msvc:<cxxflags>/wd4127 # expression is constant.
     145      <toolset>msvc:<cxxflags>/wd4701 # unreachable code - needed for lexical cast - temporary for Boost 1.40 & earlier.
     146   ...
     147    ;
     148}}}
     149
     150Using warning-as-errors will make it hard to miss warnings.
     151  Microsoft command line option /WX,
     152  gcc option -warning-as-errors
     153  gcc option -pedantic-errors
     154
     1552  Consider each warning and
     156
     157a  Rewrite the code to avoid the warning, if possible. For example, adding a static_cast will indicate that any warning about loss of accuracy has been judged not possible or significant. Remove or comment out parameters to avoid warnings about unused parameters. Placing /* comment */ around an unused variable name, allows the name still to be useful documentation.
     158
     159b  Use the compiler specific mechanism to suppress the warning message, but try hard to ensure that this is as local
     160to the package as possible so that users can still get warnings from *their code*.
     161
     162For MSVC, this involves pushing to save the current warning state, disabling the warning, and later popping to restore (abbreviated as ''push'n'pop'').
     163{{{
     164#if defined(_MSC_VER)
     165#pragma warning(push) // Save warning settings.
     166#pragma warning(disable : 4996) // Disable deprecated localtime/gmtime warning.
     167#endif
     168
     169...
     170
     171#if defined(_MSC_VER)
     172#pragma warning(pop) // Restore warnings to previous state.
     173#endif
     174
     175}}}
     176
     177Adding some or all of the warning message as a comment is helpful to tell ''readers'' what warning is being ignored, for example:
     178
     179{{{
     180#  pragma warning(disable: 4510) // default constructor could not be generated
     181}}}
     182
     183If the warning is only for a specific compiler version, use this approach:
     184
     185{{{
     186#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
     187#pragma warning(push)
     188#pragma warning(disable:4512) //assignment operator could not be generated
     189#endif
     190
     191...
     192
     193#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
     194#pragma warning(pop)
     195#endif
     196}}}
     197
     198c  Repeat this process with other compilers and use their specific suppression methods.
     199
     200d  If a warning cannot be eliminated or suppressed, explain why in the code and the documentation.  If appropriate, document in build files, as well.  Consider indicating the highest warning level possible or compiler-specific settings that will provide a warning-free build.
     201
     202
     203=== Specific Warnings and Suggested Actions. ===
     204
     205''These are just few for starters, and need more, especially for gcc. Suggestions may be wrong! ''
     206
     207The pragma or other code required to suppress warnings is in the right hand box, ready for copy and paste.
     208
     209'''Microsoft'''
     210
     211If you chose to suppress (rather than fix by recoding),
     212localise the warnings as far as possible by using push'n'pop pragmas (see above).
     213||Warning||Warning Description||Suggestions||Suppression||
     214
     215
     216||C4100|| unreferenced formal parameter||Either surround the parameter with C comments, for example: int */ my_variable */)or just delete if the variable name is uninformative. If in other's module(s), or you are too busy/idle, at least suppress warning. In generic code you might not be able to comment the variable name as it might actually be used to call a static function. In this case simply referencing the variable (varname;) in the function body eliminates the warning.||#  pragma warning(disable: 4100) // 'name' : unreferenced formal parameter||
     217
     218||C4127|| conditional expression is constant||Very common and many believe unhelpful, but a few find it informative, so do not suppress globally.  Even while(true) can trigger this!  Suppress. while(true) can be rewritten as for(;;) eliminating the warning. || #  pragma warning(disable: 4127) // conditional expression is constant.||
     219
     220||C4146|| unary minus operator applied to unsigned type, result still unsigned||This indicates a real error. ||Fix. ||
     221
     222||C4180||  qualifier applied to function type has no meaning; ignored||The meaningless qualifier can always be removed (or left as a comment if it informative) - but check that you didn't mean to put the const somewhere else. can always be suppressed.||#  pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored||
     223
     224||C4189||local variable is initialized but not referenced||This probably indicates a redundant variable and assignment, so probably remove it. If you are sure it is required (or has negligible cost for some documentation benefit), suppress.||#  pragma warning(disable: 4189) //local variable is initialized but not referenced||
     225
     226||C4224||nonstandard extension used : formal parameter 'arg' was previously defined as a type.||This will bite users who try to compile with Microsoft extensions disabled. So is most undesirable, but may be a major nuisance to change the names in code.However fixing is the Right Thing, but meanwhile suppressing may be helpful.||#  pragma warning(disable: 4224) // formal parameter 'arg' was previously defined as a type.||
     227
     228||C4244|| Conversion: possible loss of data.||Fix, for example changing type or using static_cast is best, suppress with much caution.||# pragma warning(disable:4244) // Conversion: possible loss of data.||
     229
     230||C4324||structure was padded due to __declspec(align())||Suppress||#pragma warning(disable:4324) // structure was padded due to __declspec(align())||
     231
     232||C4503||decorated name length exceeded||Suppress.  (Note that \boost\config\compiler\visualc.hpp includes this global suppression: #pragma warning(disable:4503)||#pragma warning( disable : 4503 ) // warning: decorated name length exceeded||
     233
     234||C4506||no definition for inline function||Provide a definition, or if you cannot/will not, suppress.||#  pragma warning(disable: 4506) // no definition for inline function||
     235
     236||C4512|| assignment operator could not be generated||Suppress using push'n'pop for the module(s) causing the warning. Adding the declaration (not the definition) of the appropriate operator=() as a private member does the trick as well.||#  pragma warning(disable: 4512) // assignment operator could not be generated.||
     237
     238||c4511||copy constructor could not be generated.||Provide constructor (and assignment operator and destructor).  Or suppress.|| #  pragma warning(disable: 4511) // copy constructor could not be generated||
     239
     240||C4510||default constructor could not be generated.||If  have  reference or const members provide default constructor with initializer list. If intent is to make non-default-constructable, provide private declaration only. Suppress.||#  pragma warning(disable: 4510) // default constructor could not be generated||
     241
     242||C4535||calling _set_se_translator() requires /EHa ||Common from Boost.Test. In jamfile, add to project : requirements ||  <toolset>msvc:<asynch-exceptions>on # calling _set_se_translator() requires /EHa||
     243
     244||C4625||copy constructor could not be generated because a base class copy constructor is inaccessible||Trying to derive from a non-copyable class? Bug?||Fix.||
     245
     246||C4626||assignmentconstructor could not be generated because a base class copy constructor is inaccessible||Trying to derive from a non-copyable class? Bug?||Fix.||
     247
     248||C4671||the copy constructor is inaccessible||Suppress?||#pragma warning(disable: 4671) // the copy constructor is inaccessible||
     249
     250||C4673||A throw object cannot be handled in the catch block.||Fix ?||#pragma warning(disable: 4673) // Thrown object cannot be handled in catch block.||
     251
     252||C4701||local variable may be used without having been initialized||Best is to recode to avoid the message, probably just initialising it. But if you are '''very''' sure the message is misleading, and cost of dummy initialisation too high, suppress.||#  pragma warning(disable: 4701) // local variable may be used without having been initialized||
     253
     254||C4702||unreachable code||Best delete or comment-out.  Be very cautious about suppressing this, but use of macros may make this troublesome, so suppress with care, and always locally.||#pragma warning(disable: 4702) // unreachable code||
     255
     256||C4710||'function' : function not inlined||If variable is volatile, suppress.||#pragma warning(disable: 4510) // function not inlined.||
     257
     258||C4725||inline assembly instruction that may not produce accurate results on some Pentium microprocessors.|| Now obselete. Suppress.||#pragma warning(disable: 4510) // inaccurate results on some Pentium microprocessors? ||
     259
     260||C4800|| int' : forcing value to bool 'true' or 'false'||Use a bool valued expression. Write out expressions, for example: "value >= 0" or "ptr != 0" (Boost prefers clarity to curtness). Take care if using templates that constants are of the right type, for example you may need "value == static_cast<T>(1)". Or use static_cast<bool>(expression). Or suppress.||#  pragma warning(disable: 4800) // int' : forcing value to bool 'true' or 'false'
     261
     262||C4996||'putenv': The POSIX name for this item is deprecated (but NOT by POSIX!).||Suppress.||#  pragma warning(disable: 4996) // 'putenv' was declared deprecated.||
     263
     264||C4996||'  this item is deprecated.||Many similar messages suggest using secure versions. Unless you strongly believe that the 'secure' versions are useful, suppress. [http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1160.pdf WG14 Austin Group concerns] may guide. See also _CRT_SECURE_NO_DEPRECATE and other defines above.||#  pragma warning(disable: 4996) // '' was declared deprecated.||
     265
     266'''GCC'''
     267
     268With GCC, it is more difficult to deal with warnings because there is no way (yet) '''locally''' silence individual warnings.  It is considered important not to leave warnings switched off when meeting user code. This is an unresolved difficulty.
     269
     270On the other hand, the number of unhelpful warnings seems fewer.
     271
     272So more emphasis should be placed on fixing warnings, for example using static_cast, or providing missing items.
     273
     274For a particular file,
     275
     276#pragma GCC system_ // No warnings from all this file, considered a system header.
     277
     278or option --isystem
     279
     280The -isystem command line option adds its argument to the list of directories to search for headers, just like -I. Any headers found in that directory will be considered system headers.
     281
     282-Wsystem-headers
     283
     284is effective until the end of the file.
     285
     286Print warning messages for constructs found in system header files. Warnings from system headers are normally suppressed, on the assumption that they usually do not indicate real problems and would only make the compiler output harder to read. Using this command line option tells GCC to emit warnings from system headers as if they occurred in user code. However, note that using -Wall in conjunction with this option will not warn about unknown pragmas in system headers—for that, -Wunknown-pragmas must also be used.
     287
     288The GCC docs say: "Also, while it is syntactically valid to put these pragmas anywhere in your sources, the only supported location for them is before any data or functions are defined. Doing otherwise may result in unpredictable results depending on how the optimizer manages your sources."
     289
     290This might only mean you can't use them inside functions or class definitions, but it seems to imply that using them after a function definition leads to undefined behavior.  Thus, even if we knew what setting to turn the warning back to (perhaps the warning wasn't enabled in the first place!), we might not be able to turn them back on.
     291
     292<toolset>gcc:<cxxflags>-fdiagnostics-show-option # find out which options controls this warning (GCC >= 4.3)
     293
     294#if defined(__GNUC__) // GCC 4.3 and higher.
     295    #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     296#endif
     297
     298But that doesn't quite work, how do you know that the user wants -Wdeprecated-declarations to be set to "warning" after the include?
     299Could be the user has disabled that one on the command line, in which case if we turn it back on, that's as annoying for the end user as warnings from Boost! There was a time when some MSVC std lib headers behaved like that, and believe me it was *seriously* annoying :-(
     300
     301-Wall
     302    This enables all the warnings about constructions that some users consider questionable, and that are easy to avoid (or modify to prevent the warning), even in conjunction with macros. This also enables some language-specific warnings described in C++ Dialect Options and Objective-C and Objective-C++ Dialect Options.
     303
     304    -Wall turns on the following warning flags:
     305
     306              -Waddress   
     307              -Warray-bounds (only with -O2) 
     308              -Wc++0x-compat 
     309              -Wchar-subscripts 
     310              -Wimplicit-int 
     311              -Wimplicit-function-declaration 
     312              -Wcomment 
     313              -Wformat   
     314              -Wmain (only for C/ObjC and unless -ffreestanding) 
     315              -Wmissing-braces 
     316              -Wnonnull 
     317              -Wparentheses 
     318              -Wpointer-sign 
     319              -Wreorder   
     320              -Wreturn-type 
     321              -Wsequence-point 
     322              -Wsign-compare (only in C++) 
     323              -Wstrict-aliasing 
     324              -Wstrict-overflow=1 
     325              -Wswitch 
     326              -Wtrigraphs 
     327              -Wuninitialized 
     328              -Wunknown-pragmas 
     329              -Wunused-function 
     330              -Wunused-label     
     331              -Wunused-value     
     332              -Wunused-variable 
     333              -Wvolatile-register-var
     334
     335    Note that some warning flags are not implied by -Wall. Some of them warn about constructions that users generally do not consider questionable, but which occasionally you might wish to check for; others warn about constructions that are necessary or hard to avoid in some cases, and there is no simple way to modify the code to suppress the warning. Some of them are enabled by -Wextra but many of them must be enabled individually.
     336
     337-Wextra
     338    This enables some extra warning flags that are not enabled by -Wall. (This option used to be called -W. The older name is still supported, but the newer name is more descriptive.)
     339
     340              -Wclobbered 
     341              -Wempty-body 
     342              -Wignored-qualifiers
     343              -Wmissing-field-initializers 
     344              -Wmissing-parameter-type (C only) 
     345              -Wold-style-declaration (C only) 
     346              -Woverride-init 
     347              -Wsign-compare 
     348              -Wtype-limits 
     349              -Wuninitialized 
     350              -Wunused-parameter (only with -Wunused or -Wall) 
     351       
     352
     353    The option -Wextra also prints warning messages for the following cases:
     354
     355        * A pointer is compared against integer zero with `<', `<=', `>', or `>='.
     356        * (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
     357        * (C++ only) Ambiguous virtual bases.
     358        * (C++ only) Subscripting an array which has been declared `register'.
     359        * (C++ only) Taking the address of a variable which has been declared `register'.
     360        * (C++ only) A base class is not initialized in a derived class' copy constructor.
     361
     362
     363More information needed here!
     364
     365=== Individual Warnings ===
     366'''comparison between signed and unsigned integer expressions'''
     367
     368    '''-Wsign-compare''' - enable the warning (also turned on by -Wextra)[[BR]]
     369    '''-Wno-sign-compare''' - disable the warning[[BR]]
     370
     371    Almost always points to a real issue. The ranges of these are obviously
     372    different, for example signed char -128 - 127 and unsigned char 0 - 255 for
     373
     374                    range               bit pattern
     375    signed char     -128 to 127     01111111 to 10000000
     376    unsigned char    0 to 255       00000000 to 11111111
     377
     378    That means: signed char     unsigned char
     379      0 to 127      +               +
     380    128 to 255      -               +
     381
     382    In the range from 128 to 255 a comparison from one to the other makes no
     383    sense.  They can have the same bit pattern, yet test as not equal.  This
     384    is the source of many subtle and hard to find bugs.
     385
     386    The same problem can occur with all of the integral types. For example with
     387    16-bit short int unsigned ranges from -32768 to 32767, and the signed short
     388    ranges from 0 to 65535.
     389
     390    To fix, if you are sure that all the values for both things being compared
     391    fall into the overlap where their values are the same, you can static_cast
     392    one type to the other, if you must, but if you can change one of the types
     393    it's a better solution.  If you are sure that you can fit all values into
     394    the compared range, i.e. positive numbers from
     395    0 to (1<<(sizeof(IntegralType)*8-1))-1, it would make more sense to
     396    declare the signed one as an unsigned equivalent, (perhaps size_t).  In
     397    general, if you don't intend for a variable to ever have negative values,
     398    take advantage of the diagnostic capabilities of the compiler and don't
     399    declare it as an unsigned type.  After you've done this, if you see the
     400    warning again for one of these same variables, it is warning you of this
     401    same danger again.
     402
     403    This often shows up with loop counters.  We all learned to use int, but
     404    if it's truly counting only positive numbers, size_t is better.
     405
     406'''missing braces around initializer for ‘main()::X'''
     407
     408    '''-Wmissing-braces''' - enable the warning (also turned on by -Wall)[[BR]]
     409    '''-Wno-missing-braces''' - disable the warning
     410
     411    This warning is trying to let you know that what you think you're
     412    initializing may not actually be what you're initializing.
     413
     414
     415{{{
     416        struct X { int i; int j;};
     417        struct Y { struct X x; int j; };
     418
     419        Y y={1,2};
     420        return 0;
     421
     422}}}
     423
     424    The above example initializes both the elements of X in Y, but doesn't
     425    initialize j.  Change to:
     426
     427        {{{Y y={{1},2};}}}
     428
     429    to initialize half of X and all of Y, or better something like:
     430
     431        {{{Y y={{1,2},3};}}}
     432
     433    The same kind of problem can come up with:
     434
     435        {{{int a[2][2]={ 0, 1, 2 };}}}
     436
     437    versus:
     438
     439        {{{int a[2][2]={ {0,1},2};}}} or {{{int a[2][2]={ 0, {1,2}};}}}
     440
     441'''deprecated conversion from string constant to ‘char*’'''
     442    '''-Wwrite-strings''' - enable this warning (disabled by default for C and enabled by default for C++)
     443    '''-Wno-write-strings''' - disable this warning
     444
     445        For C will warn about trying to modify string constants, but only if defined const.
     446        For C++ often symptomatic of a real bug since string literals are not writeable in C++.
     447
     448        This one shows up when you have a string literal, like "Hello world!" which
     449        is arguably const data, and you assign it no a non-const char* either
     450        directly or via passing as an argument to a functions which expects a non-const char *.
     451        both:
     452            {{{
     453               char* cp="Hello world!";
     454            }}}
     455        and
     456            {{{
     457                void foo(char *cp);
     458                foo("Hello world")
     459            }}}
     460        will get this warning because you're using a string literal where a char*
     461        is expected.  If you say, so what?  See if you can predict what will print
     462        in the example below.
     463
     464        {{{
     465        #include <iostream>
     466
     467        void
     468        foo(char *cp)
     469        {
     470            cp[0]='W';
     471        }
     472
     473        int main()
     474        {
     475                char *str="Hello, world";
     476                foo(str);
     477                std::cout << str << std::endl;
     478        }
     479        }}}
     480
     481        If you said that Wello, world will print, think again.  Your most likely
     482        output is something like:
     483                '''Segmentation fault (core dumped)'''
     484        A string literal is put into a section that is read only and trying to
     485        write to it makes things blow up!
     486
     487        The right fix is to make anything that a string literal can be assigned
     488        to a const char*.
     489        Unfortunately, sometimes you can't fix the problem at the source, because
     490        it's someone else's code, and you can't change the declaration.  For
     491        example, if you had this function:
     492
     493        {{{
     494        int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
     495                                char *format, char **kwlist, ...);
     496        }}}
     497
     498        and you had a keyword list to pass it that looked like this:
     499
     500        {{{
     501        static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
     502                if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
     503                                          kwlist, &get, &set, &del, &doc))
     504        }}}
     505
     506        you would get the warning on the kwlist assignment, because you're
     507        assigning a const char * to char *, but when you correctly change
     508        it to:
     509
     510        {{{
     511        static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
     512        }}}
     513
     514        to get rid of the waring you'll get a warning on the call to
     515        PyArg_ParseTupleAndKeywords:
     516
     517            error: invalid conversion from ‘const char**’ to ‘char**’
     518
     519        because the library function was declared as taking a char **
     520        for the fourth argument.  Your only recourse is to cast away
     521        the constness with a const_cast:
     522
     523        {{{
     524        if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
     525                                          const_cast<char **>(kwlist), &get, &set, &del, &doc))
     526        }}}
     527
     528        Annoying, yet more correct than before.
     529
     530'''dereferencing type-punned pointer will break strict-aliasing rules'''
     531    this warning is only active when strict-aliasing optimization is active
     532
     533    '''-Wstrict-aliasing''' - equivalent to -Wstring-aliasing=3 (included in -Wall)[[BR]]
     534    '''-Wstrict-aliasing=N''' where N is in {1,2,3} - Higher N implies less false positives, at the expense of more work.  Currently there are 3 levels.[[BR]]
     535        Level 1: Most agressive, quick, very few false negatives, but many false positives.  Might use if higher levels don't warn, but turning on -fstrict-aliasing breaks the code.  Warns about pointer conversions even if pointer not dereferenced.[[BR]]
     536        Level 2: Agressive, quick, not too precise.  Less false positives than Level 1, but more false negatives.  Only warns if pointer is dereferenced.[[BR]]
     537        Level 3: Very few false positives and very few false negatives--the default.[[BR]]
     538    '''-fstrict-aliasing''' - also turned on by -O2, -O3 and -Os.  Tells the compiler that it's ok to do a certain class of optimization based on the type of expressions.  In particular you're promising by using this flag that an object of one type won't reside at the same address as an object of an incompatible type.
     539    '''-fno-strict-aliasing''' - turns off this optimization.  If this changes the behavior of your code, you have a problem in your code.
     540
     541    This is trying to let you know that you are asking the compiler to do undefined behavior and it may not do what you think it will do.  As the optimization level increases, the liklihood that you won't like what it does will increase.  I show a simple example later that surprisingly generates the wrong result when optimization at any level is turned on.  Ignore this warning at your own peril.  You are unlikely to care for the undefined behavior that results.
     542{{{
     543From the C++ Standard, section 3.10 Lvalues and rvalues
     544      15   If a program attempts to access the stored value of an object through an lvalue of other than
     545          one of the following types the behavior is undefined
     546        — the dynamic type of the object,
     547        — a cv-qualified version of the dynamic type of the object,
     548        — a type similar (as defined in 4.4) to the dynamic type of the object,
     549        — a type that is the signed or unsigned type corresponding to the dynamic type of the object,
     550        — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
     551        — an aggregate or union type that includes one of the aforementioned types among its member
     552          (including, recursively, a member of a subaggregate or contained union),
     553        — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
     554        — a char or unsigned char type.
     555}}}
     556The following program generates 6 warnings about breaking strict-aliasing rules, and many would dismiss them.  The correct output of the program is:
     557
     55800000020
     55900200000
     560
     561but when optimization is turned on it's:
     562
     56300000020
     56400000020
     565
     566THAT's what the warning is trying to tell you, that the optimizer is going to do things that you don't like.  In this case seeing that acopy is set to a and never touched again, strict aliasing lets it optimize by just returning the original value of a at the end.
     567{{{
     568uint32_t
     569swaphalves(uint32_t a)
     570{
     571    uint32_t acopy=a;
     572    uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal.
     573                                    // you should be warned by that.
     574    uint16_t tmp=ptr[0];
     575    ptr[0]=ptr[1];
     576    ptr[1]=tmp;
     577    return acopy;
     578}
     579
     580int main()
     581{
     582    uint32_t a;
     583    a=32;
     584    cout << hex << setfill('0') << setw(8) << a << endl;
     585    a=swaphalves(a);
     586    cout << setw(8) << a << endl;
     587}
     588}}}
     589Here's the (annotated) x86 assembler generated by gcc 4.4.1 for swaphalves, let's see what went wrong:
     590{{{
     591_Z10swaphalvesj:
     592    pushl   %ebp
     593    movl    %esp, %ebp
     594    subl    $16, %esp
     595    movl    8(%ebp), %eax   # get a in %eax
     596    movl    %eax, -8(%ebp)  # and store in in acopy
     597    leal    -8(%ebp), %eax  # now get eax pointing at acopy (ptr=&acopy)
     598    movl    %eax, -12(%ebp) # save that ptr at -12(%ebp)
     599    movl    -12(%ebp), %eax # get the ptr back in %eax
     600    movzwl  (%eax), %eax    # get 16 bits from ptr[0] in eax
     601    movw    %ax, -2(%ebp)   # store the 16 bits into tmp
     602    movl    -12(%ebp), %eax # get the ptr back in eax
     603    addl    $2, %eax        # bump up by two to get to ptr[1]
     604    movzwl  (%eax), %edx    # get that 16 bits into %edx
     605    movl    -12(%ebp), %eax # get ptr into eax
     606    movw    %dx, (%eax)     # store the 16 bits into ptr[1]
     607    movl    -12(%ebp), %eax # get the ptr again
     608    leal    2(%eax), %edx   # get the address of ptr[1] into edx
     609    movzwl  -2(%ebp), %eax  # get tmp into eax
     610    movw    %ax, (%edx)     # store into ptr[1]
     611    movl    -8(%ebp), %eax  # forget all that, return original a.
     612    leave
     613    ret
     614}}}
     615Scary, isn't it?  Of course you could use -fno-strict-aliasing to get the right output, but the generated code won't be as good.  A better way to accomplish the same thing without the warning's or the incorrect output is to define swaphalves like this:
     616
     617{{{
     618uint32_t
     619swaphalves(uint32_t a)
     620{
     621    union swapem{
     622        uint32_t a;
     623        uint16_t b[2];
     624    };
     625    swapem s={a};
     626    uint16_t tmp;
     627    tmp=s.b[0];
     628    s.b[0]=s.b[1];
     629    s.b[1]=tmp;
     630    return s.a;
     631}
     632}}}
     633The C++ compiler knows that members of a union alias, and this helps the compiler generate MUCH better code:
     634{{{
     635_Z10swaphalvesj:
     636    pushl   %ebp                        # save the original value of ebp
     637    movl    %esp, %ebp          # point ebp at the stack frame
     638    movl    8(%ebp), %eax       # get a in eax
     639    popl    %ebp                        # get the original ebp value back
     640    roll    $16, %eax           # swap the two halves of a and return it
     641    ret
     642}}}
     643
     644   
     645
     646
     647
     648
     649
     650 |? || class does not have a  virtual destructor||Suppress or provide a virtual destructor.||??||
     651
     652'''Intel'''
     653
     654Information needed here.
     655
     656'''Darwin /MacOS'''
     657
     658Information needed here.
     659
     660'''ACC'''
     661
     662Information needed here.
     663
     664'''Borland'''
     665
     666
     667Information needed here.