Changes between Version 40 and Version 41 of Guidelines/MaintenanceGuidelines


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

Warnings section Moved to new section on compiler warnings

Legend:

Unmodified
Added
Removed
Modified
  • Guidelines/MaintenanceGuidelines

    v40 v41  
    539539
    540540-----------------------------------------------------------------------------------------------
    541 == Managing Warnings from Compilers (and other tools) == #warnings
    542 
    543 === Avoid warnings, Eliminate warning, Suppress Warnings, or Document. ===
    544 
    545 Boost aims to avoid warnings messages as far as is reasonably practicable,
    546 even when compiled with the highest and most pedantic warning level,
    547 avoiding vendor specific extensions if possible.
    548 
    549 Warnings often indicate real problems.  Sometimes they only manifest
    550 on a particular platform, revealing a portability issue.  Sometimes
    551 they indicate that the code doesn't account for a runtime condition,
    552 like overflow, which the warning can only suggest as a possibility.
    553 
    554 Suppressing a warning without altering code may simply mask a problem.
    555 The right approach is to determine why the warning occurs is to decide
    556 whether it is correct in the context, and if so, apply appropriate remediation.
    557 If the warning is not correct in the context, only then should it be suppressed.
    558 
    559 Because developers don't have the same knowledge, even among Boost
    560 developers, Boost is amassing information to help them know when a
    561 warning is significant and not.  That information can show cases in
    562 which a warning is legitimate and when it isn't.  For the former,
    563 there is help to understand how to change the code portably to
    564 account for the problem revealed by the warning.  For the latter,
    565 there is information on how to suppress the warning in a portable way.
    566 
    567 Changing code can lead to bugs.  Thus, changing code to eliminate a warning might create a bug.  That's unfortunate.
    568 From a maintenance standpoint, however, most would prefer to see altered code to a
    569 glob of preprocessor and pragma line noise that suppresses a warning in the unchanged code.
    570 
    571 Testing will reveal the bug.  If it doesn't, the testing is insufficient.
    572 If the bug appears on an untested platform, then more testers are needed to be able to detect such bugs in the future.
    573 
    574 Breifly, for some users, any warning '''is''' a bug.
    575 
    576 See also [https://svn.boost.org/trac/boost/wiki/WarningFixes] for progress made on warning fixes/suppression.[[BR]]
    577 
    578 '''Reasons to eliminate or suppress warnings:'''
    579 
    580 1  To allow users, whose environment requires no warnings, to use Boost code.
    581 
    582 2  To avoid the nuisance, perhaps overwhelming, of spurious warning messages.
    583 
    584 3  To improve code quality by focusing library writers' attention on potential problems.
    585 
    586 4  To improve portability by focusing developer attention on potentially non-portable code.
    587 
    588 5  To improve compliance with the C++ Standard.
    589 
    590 6  To permit users to set high warning levels when using Boost libraries without being overwhelmed with a barrage of library warnings.
    591 
    592 7  To document that warnings have been considered by the library author or maintainer
    593 and are considered not significant.
    594 
    595 8  For Boost, making the suppression local is more important than only suppressing a specific warning.
    596 
    597 '''What to do'''
    598 
    599 1  Test compilation with the most pedantic setting for the compiler, and non-debug mode.
    600 
    601 '''For Microsoft Visual Studio''', this means setting level to 4 (command line /W4).[[BR]]
    602 For code that doesn't deliberately use Microsoft language extensions, disable them with Disable MS extensions = Yes, command line option /Za[[BR]]
    603 
    604 To a jamfile add  <toolset>msvc:<cxxflags>/Za # disable MS extensions.[[BR]]
    605 
    606 If 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.
    607 
    608 If 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:
    609 
    610 {{{
    611 # pow test requires type_of that MS extensions.
    612 run pow_test.cpp ../../test/build//boost_test_exec_monitor
    613         : # command line
    614         : # input files
    615         : # requirements
    616           -<toolset>msvc:<cxxflags>/Za # Requires type_of which requires MS extensions, so cancel /Za.
    617         : test_pow
    618 ;
    619 
    620 Note the leading - switches off the compiler switch /Za, producing output thus:
    621 
    622 compile-c-c++ ..\..\..\bin.v2\libs\math\test\test_pow.test\msvc-9.0\debug\asynch-exceptions-on\threading-multi\pow_test.obj
    623 pow_test.cpp
    624 using native typeof
    625 
    626 }}}
    627 
    628 
    629 (You might also consider using Microsoft /Wall if available.  You may find
    630 [http://www.geoffchappell.com/viewer.htm?doc=studies/msvc/cl/c1xx/warnings/index.htm&tx=2,27&ts=0,3820]
    631 a helpful guide to the byzantine complexity of warnings).[[BR]]
    632 
    633 (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.
    634 
    635 {{{
    636 function AddCommonConfig(oProj, strProjectName,bAddUnicode,bForEmptyProject) in the sections for debug and/or release
    637 
    638 CLTool.DisableLanguageExtensions = true; // add to make the default NO MS extensions.
    639 
    640 LinkTool.LinkIncremental = linkIncrementalNo; // add
    641 
    642 CLTool.WarningLevel = WarningLevel_4; // change from 3 to 4 to making the default warning level 4
    643 
    644 }}}
    645 
    646 '''For GCC''' this means -Wall -pendantic 
    647 
    648 but you might consider adding specific warnings that are to be suppressed, for example:
    649 
    650 -pedantic -Wall -Wno-long-long -Wno-unused-value
    651 
    652 but 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.
    653 
    654 Using bjam add warnings=all to the invocation command line.
    655 
    656 Putting options in jam files allows setting to be made for one or more specified compiler(s).
    657 
    658 Some sample options in jamfile.v2 are:
    659 
    660 {{{
    661 project 
    662     : requirements
    663       <toolset>gcc:<cxxflags>-Wno-missing-braces
    664       <toolset>darwin:<cxxflags>-Wno-missing-braces
    665       <toolset>acc:<cxxflags>+W2068,2461,2236,4070,4069 # Comments on warning message help readers who do not have ACC documentation to hand.
    666       <toolset>intel:<cxxflags>-nologo
    667       <toolset>msvc:<warnings>all # == /W4
    668       -<toolset>msvc:<define>_DEBUG # Undefine DEBUG.
    669       <toolset>msvc:<define>NDEBUG # Define NO debug, or release.
    670       <toolset>msvc:<asynch-exceptions>on # Needed for Boost.Test
    671       <toolset>msvc:<cxxflags>/Za # Disable MS extensions.
    672       #-<toolset>msvc:<cxxflags>/Za # (Re-)Enable MS extensions if these are definitely required for specific module.
    673       #  The define of macros below prevent warnings about the checked versions of SCL and CRT libraries.
    674       #  Most Boost code does not need these versions (as they are markedly slower).
    675       <toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS
    676       <toolset>msvc:<define>_SCL_SECURE_NO_DEPRECATE
    677       <toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS
    678       <toolset>msvc:<define>_CRT_SECURE_NO_DEPRECATE
    679       <toolset>msvc:<define>_CRT_NONSTDC_NO_DEPRECATE # Suppresses other warnings about using standard POSIX and C9X.
    680       #  Alternatively, you can just suppress the warnings (perhaps not the best way).
    681       <toolset>msvc:<cxxflags>/wd4996 # 'putenv': The POSIX name for this item is deprecated.
    682       <toolset>msvc:<cxxflags>/wd4512 # assignment operator could not be generated.
    683       <toolset>msvc:<cxxflags>/wd4224 # nonstandard extension used : formal parameter 'arg' was previously defined as a type.
    684       <toolset>msvc:<cxxflags>/wd4127 # expression is constant.
    685       <toolset>msvc:<cxxflags>/wd4701 # unreachable code - needed for lexical cast - temporary for Boost 1.40 & earlier.
    686    ...
    687     ;
    688 }}}
    689 
    690 Using warning-as-errors will make it hard to miss warnings.
    691   Microsoft command line option /WX,
    692   gcc option -warning-as-errors
    693   gcc option -pedantic-errors
    694 
    695 2  Consider each warning and
    696 
    697 a  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.
    698 
    699 b  Use the compiler specific mechanism to suppress the warning message, but try hard to ensure that this is as local
    700 to the package as possible so that users can still get warnings from *their code*.
    701 
    702 For MSVC, this involves pushing to save the current warning state, disabling the warning, and later popping to restore (abbreviated as ''push'n'pop'').
    703 {{{
    704 #if defined(_MSC_VER)
    705 #pragma warning(push) // Save warning settings.
    706 #pragma warning(disable : 4996) // Disable deprecated localtime/gmtime warning.
    707 #endif
    708 
    709 ...
    710 
    711 #if defined(_MSC_VER)
    712 #pragma warning(pop) // Restore warnings to previous state.
    713 #endif
    714 
    715 }}}
    716 
    717 Adding some or all of the warning message as a comment is helpful to tell ''readers'' what warning is being ignored, for example:
    718 
    719 {{{
    720 #  pragma warning(disable: 4510) // default constructor could not be generated
    721 }}}
    722 
    723 If the warning is only for a specific compiler version, use this approach:
    724 
    725 {{{
    726 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
    727 #pragma warning(push)
    728 #pragma warning(disable:4512) //assignment operator could not be generated
    729 #endif
    730 
    731 ...
    732 
    733 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
    734 #pragma warning(pop)
    735 #endif
    736 }}}
    737 
    738 c  Repeat this process with other compilers and use their specific suppression methods.
    739 
    740 d  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.
    741 
    742 
    743 === Specific Warnings and Suggested Actions. ===
    744 
    745 ''These are just few for starters, and need more, especially for gcc. Suggestions may be wrong! ''
    746 
    747 The pragma or other code required to suppress warnings is in the right hand box, ready for copy and paste.
    748 
    749 '''Microsoft'''
    750 
    751 If you chose to suppress (rather than fix by recoding),
    752 localise the warnings as far as possible by using push'n'pop pragmas (see above).
    753 ||Warning||Warning Description||Suggestions||Suppression||
    754 
    755 
    756 ||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||
    757 
    758 ||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.||
    759 
    760 ||C4146|| unary minus operator applied to unsigned type, result still unsigned||This indicates a real error. ||Fix. ||
    761 
    762 ||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||
    763 
    764 ||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||
    765 
    766 ||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.||
    767 
    768 ||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.||
    769 
    770 ||C4324||structure was padded due to __declspec(align())||Suppress||#pragma warning(disable:4324) // structure was padded due to __declspec(align())||
    771 
    772 ||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||
    773 
    774 ||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||
    775 
    776 ||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.||
    777 
    778 ||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||
    779 
    780 ||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||
    781 
    782 ||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||
    783 
    784 ||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.||
    785 
    786 ||C4626||assignmentconstructor could not be generated because a base class copy constructor is inaccessible||Trying to derive from a non-copyable class? Bug?||Fix.||
    787 
    788 ||C4671||the copy constructor is inaccessible||Suppress?||#pragma warning(disable: 4671) // the copy constructor is inaccessible||
    789 
    790 ||C4673||A throw object cannot be handled in the catch block.||Fix ?||#pragma warning(disable: 4673) // Thrown object cannot be handled in catch block.||
    791 
    792 ||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||
    793 
    794 ||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||
    795 
    796 ||C4710||'function' : function not inlined||If variable is volatile, suppress.||#pragma warning(disable: 4510) // function not inlined.||
    797 
    798 ||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? ||
    799 
    800 ||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'
    801 
    802 ||C4996||'putenv': The POSIX name for this item is deprecated (but NOT by POSIX!).||Suppress.||#  pragma warning(disable: 4996) // 'putenv' was declared deprecated.||
    803 
    804 ||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.||
    805 
    806 '''GCC'''
    807 
    808 With 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.
    809 
    810 On the other hand, the number of unhelpful warnings seems fewer.
    811 
    812 So more emphasis should be placed on fixing warnings, for example using static_cast, or providing missing items.
    813 
    814 For a particular file,
    815 
    816 #pragma GCC system_ // No warnings from all this file, considered a system header.
    817 
    818 or option --isystem
    819 
    820 The -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.
    821 
    822 -Wsystem-headers
    823 
    824 is effective until the end of the file.
    825 
    826 Print 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.
    827 
    828 The 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."
    829 
    830 This 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.
    831 
    832 <toolset>gcc:<cxxflags>-fdiagnostics-show-option # find out which options controls this warning (GCC >= 4.3)
    833 
    834 #if defined(__GNUC__) // GCC 4.3 and higher.
    835     #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    836 #endif
    837 
    838 But that doesn't quite work, how do you know that the user wants -Wdeprecated-declarations to be set to "warning" after the include?
    839 Could 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 :-(
    840 
    841 -Wall
    842     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.
    843 
    844     -Wall turns on the following warning flags:
    845 
    846               -Waddress   
    847               -Warray-bounds (only with -O2) 
    848               -Wc++0x-compat 
    849               -Wchar-subscripts 
    850               -Wimplicit-int 
    851               -Wimplicit-function-declaration 
    852               -Wcomment 
    853               -Wformat   
    854               -Wmain (only for C/ObjC and unless -ffreestanding) 
    855               -Wmissing-braces 
    856               -Wnonnull 
    857               -Wparentheses 
    858               -Wpointer-sign 
    859               -Wreorder   
    860               -Wreturn-type 
    861               -Wsequence-point 
    862               -Wsign-compare (only in C++) 
    863               -Wstrict-aliasing 
    864               -Wstrict-overflow=1 
    865               -Wswitch 
    866               -Wtrigraphs 
    867               -Wuninitialized 
    868               -Wunknown-pragmas 
    869               -Wunused-function 
    870               -Wunused-label     
    871               -Wunused-value     
    872               -Wunused-variable 
    873               -Wvolatile-register-var
    874 
    875     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.
    876 
    877 -Wextra
    878     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.)
    879 
    880               -Wclobbered 
    881               -Wempty-body 
    882               -Wignored-qualifiers
    883               -Wmissing-field-initializers 
    884               -Wmissing-parameter-type (C only) 
    885               -Wold-style-declaration (C only) 
    886               -Woverride-init 
    887               -Wsign-compare 
    888               -Wtype-limits 
    889               -Wuninitialized 
    890               -Wunused-parameter (only with -Wunused or -Wall) 
    891        
    892 
    893     The option -Wextra also prints warning messages for the following cases:
    894 
    895         * A pointer is compared against integer zero with `<', `<=', `>', or `>='.
    896         * (C++ only) An enumerator and a non-enumerator both appear in a conditional expression.
    897         * (C++ only) Ambiguous virtual bases.
    898         * (C++ only) Subscripting an array which has been declared `register'.
    899         * (C++ only) Taking the address of a variable which has been declared `register'.
    900         * (C++ only) A base class is not initialized in a derived class' copy constructor.
    901 
    902 
    903 More information needed here!
    904 
    905 === Individual Warnings ===
    906 '''comparison between signed and unsigned integer expressions'''
    907 
    908     '''-Wsign-compare''' - enable the warning (also turned on by -Wextra)[[BR]]
    909     '''-Wno-sign-compare''' - disable the warning[[BR]]
    910 
    911     Almost always points to a real issue. The ranges of these are obviously
    912     different, for example signed char -128 - 127 and unsigned char 0 - 255 for
    913 
    914                     range               bit pattern
    915     signed char     -128 to 127     01111111 to 10000000
    916     unsigned char    0 to 255       00000000 to 11111111
    917 
    918     That means: signed char     unsigned char
    919       0 to 127      +               +
    920     128 to 255      -               +
    921 
    922     In the range from 128 to 255 a comparison from one to the other makes no
    923     sense.  They can have the same bit pattern, yet test as not equal.  This
    924     is the source of many subtle and hard to find bugs.
    925 
    926     The same problem can occur with all of the integral types. For example with
    927     16-bit short int unsigned ranges from -32768 to 32767, and the signed short
    928     ranges from 0 to 65535.
    929 
    930     To fix, if you are sure that all the values for both things being compared
    931     fall into the overlap where their values are the same, you can static_cast
    932     one type to the other, if you must, but if you can change one of the types
    933     it's a better solution.  If you are sure that you can fit all values into
    934     the compared range, i.e. positive numbers from
    935     0 to (1<<(sizeof(IntegralType)*8-1))-1, it would make more sense to
    936     declare the signed one as an unsigned equivalent, (perhaps size_t).  In
    937     general, if you don't intend for a variable to ever have negative values,
    938     take advantage of the diagnostic capabilities of the compiler and don't
    939     declare it as an unsigned type.  After you've done this, if you see the
    940     warning again for one of these same variables, it is warning you of this
    941     same danger again.
    942 
    943     This often shows up with loop counters.  We all learned to use int, but
    944     if it's truly counting only positive numbers, size_t is better.
    945 
    946 '''missing braces around initializer for ‘main()::X'''
    947 
    948     '''-Wmissing-braces''' - enable the warning (also turned on by -Wall)[[BR]]
    949     '''-Wno-missing-braces''' - disable the warning
    950 
    951     This warning is trying to let you know that what you think you're
    952     initializing may not actually be what you're initializing.
    953 
    954 
    955 {{{
    956         struct X { int i; int j;};
    957         struct Y { struct X x; int j; };
    958 
    959         Y y={1,2};
    960         return 0;
    961 
    962 }}}
    963 
    964     The above example initializes both the elements of X in Y, but doesn't
    965     initialize j.  Change to:
    966 
    967         {{{Y y={{1},2};}}}
    968 
    969     to initialize half of X and all of Y, or better something like:
    970 
    971         {{{Y y={{1,2},3};}}}
    972 
    973     The same kind of problem can come up with:
    974 
    975         {{{int a[2][2]={ 0, 1, 2 };}}}
    976 
    977     versus:
    978 
    979         {{{int a[2][2]={ {0,1},2};}}} or {{{int a[2][2]={ 0, {1,2}};}}}
    980 
    981 '''deprecated conversion from string constant to ‘char*’'''
    982     '''-Wwrite-strings''' - enable this warning (disabled by default for C and enabled by default for C++)
    983     '''-Wno-write-strings''' - disable this warning
    984 
    985         For C will warn about trying to modify string constants, but only if defined const.
    986         For C++ often symptomatic of a real bug since string literals are not writeable in C++.
    987 
    988         This one shows up when you have a string literal, like "Hello world!" which
    989         is arguably const data, and you assign it no a non-const char* either
    990         directly or via passing as an argument to a functions which expects a non-const char *.
    991         both:
    992             {{{
    993                char* cp="Hello world!";
    994             }}}
    995         and
    996             {{{
    997                 void foo(char *cp);
    998                 foo("Hello world")
    999             }}}
    1000         will get this warning because you're using a string literal where a char*
    1001         is expected.  If you say, so what?  See if you can predict what will print
    1002         in the example below.
    1003 
    1004         {{{
    1005         #include <iostream>
    1006 
    1007         void
    1008         foo(char *cp)
    1009         {
    1010             cp[0]='W';
    1011         }
    1012 
    1013         int main()
    1014         {
    1015                 char *str="Hello, world";
    1016                 foo(str);
    1017                 std::cout << str << std::endl;
    1018         }
    1019         }}}
    1020 
    1021         If you said that Wello, world will print, think again.  Your most likely
    1022         output is something like:
    1023                 '''Segmentation fault (core dumped)'''
    1024         A string literal is put into a section that is read only and trying to
    1025         write to it makes things blow up!
    1026 
    1027         The right fix is to make anything that a string literal can be assigned
    1028         to a const char*.
    1029         Unfortunately, sometimes you can't fix the problem at the source, because
    1030         it's someone else's code, and you can't change the declaration.  For
    1031         example, if you had this function:
    1032 
    1033         {{{
    1034         int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
    1035                                 char *format, char **kwlist, ...);
    1036         }}}
    1037 
    1038         and you had a keyword list to pass it that looked like this:
    1039 
    1040         {{{
    1041         static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
    1042                 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
    1043                                           kwlist, &get, &set, &del, &doc))
    1044         }}}
    1045 
    1046         you would get the warning on the kwlist assignment, because you're
    1047         assigning a const char * to char *, but when you correctly change
    1048         it to:
    1049 
    1050         {{{
    1051         static const char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
    1052         }}}
    1053 
    1054         to get rid of the waring you'll get a warning on the call to
    1055         PyArg_ParseTupleAndKeywords:
    1056 
    1057             error: invalid conversion from ‘const char**’ to ‘char**’
    1058 
    1059         because the library function was declared as taking a char **
    1060         for the fourth argument.  Your only recourse is to cast away
    1061         the constness with a const_cast:
    1062 
    1063         {{{
    1064         if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
    1065                                           const_cast<char **>(kwlist), &get, &set, &del, &doc))
    1066         }}}
    1067 
    1068         Annoying, yet more correct than before.
    1069 
    1070 '''dereferencing type-punned pointer will break strict-aliasing rules'''
    1071     this warning is only active when strict-aliasing optimization is active
    1072 
    1073     '''-Wstrict-aliasing''' - equivalent to -Wstring-aliasing=3 (included in -Wall)[[BR]]
    1074     '''-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]]
    1075         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]]
    1076         Level 2: Agressive, quick, not too precise.  Less false positives than Level 1, but more false negatives.  Only warns if pointer is dereferenced.[[BR]]
    1077         Level 3: Very few false positives and very few false negatives--the default.[[BR]]
    1078     '''-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.
    1079     '''-fno-strict-aliasing''' - turns off this optimization.  If this changes the behavior of your code, you have a problem in your code.
    1080 
    1081     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.
    1082 {{{
    1083 From the C++ Standard, section 3.10 Lvalues and rvalues
    1084       15   If a program attempts to access the stored value of an object through an lvalue of other than
    1085           one of the following types the behavior is undefined
    1086         — the dynamic type of the object,
    1087         — a cv-qualified version of the dynamic type of the object,
    1088         — a type similar (as defined in 4.4) to the dynamic type of the object,
    1089         — a type that is the signed or unsigned type corresponding to the dynamic type of the object,
    1090         — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
    1091         — an aggregate or union type that includes one of the aforementioned types among its member
    1092           (including, recursively, a member of a subaggregate or contained union),
    1093         — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
    1094         — a char or unsigned char type.
    1095 }}}
    1096 The following program generates 6 warnings about breaking strict-aliasing rules, and many would dismiss them.  The correct output of the program is:
    1097 
    1098 00000020
    1099 00200000
    1100 
    1101 but when optimization is turned on it's:
    1102 
    1103 00000020
    1104 00000020
    1105 
    1106 THAT'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.
    1107 {{{
    1108 uint32_t
    1109 swaphalves(uint32_t a)
    1110 {
    1111     uint32_t acopy=a;
    1112     uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal.
    1113                                     // you should be warned by that.
    1114     uint16_t tmp=ptr[0];
    1115     ptr[0]=ptr[1];
    1116     ptr[1]=tmp;
    1117     return acopy;
    1118 }
    1119 
    1120 int main()
    1121 {
    1122     uint32_t a;
    1123     a=32;
    1124     cout << hex << setfill('0') << setw(8) << a << endl;
    1125     a=swaphalves(a);
    1126     cout << setw(8) << a << endl;
    1127 }
    1128 }}}
    1129 Here's the (annotated) x86 assembler generated by gcc 4.4.1 for swaphalves, let's see what went wrong:
    1130 {{{
    1131 _Z10swaphalvesj:
    1132     pushl   %ebp
    1133     movl    %esp, %ebp
    1134     subl    $16, %esp
    1135     movl    8(%ebp), %eax   # get a in %eax
    1136     movl    %eax, -8(%ebp)  # and store in in acopy
    1137     leal    -8(%ebp), %eax  # now get eax pointing at acopy (ptr=&acopy)
    1138     movl    %eax, -12(%ebp) # save that ptr at -12(%ebp)
    1139     movl    -12(%ebp), %eax # get the ptr back in %eax
    1140     movzwl  (%eax), %eax    # get 16 bits from ptr[0] in eax
    1141     movw    %ax, -2(%ebp)   # store the 16 bits into tmp
    1142     movl    -12(%ebp), %eax # get the ptr back in eax
    1143     addl    $2, %eax        # bump up by two to get to ptr[1]
    1144     movzwl  (%eax), %edx    # get that 16 bits into %edx
    1145     movl    -12(%ebp), %eax # get ptr into eax
    1146     movw    %dx, (%eax)     # store the 16 bits into ptr[1]
    1147     movl    -12(%ebp), %eax # get the ptr again
    1148     leal    2(%eax), %edx   # get the address of ptr[1] into edx
    1149     movzwl  -2(%ebp), %eax  # get tmp into eax
    1150     movw    %ax, (%edx)     # store into ptr[1]
    1151     movl    -8(%ebp), %eax  # forget all that, return original a.
    1152     leave
    1153     ret
    1154 }}}
    1155 Scary, 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:
    1156 
    1157 {{{
    1158 uint32_t
    1159 swaphalves(uint32_t a)
    1160 {
    1161     union swapem{
    1162         uint32_t a;
    1163         uint16_t b[2];
    1164     };
    1165     swapem s={a};
    1166     uint16_t tmp;
    1167     tmp=s.b[0];
    1168     s.b[0]=s.b[1];
    1169     s.b[1]=tmp;
    1170     return s.a;
    1171 }
    1172 }}}
    1173 The C++ compiler knows that members of a union alias, and this helps the compiler generate MUCH better code:
    1174 {{{
    1175 _Z10swaphalvesj:
    1176     pushl   %ebp                        # save the original value of ebp
    1177     movl    %esp, %ebp          # point ebp at the stack frame
    1178     movl    8(%ebp), %eax       # get a in eax
    1179     popl    %ebp                        # get the original ebp value back
    1180     roll    $16, %eax           # swap the two halves of a and return it
    1181     ret
    1182 }}}
    1183 
    1184    
    1185 
    1186 
    1187 
    1188 
    1189 
    1190  |? || class does not have a  virtual destructor||Suppress or provide a virtual destructor.||??||
    1191 
    1192 '''Intel'''
    1193 
    1194 Information needed here.
    1195 
    1196 '''Darwin /MacOS'''
    1197 
    1198 Information needed here.
    1199 
    1200 '''ACC'''
    1201 
    1202 Information needed here.
    1203 
    1204 '''Borland'''
    1205 
    1206 
    1207 Information needed here.
    1208 
    1209 
    1210 
    1211 
     541
     542Guidelines on compiler warnings have been moved to a new section.