1

The following code generates a warning that temp is not used (which is true):

#include <cstdio>

int f() { return 5; }

int main() {
    if(const int& temp = f()) {
        printf("hello!\n");
    }

    return 0;
}

The thing is that I NEED to do this without generating a warning with gcc -Wall and clang -Weverything (I'm implementing a feature similar to the SECTION() stuff of Catch) .

So any ways to silence it? I tried using __attribute__((unused)).

Using -Wno-unused-variable globally is not an option for me since I'm writing a header only library.

Mat
  • 202,337
  • 40
  • 393
  • 406
onqtam
  • 4,356
  • 2
  • 28
  • 50

3 Answers3

3
#include <cstdio>

int f() { return 5; }

int main()
{
  if (const int &temp __attribute__((unused)) = f()) {
    printf("hello!\n");
  }

  return 0;
}

This silences the warning for GCC and clang.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • I had used ```__attribute__((unused))``` in the wrong place - before the ```const``` – onqtam Feb 23 '16 at 07:49
  • 1
    The [attribute syntax](https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax) is not exactly trivial, to say the least, but in my limited experience, as long as you stick to a single declaration, putting it right after the name you defined seems to work (after the parameter list for functions). – Mat Feb 23 '16 at 09:48
2

If temp is unused, in essence it is also probably not needed. Remove it.

#include <cstdio>

int f() { return 5; }

int main() {
    if(f()) {
        printf("hello!\n");
    }

    return 0;
}

I realise this is an MCVE, so why would it need to be there in the first place?

As you mention in the comments, the destructor of temp is important in the target code. Adding an additional set of braces will add both control of the lifetime of the temporary and ensure its use (hence remove the warning);

#include <iostream>

using namespace std;

struct A {
    ~A() { cout << "~A()" << endl; }
    explicit operator bool() const { return true; }
};

A f() { return A{}; }

int main() {
    { // braced to limit scope...
        auto&& a = f(); // can be const A&
        if ( a ) {
            cout << "hello!" << endl;
        }
    } // braced to limit scope....
    return 0;
}

Demo code.

Given the additional constraints of the lifetime of temp been extended to the end of an associated else, simply forcing the warning to be silenced will work (compiler limited).

if (const int &temp __attribute__((unused)) = f())

C++11 brings with it the [[...]] style of attributes, but the unused is not standard, but clang does support this syntax [[gnu::unused]]

Niall
  • 30,036
  • 10
  • 99
  • 142
  • Well it actually isn't an int but a type with a ctor/dtor and I need the destructor to execute at the end of the if block... maybe I should have given a full example – onqtam Feb 23 '16 at 07:18
  • @onqtam Its destructor will be executed, even if no named variable here. – songyuanyao Feb 23 '16 at 07:21
  • 1
    @songyuanyao the lifetime of the temp is different in ```if(myType())``` and ```if(const myType& temp = myType())``` - in the former it will not last until the end of the then block (and the const ref will be) – onqtam Feb 23 '16 at 07:29
  • Niall - your solution did work but since my macro will expand only to the if statement I cannot force the user to add more braces after the *then* part of the if. also c++98... – onqtam Feb 23 '16 at 07:39
  • @onqtam. Does the `SECTION()` macro have to run the destructor immediately at the end of the `if()/else`? If not then simply creating a local bind (`const&`) with a random name (possibly add a line number) will run the destructor at the end of whatever the larger scope is. – Niall Feb 23 '16 at 07:42
1

After jumping through hoops trying to solve this without using __attribute__((unused)) (which is totally the correct solution), I settled on this.

if(const int& temp = ((true) ? f() : (static_cast<void>(temp), f())) )

The parenthesis around the true suppress a dead code warning, the conditional operator suppresses the warning about use of temp before it is assigned, and the cast to void removes the unused variable warning.

gcc's -Wall and clang's -Weverything don't have anything to say, although a reasonable human might.

Fair warning: if temp is ever declared volatile with a volatile copy constructor, this would be UB (some arcane rule about when lvalue to rvalue conversion occurs).

Weak to Enuma Elish
  • 4,622
  • 3
  • 24
  • 36