diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2012-03-20 19:49:14 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2012-03-20 19:49:14 +0000 |
commit | 6181e56a44ecc31dfca8baea2ae8738957003496 (patch) | |
tree | c427f72b4b25374592dd9af0f58ba3f38da80db4 | |
parent | fd4ce2c9d64032b42c037b2af3bf4ebeac5bbac8 (diff) |
Debug info: Tighten up uses of plain MDNode pointers which don't survive replaceOperandWith.
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
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 28 | ||||
-rw-r--r-- | test/CodeGenCXX/debug-info-use-after-free.cpp | 312 |
2 files changed, 325 insertions, 15 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 0595fdf06b..76ba2ec4b3 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -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 index 0000000000..9757ca4d37 --- /dev/null +++ b/test/CodeGenCXX/debug-info-use-after-free.cpp @@ -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; + } +} |