[cfe-dev] GCC's "Temporaries May Vanish Before You Expect"

David Blaikie dblaikie at gmail.com
Wed Sep 12 16:27:49 PDT 2012


On Wed, Sep 12, 2012 at 4:10 PM, Jordan Rose <jordan_rose at apple.com> wrote:
> Throughout Clang we have a dangerous little helper method that looks like this:
>
>   template<class T> const T *getAs() const {
>     if (isa<T>(this))
>       return static_cast<const T*>(this);
>     return 0;
>   }
>
> or sometimes, more simply
>
>   template<class T> const T *getAs() const {
>     return dyn_cast<T>(this);
>   }
>
> The problem? This method is very dangerous to use with value objects, since you could accidentally do this:
>
> CFGStmt *S = getTemporaryObject().getAs<CFGStmt>();
>
> And indeed we've found two such cases in the last week where we've actually done this in the analyzer (the value object being CFGElement).
>
> I'm half-inclined to remove 'getAs' from CFGElement, but it is useful when you are, say, iterating over a set of known-valid objects. It's the difference between
>
>   I->getAs<CFGStmt>()
>
> and
>
>   dyn_cast<CFGStmt>(&*I)
>
> , the latter of which is slightly more ugly.
>
> The thing that keeps me from removing it is that it IS more convenient and it CAN be made safe. The first way is to use C++11 to forbid the use of this function on rvalues; that looks like this:
>
>   template<class T> const T *getAs() const && = delete;
>   template<class T> const T *getAs() const & {
>     return dyn_cast<T>(this);
>   }

Indeed, my thoughts precisely. [I wonder at what point it'll be worth
moving default development to C++11 and just keeping some bots around
for C++98 back compat testing.]

> This could be hidden behind a compatibility macro:
>
>   template<class T> const T *getAs() const LLVM_RVALUE_DELETE;
>   template<class T> const T *getAs() const LLVM_LVALUE {
>     return dyn_cast<T>(this);
>   }

What do you envision those macros being defined to in C++98? Wouldn't
you end up with errors relating to redeclaration of class members if
they expanded to nothing in C++98 builds.

Seems to me, unfortunately, like we'd have to #ifdef the extra
declaration entirely, or put the declaration inside a function-like
macro if possible, etc)

> The second way is if -fcatch-undefined-behavior could be augmented to handle this case. I have no idea how to do this, though -- perhaps it requires something ASan-ish to poison the temporary memory once its lifetime ends.
>
> Any chance of either of these happening on trunk?

+Richard Smith for the undefined behavior checking possibilities.



More information about the cfe-dev mailing list