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

Jordan Rose jordan_rose at apple.com
Wed Sep 12 16:10:45 PDT 2012


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);
  }

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);
  }

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?
Thanks,
Jordan



More information about the cfe-dev mailing list