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
This commit is contained in:
Benjamin Kramer 2012-03-20 19:49:14 +00:00
Родитель fd4ce2c9d6
Коммит 6181e56a44
2 изменённых файлов: 325 добавлений и 15 удалений

Просмотреть файл

@ -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,

Просмотреть файл

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