]> granicus.if.org Git - clang/commitdiff
Debug info: Tighten up uses of plain MDNode pointers which don't survive replaceOpera...
authorBenjamin Kramer <benny.kra@googlemail.com>
Tue, 20 Mar 2012 19:49:14 +0000 (19:49 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Tue, 20 Mar 2012 19:49:14 +0000 (19:49 +0000)
TrackingVH notices when it gets RAUW'd. Fixes PR12305 and PR12315.

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

lib/CodeGen/CGDebugInfo.cpp
test/CodeGenCXX/debug-info-use-after-free.cpp [new file with mode: 0644]

index 0595fdf06ba689a58cc8f8b5e8adf8eebe166699..76ba2ec4b38e26878d5cb38cf2b39d023e5cf0eb 100644 (file)
@@ -1199,10 +1199,9 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
 
   if (FwdDecl.isForwardDecl())
     return FwdDecl;
-  
-  llvm::MDNode *MN = FwdDecl;
-  llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
-  
+
+  llvm::TrackingVH<llvm::MDNode> FwdDeclNode(FwdDecl);
+
   // Push the struct on region stack.
   LexicalBlockStack.push_back(FwdDeclNode);
   RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
@@ -1246,15 +1245,15 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
   // get some enums in llvm/Analysis/DebugInfo.h to refer to
   // them.
   if (RD->isUnion())
-    MN->replaceOperandWith(10, Elements);
+    FwdDeclNode->replaceOperandWith(10, Elements);
   else if (CXXDecl) {
-    MN->replaceOperandWith(10, Elements);
-    MN->replaceOperandWith(13, TParamsArray);
+    FwdDeclNode->replaceOperandWith(10, Elements);
+    FwdDeclNode->replaceOperandWith(13, TParamsArray);
   } else
-    MN->replaceOperandWith(10, Elements);
+    FwdDeclNode->replaceOperandWith(10, Elements);
 
-  RegionMap[Ty->getDecl()] = llvm::WeakVH(MN);
-  return llvm::DIType(MN);
+  RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode);
+  return llvm::DIType(FwdDeclNode);
 }
 
 /// CreateType - get objective-c object type.
@@ -1305,8 +1304,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
   // will find it and we're emitting the complete type.
   CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
   // Push the struct on region stack.
-  llvm::MDNode *MN = RealDecl;
-  llvm::TrackingVH<llvm::MDNode> FwdDeclNode = MN;
+  llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl);
 
   LexicalBlockStack.push_back(FwdDeclNode);
   RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
@@ -1401,10 +1399,10 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
   }
 
   llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
-  RealDecl->replaceOperandWith(10, Elements);
+  FwdDeclNode->replaceOperandWith(10, Elements);
   
   LexicalBlockStack.pop_back();
-  return RealDecl;
+  return llvm::DIType(FwdDeclNode);
 }
 
 llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
@@ -1814,7 +1812,7 @@ llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
   uint64_t Size = CGM.getContext().getTypeSize(Ty);
   uint64_t Align = CGM.getContext().getTypeAlign(Ty);
   const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
-  llvm::MDNode *RealDecl = NULL;
+  llvm::TrackingVH<llvm::MDNode> RealDecl;
   
   if (RD->isUnion())
     RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
