зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
fd4ce2c9d6
Коммит
6181e56a44
|
@ -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;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче