Search code examples
c++visual-studiolanguage-lawyercompiler-warningssuppress-warnings

Why is (void)sizeof(param) not "using" param?


I have a macro defined as follows:

#define UNREF_PARAM_1(a)
    do { \
        (void)sizeof(a); \
    } \
    while (0)

To get rid of compiler warnings. In a new project I am working on, VS2013 is suddenly complaining again about a unreferenced formal parameter.

Strangely it does work if I just use (void)param. Does anybody have a clue why it does not work when using it with (void)sizeof(param)?


Solution

  • Because in sizeof(param), param is a so-called unevaluated operand and therefore not odr-used - that is, not needed at runtime.

    However, (void)param does constitute a odr-use.

    A cast with the notation in your code internally invokes a static_cast. [expr.static.cast]/6:

    Any expression can be explicitly converted to type cv void, in which case it becomes a discarded-value expression (Clause 5).

    [expr]/10:

    In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression. The expression is evaluated and its value is discarded. […] The lvalue-to-rvalue conversion (4.1) is applied only if the expression is an lvalue of volatile-qualified type […]

    [basic.def.odr]/2:

    An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied.

    The first part of this quote specifies that sizeof(a) isn't an odr-use of a since a is an unevaluated operand1.
    Clearly (void)a is potentially evaluated. And because a is certainly neither allowed to appear in a constant expression nor declared volatile, no lvalue-to-rvalue conversion is "immediately applied" and thus a is odr-used.


    1) Here is a list of expressions where x is an unevaluated operand as from C++11:

    • typeid(x), where x is not a glvalue of polymorphic class type
    • sizeof(x) (and sizeof x)
    • noexcept(x)
    • decltype(x)
    • alignof(x)? alignas(x)?