Boost logo

Boost :

Subject: Re: [boost] Compiler Warnings Tests
From: Stewart, Robert (Robert.Stewart_at_[hidden])
Date: 2009-11-28 15:24:06


Vicente Botet Escriba wrote:

[Vicente, please don't overquote]

> Robert Ramey wrote:
> > Paul A. Bristow wrote:
> >>
> >> The Microsoft docs examples might be a good start?
[snip]
> >> So are you proposing a collection of these, with versions
> >> that should compile and others that should not,...
> >>
> >> Or am I still misunderstanding you?
> >
> > You've got it.
> >
> > The only difference would be that the warning shouldn't be
> > associated with a particular compiler.
>
> We need to have a test that probes the warning is present for
> some compilers. The simple way is to build with
> warnigs_as_errors=on and check that the compilation fails.
>
> We need of course check that the workaround or a better
> coding style solves the issue. This needs to be done also
> with warnigs_as_errors=on and check that the compilation
> succeeds.
>
> And last, in some cases, we need to check that with
> warnigs_as_errors=off both are equivalent. This needs to be
> done with warnigs_as_errors=off and check the test run
> succeed.

That seems quite reasonable.

> int main() {
> int b = 30000, c = 30000;
> #if defined(BOOST_WARNING_AS_ERROR_MUST_FAIL)
> short a = b + c; // C4244
> #elif undefined(BOOST_WARNING_AS_ERROR_MUST_SUCCEED)
> short a = static_cast<unsigned short>(b + c);
> #else
> short a1 = b + c; // C4244
> short a2 = static_cast<unsigned short>(b + c);
> assert(a1==a2)
> #endif
> }

I see what you're trying to do, but I dislike the duplication, particularly as some tests may require a good deal of setup. That example could be recast as:

int
main()
{
   int b(30000);
   int c(30000);
#if defined (BOOST_WARNING_AS_ERROR_MUST_FAIL) \
   || !defined (BOOST_WARNING_AS_ERROR_MUST_PASS)

   short a1(b + c); // MSVC: C4244

#endif
#if defined (BOOST_WARNING_AS_ERROR_MUST_PASS) \
   || !defined (BOOST_WARNING_AS_ERROR_MUST_FAIL)

   short a2(static_cast<unsigned short>(b + c));

#endif
#if !defined (BOOST_WARNING_AS_ERROR_MUST_PASS) \
   && !defined (BOOST_WARNING_AS_ERROR_MUST_FAIL)

   assert(a1 == a2);

#endif
}

Obviously, the macros add a lot of line noise, so we could construct simpler manifest constants that represent the three conditions: BOOST_WARNING_TEST_FAIL_OR_IGNORE, BOOST_WARNING_TEST_PASS_OR_IGNORE, and BOOST_WARNING_TEST_IGNORE might do.

> The question no is how to use this test on compiler that
> don't warm in this case.
>
> An here is where we can not be independent of the compiler. We need to
> determine on the code if the compiler must warms or not:

[snip code trying to trigger a warning when the compiler doesn't]

It might be possible to wrap the code that is supposed to warn with a macro that dictates the expected behavior:

   BOOST_MUST_WARN(short a1(b + c));

Assuming that is possible, then BOOST_MUST_WARN will rely on the supplied statement to warn when a compiler is expected to warn in that situation, and will force a warning or some other failure, when it isn't. There would then be preprocessor conditional logic to determine whether BOOST_MUST_WARN needs to force a warning/compilation error or not, based upon the compiler being used, as well as to pass through the code for the equivalence test. That logic will be largely boilerplate and will appear outside the test code, making the test code more readable.

Given that mechanism, the example becomes the following:

int
main()
{
   int b(30000);
   int c(30000);
   BOOST_MUST_WARN(short a1(b + c)); // MSVC: C4244
   short a2(static_cast<unsigned short>(b + c));
#ifdef BOOST_WARNING_TEST_IGNORE
   assert(a1 == a2);
#endif
}

Since initializing a1 is expected to warn on MSVC, the macro will just emit the supplied code when testing for failure with warnings-as-errors. The macro must also emit the code for the warnings-as-warnings equivalence test. For a no-warnings test, the macro must emit nothing.

For a compiler that doesn't emit a warning for that statement, BOOST_MUST_WARN must be defined to produce a warning (or to otherwise fail the compilation) in a warnings-as-errors test. Otherwise, it must simply emit the code unchanged.

The initialization of a2 is expected to produce no warnings in any case, so it needn't be special cased.

The assertion -- or other equivalence test code in other cases -- might only be desirable in the equivalence test, hence the conditional compilation.

The foregoing assumes, of course, that the warning-generating code can be reduced to a statement and that all desired statements can be captured as shown.

HTH,

_____
Rob Stewart robert.stewart_at_[hidden]
Software Engineer, Core Software using std::disclaimer;
Susquehanna International Group, LLP http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk