8

I am facing a GCC warning that I want to fix. Basically I am passing to a method a pointer to a local variable, which in my case is perfectly OK. I understand why the compiler tells me that this is a potential problem, but in my case this is OK.

How can I workaround it, on a local space? Passing -fpermissive when compiling will make me fail to find future problems. I want to fix this specific problem, or workaround it.

Code is available here:

#include <cstdio>

class Integer{
public:
    Integer(int i ){ v = i; };
    int value(){ return v; };
private:
    int v;
};

int foo(Integer *i);

int main()
{
    foo( &Integer(12) );
}

int foo(Integer *i)
{
    std::printf("Integer = %d\n", i->value());
}

And compilation gives me:

$ g++ test-reference.cpp -O test-reference
test-reference.cpp: In function ‘int main()’:
test-reference.cpp:15:18: error: taking address of temporary [-fpermissive]

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu3) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

EDIT:

Using const (as in making foo take a const pointer, and marking value() as const) gives the same error.

elcuco
  • 8,948
  • 9
  • 47
  • 69
  • @jalf see Mat response, to understand. In my case, the variable is on scope when the function is called. – elcuco Apr 01 '12 at 08:46
  • 1
    Can't you change the function's signature to `int foo(const Integer& i);`? – jrok Apr 01 '12 at 10:14

3 Answers3

9
Integer i(12);
foo(&i);

That gets rid of the "taking the address of a temporary" problem, which is what you have. You're not passing the address of a local variable (which the above does, and is indeed ok in this case), you're grabbing the address of a temporary.

Obviously, if foo tries to hold on to that pointer one way or another, you'll have issues down the line.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 5
    *you're grabbing the address of a temporary which is very suspicious.* No, it is not suspicious.The behavior is well defined,`12.2/3` *Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created*. – Alok Save Apr 01 '12 at 08:45
  • It's no more dangerous than taking a reference to an rvalue. – Puppy Apr 01 '12 at 08:46
  • Ok, didn't mean to mean it was invalid, just (IMO) suspicious. – Mat Apr 01 '12 at 08:47
  • 1
    @Mat, I need this to be a one liner "without" temporary variables , as this is a temporary variable generated by a DEBUG macro (in my app, its a struct that maintains information about line, file, time, threadID etc). – elcuco Apr 01 '12 at 08:49
  • 2
    @elcuco: `{ Integer i(12); foo(&i); }` – Mat Apr 01 '12 at 08:53
  • 2
    @elcuco: my answer already contains that. The `{}` add nothing of real value. – Mat Apr 01 '12 at 10:56
  • @Mat The value is that it makes it clear that at a high-level, this is meant as one operation and is only broken down into two for technical reasons, and it limits the scope of the single-letter `i` var, which could be considered a coding standard taboo if not used in a tightly-confined scope. – Slipp D. Thompson Dec 31 '14 at 02:45
4
template<typename T> const T* rvalue_address(const T& in) {
    return &in;
}

In my opinion, it should be just as legal to take a const T* as a const T&, but this trivial function will handily perform the conversion.

Puppy
  • 144,682
  • 38
  • 256
  • 465
4

GCC is wrong in this case. Your integer is an rvalue and taking the address of an rvalue is illegal.

§5.3.1 Unary operators, Section 3

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id.

Clang gives an error in this case:

error: taking the address of a temporary object of type 'Integer' [-Waddress-of-temporary]
    foo( &Integer(12) );
         ^~~~~~~~~~~~
Nikola Smiljanić
  • 26,745
  • 6
  • 48
  • 60
  • 4
    GCC is not wrong, it rejected it with `error:` because it is illegal. `-fpermissive` is a GCC extension that basically says "yeah, all right, I know what you *meant*". Extensions are allowed to do whatever non-standard things they like because, well, they're non-standard extensions. – ams Apr 02 '12 at 12:19
  • The standard requires a diagnostic for any ill-formed program unless otherwise specified. A warning is a diagnostic. Even if GCC emitted just a warning *without* -fpermissive, this would not be a conformance issue. – Arne Vogel Jul 08 '15 at 16:15