diff --git a/test/CodeGenCXX/debug-info-use-after-free.cpp b/test/CodeGenCXX/debug-info-use-after-free.cpp
new file mode 100644 (file)
index 0000000..9757ca4
--- /dev/null
@@ -0,0 +1,312 @@
+// RUN: %clang_cc1 -g -emit-llvm-only %s
+// Check that we don't crash.
+// PR12305, PR12315
+
+# 1 "a.h"  3
+template < typename T1 > struct Types1
+{
+  typedef T1 Head;
+};
+template < typename > struct Types;
+template < template < typename > class Tmpl > struct TemplateSel
+{
+  template < typename T > struct Bind
+  {
+    typedef Tmpl < T > type;
+  };
+};
+template < typename > struct NoneT;
+template < template < typename > class T1, template < typename > class > struct Templates2
+{
+  typedef TemplateSel < T1 > Head;
+};
+template < template < typename > class, template < typename > class =
+  NoneT, template < typename > class = NoneT, template < typename > class =
+  NoneT > struct Templates;
+template < template < typename > class T1,
+  template < typename > class T2 > struct Templates <T1, T2 >
+{
+  typedef Templates2 < T1, T2 > type;
+};
+template < typename T > struct TypeList
+{
+  typedef Types1 < T > type;
+};
+template < template < typename > class, class TestSel,
+  typename Types > class TypeParameterizedTest
+{
+public:static bool Register ()
+  {
+    typedef typename Types::Head Type;
+    typename TestSel::template Bind < Type >::type TestClass;
+}};
+
+template < template < typename > class Fixture, typename Tests,
+  typename Types > class TypeParameterizedTestCase
+{
+public:static bool Register (char *, char *, int *)
+  {
+    typedef typename Tests::Head Head;
+    TypeParameterizedTest < Fixture, Head, Types >::Register;
+}};
+
+template < typename > class TypedTestP1
+{
+};
+
+namespace gtest_case_TypedTestP1_
+{
+  template < typename gtest_TypeParam_ > class A:TypedTestP1 <
+    gtest_TypeParam_ >
+  {
+  };
+template < typename gtest_TypeParam_ > class B:TypedTestP1 <
+    gtest_TypeParam_ >
+  {
+  };
+  typedef Templates < A >::type gtest_AllTests_;
+}
+
+template < typename > class TypedTestP2
+{
+};
+
+namespace gtest_case_TypedTestP2_
+{
+  template < typename gtest_TypeParam_ > class A:TypedTestP2 <
+    gtest_TypeParam_ >
+  {
+  };
+  typedef Templates < A >::type gtest_AllTests_;
+}
+
+bool gtest_Int_TypedTestP1 =
+  TypeParameterizedTestCase < TypedTestP1,
+  gtest_case_TypedTestP1_::gtest_AllTests_,
+  TypeList < int >::type >::Register ("Int", "TypedTestP1", 0);
+bool gtest_Int_TypedTestP2 =
+  TypeParameterizedTestCase < TypedTestP2,
+  gtest_case_TypedTestP2_::gtest_AllTests_,
+  TypeList < Types < int > >::type >::Register ("Int", "TypedTestP2", 0);
+
+template < typename _Tp > struct new_allocator
+{
+  typedef _Tp *pointer;
+  template < typename > struct rebind {
+    typedef new_allocator other;
+  };
+};
+template < typename _Tp > struct allocator:new_allocator < _Tp > {
+};
+template < typename _Tp, typename _Alloc > struct _Vector_base {
+  typedef typename _Alloc::template rebind < _Tp >::other _Tp_alloc_type;
+  struct _Vector_impl {
+    typename _Tp_alloc_type::pointer _M_end_of_storage;
+  };
+  _Vector_base () {
+    foo((int *) this->_M_impl._M_end_of_storage);
+  }
+  void foo(int *);
+  _Vector_impl _M_impl;
+};
+template < typename _Tp, typename _Alloc =
+allocator < _Tp > >struct vector:_Vector_base < _Tp, _Alloc > { };
+
+
+template < class T> struct HHH {};
+struct DDD { int x_;};
+struct Data;
+struct X1;
+struct CCC:DDD {   virtual void xxx (HHH < X1 >); };
+template < class SSS > struct EEE:vector < HHH < SSS > > { };
+template < class SSS, class = EEE < SSS > >class FFF { };
+template < class SSS, class GGG = EEE < SSS > >class AAA:FFF <GGG> { };
+class BBB:virtual CCC {
+  void xxx (HHH < X1 >);
+  vector < HHH < X1 > >aaa;
+};
+class ZZZ:AAA < Data >, BBB { virtual ZZZ *ppp () ; };
+ZZZ * ZZZ::ppp () { return new ZZZ; }
+
+namespace std
+{
+  template < class, class > struct pair;
+}
+namespace __gnu_cxx {
+template < typename > class new_allocator;
+}
+namespace std {
+template < typename _Tp > class allocator:__gnu_cxx::new_allocator < _Tp > {
+};
+template < typename, typename > struct _Vector_base {
+};
+template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class vector:_Vector_base < _Tp,
+  _Alloc
+        > {
+        };
+}
+
+namespace
+std {
+  template <
+      typename,
+      typename > struct unary_function;
+  template <
+      typename,
+      typename,
+      typename > struct binary_function;
+  template <
+      typename
+      _Tp > struct equal_to:
+        binary_function <
+        _Tp,
+        _Tp,
+        bool > {
+        };
+  template <
+      typename
+      _Pair > struct _Select1st:
+        unary_function <
+        _Pair,
+        typename
+        _Pair::first_type > {
+        };
+}
+# 1 "f.h"  3
+using
+std::pair;
+namespace
+__gnu_cxx {
+  template <
+      class > struct hash;
+  template <
+      class,
+      class,
+      class,
+      class,
+      class
+          _EqualKey,
+      class >
+          class
+          hashtable {
+           public:
+            typedef _EqualKey
+                key_equal;
+          };
+  using
+      std::equal_to;
+  using
+      std::allocator;
+  using
+      std::_Select1st;
+  template < class _Key, class _Tp, class _HashFn =
+      hash < _Key >, class _EqualKey = equal_to < _Key >, class _Alloc =
+      allocator < _Tp > >class hash_map {
+        typedef
+            hashtable <
+            pair <
+            _Key,
+        _Tp >,
+        _Key,
+        _HashFn,
+        _Select1st <
+            pair <
+            _Key,
+        _Tp > >,
+        _EqualKey,
+        _Alloc >
+            _Ht;
+       public:
+        typename _Ht::key_type;
+        typedef typename
+            _Ht::key_equal
+            key_equal;
+      };
+}
+using
+__gnu_cxx::hash_map;
+class
+C2;
+template < class > class scoped_ptr {
+};
+namespace {
+class
+    AAA {
+      virtual ~
+          AAA () {
+          }};
+}
+template < typename > class EEE;
+template < typename CCC, typename =
+typename CCC::key_equal, typename =
+EEE < CCC > >class III {
+};
+namespace
+util {
+  class
+      EEE {
+      };
+}
+namespace {
+class
+    C1:
+      util::EEE {
+       public:
+        class
+            C3:
+              AAA {
+                struct FFF;
+                typedef
+                    III <
+                    hash_map <
+                    C2,
+                    FFF > >
+                        GGG;
+                GGG
+                    aaa;
+                friend
+                    C1;
+              };
+        void
+            HHH (C3::GGG &);
+      };
+}
+namespace
+n1 {
+  class
+      Test {
+      };
+  template <
+      typename >
+      class
+      C7 {
+      };
+  class
+      C4:
+        n1::Test {
+          vector <
+              C1::C3 * >
+              a1;
+        };
+  enum C5 { };
+  class
+      C6:
+        C4,
+        n1::C7 <
+        C5 > {
+        };
+  class
+      C8:
+        C6 {
+        };
+  class
+      C9:
+        C8 {
+          void
+              TestBody ();
+        };
+  void
+      C9::TestBody () {
+        scoped_ptr < C1::C3 > context;
+      }
+}