]> granicus.if.org Git - clang/commitdiff
Use the new LLVM_LVALUE_FUNCTION to ban two getAs() calls on rvalues.
authorJordan Rose <jordan_rose@apple.com>
Fri, 30 Nov 2012 01:15:32 +0000 (01:15 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 30 Nov 2012 01:15:32 +0000 (01:15 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@168967 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/CFG.h
include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h

index 8cc5d814e822eb48b9268701861260ca2faddb67..5fcd64c76cd3658355e6e135099b97356597a5a1 100644 (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 {
index b112e66d30d383ad266559f3d06993cab77694d3..ebdb02dd22df73e8b3c1846f8134f1d46fc99350 100644 (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,