Use the new LLVM_LVALUE_FUNCTION to ban two getAs() calls on rvalues.

If 'x' is a temporary, x.getAs<Foo>() may not be safe if the result is
supposed to persist (if its address is stored somewhere). Since getAs()
can return a null value, the result is almost always stored into a
variable, which of course is not safe when the original value dies.

This has caused several bugs with GCC's "Temporaries May Vanish Sooner Than
You Expect" optimization; in C++11 builds, at least, we'll be able to catch
these problems now.

I would suggest applying these to other getAs() and get*As() methods
(castAs is "better" because sometimes the result is used directly, which
means the temporary will still be live), but these two have both caused
trouble in the analyzer in the past.

llvm-svn: 168967
This commit is contained in:
Jordan Rose 2012-11-30 01:15:32 +00:00
parent 46c6abb306
commit ba101e1b3b
2 changed files with 14 additions and 5 deletions

View File

@ -83,11 +83,13 @@ public:
operator bool() const { return isValid(); }
template<class ElemTy> const ElemTy *getAs() const {
if (llvm::isa<ElemTy>(this))
return static_cast<const ElemTy*>(this);
return 0;
template<class ElemTy> const ElemTy *getAs() const LLVM_LVALUE_FUNCTION {
return dyn_cast<ElemTy>(this);
}
#if LLVM_USE_RVALUE_REFERENCES
template<class ElemTy> void getAs() && LLVM_DELETED_FUNCTION;
#endif
};
class CFGStmt : public CFGElement {

View File

@ -155,7 +155,14 @@ public:
ProgramStateRef getState() const { return State; }
template <typename T>
const T* getLocationAs() const { return llvm::dyn_cast<T>(&Location); }
const T* getLocationAs() const LLVM_LVALUE_FUNCTION {
return dyn_cast<T>(&Location);
}
#if LLVM_USE_RVALUE_REFERENCES
template <typename T>
void getLocationAs() && LLVM_DELETED_FUNCTION;
#endif
static void Profile(llvm::FoldingSetNodeID &ID,
const ProgramPoint &Loc,