forked from OSchip/llvm-project
Copy the decls returned by DeclContext::lookup_result to a
new container so we can safely iterate over them. The container holding the lookup decls can under certain conditions be changed while iterating (e.g. because of deserialization). llvm-svn: 167816
This commit is contained in:
parent
193e035b9c
commit
243d82345d
|
@ -2744,14 +2744,14 @@ static OverloadingResult
|
||||||
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
|
ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
OverloadCandidateSet &CandidateSet,
|
OverloadCandidateSet &CandidateSet,
|
||||||
DeclContext::lookup_iterator Con,
|
ArrayRef<NamedDecl *> Ctors,
|
||||||
DeclContext::lookup_iterator ConEnd,
|
|
||||||
OverloadCandidateSet::iterator &Best,
|
OverloadCandidateSet::iterator &Best,
|
||||||
bool CopyInitializing, bool AllowExplicit,
|
bool CopyInitializing, bool AllowExplicit,
|
||||||
bool OnlyListConstructors, bool InitListSyntax) {
|
bool OnlyListConstructors, bool InitListSyntax) {
|
||||||
CandidateSet.clear();
|
CandidateSet.clear();
|
||||||
|
|
||||||
for (; Con != ConEnd; ++Con) {
|
for (ArrayRef<NamedDecl *>::iterator
|
||||||
|
Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) {
|
||||||
NamedDecl *D = *Con;
|
NamedDecl *D = *Con;
|
||||||
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
||||||
bool SuppressUserConversions = false;
|
bool SuppressUserConversions = false;
|
||||||
|
@ -2844,6 +2844,10 @@ static void TryConstructorInitialization(Sema &S,
|
||||||
// through overload resolution.
|
// through overload resolution.
|
||||||
DeclContext::lookup_iterator ConStart, ConEnd;
|
DeclContext::lookup_iterator ConStart, ConEnd;
|
||||||
llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
|
llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
|
||||||
|
// The container holding the constructors can under certain conditions
|
||||||
|
// be changed while iterating (e.g. because of deserialization).
|
||||||
|
// To be safe we copy the lookup results to a new container.
|
||||||
|
SmallVector<NamedDecl*, 16> Ctors(ConStart, ConEnd);
|
||||||
|
|
||||||
OverloadingResult Result = OR_No_Viable_Function;
|
OverloadingResult Result = OR_No_Viable_Function;
|
||||||
OverloadCandidateSet::iterator Best;
|
OverloadCandidateSet::iterator Best;
|
||||||
|
@ -2865,7 +2869,7 @@ static void TryConstructorInitialization(Sema &S,
|
||||||
(!DestRecordDecl->hasDeclaredDefaultConstructor() &&
|
(!DestRecordDecl->hasDeclaredDefaultConstructor() &&
|
||||||
!DestRecordDecl->needsImplicitDefaultConstructor()))
|
!DestRecordDecl->needsImplicitDefaultConstructor()))
|
||||||
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
|
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
|
||||||
CandidateSet, ConStart, ConEnd, Best,
|
CandidateSet, Ctors, Best,
|
||||||
CopyInitialization, AllowExplicit,
|
CopyInitialization, AllowExplicit,
|
||||||
/*OnlyListConstructor=*/true,
|
/*OnlyListConstructor=*/true,
|
||||||
InitListSyntax);
|
InitListSyntax);
|
||||||
|
@ -2883,7 +2887,7 @@ static void TryConstructorInitialization(Sema &S,
|
||||||
if (Result == OR_No_Viable_Function) {
|
if (Result == OR_No_Viable_Function) {
|
||||||
AsInitializerList = false;
|
AsInitializerList = false;
|
||||||
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
|
Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
|
||||||
CandidateSet, ConStart, ConEnd, Best,
|
CandidateSet, Ctors, Best,
|
||||||
CopyInitialization, AllowExplicit,
|
CopyInitialization, AllowExplicit,
|
||||||
/*OnlyListConstructors=*/false,
|
/*OnlyListConstructors=*/false,
|
||||||
InitListSyntax);
|
InitListSyntax);
|
||||||
|
@ -3153,9 +3157,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
|
||||||
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
|
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
|
||||||
|
|
||||||
DeclContext::lookup_iterator Con, ConEnd;
|
DeclContext::lookup_iterator Con, ConEnd;
|
||||||
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
|
llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl);
|
||||||
Con != ConEnd; ++Con) {
|
// The container holding the constructors can under certain conditions
|
||||||
NamedDecl *D = *Con;
|
// be changed while iterating (e.g. because of deserialization).
|
||||||
|
// To be safe we copy the lookup results to a new container.
|
||||||
|
SmallVector<NamedDecl*, 16> Ctors(Con, ConEnd);
|
||||||
|
for (SmallVector<NamedDecl*, 16>::iterator
|
||||||
|
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
|
||||||
|
NamedDecl *D = *CI;
|
||||||
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
|
||||||
|
|
||||||
// Find the constructor (which may be a template).
|
// Find the constructor (which may be a template).
|
||||||
|
@ -4317,11 +4326,17 @@ static void LookupCopyAndMoveConstructors(Sema &S,
|
||||||
CXXRecordDecl *Class,
|
CXXRecordDecl *Class,
|
||||||
Expr *CurInitExpr) {
|
Expr *CurInitExpr) {
|
||||||
DeclContext::lookup_iterator Con, ConEnd;
|
DeclContext::lookup_iterator Con, ConEnd;
|
||||||
for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
|
llvm::tie(Con, ConEnd) = S.LookupConstructors(Class);
|
||||||
Con != ConEnd; ++Con) {
|
// The container holding the constructors can under certain conditions
|
||||||
|
// be changed while iterating (e.g. because of deserialization).
|
||||||
|
// To be safe we copy the lookup results to a new container.
|
||||||
|
SmallVector<NamedDecl*, 16> Ctors(Con, ConEnd);
|
||||||
|
for (SmallVector<NamedDecl*, 16>::iterator
|
||||||
|
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
|
||||||
|
NamedDecl *D = *CI;
|
||||||
CXXConstructorDecl *Constructor = 0;
|
CXXConstructorDecl *Constructor = 0;
|
||||||
|
|
||||||
if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) {
|
if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
|
||||||
// Handle copy/moveconstructors, only.
|
// Handle copy/moveconstructors, only.
|
||||||
if (!Constructor || Constructor->isInvalidDecl() ||
|
if (!Constructor || Constructor->isInvalidDecl() ||
|
||||||
!Constructor->isCopyOrMoveConstructor() ||
|
!Constructor->isCopyOrMoveConstructor() ||
|
||||||
|
@ -4336,7 +4351,7 @@ static void LookupCopyAndMoveConstructors(Sema &S,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle constructor templates.
|
// Handle constructor templates.
|
||||||
FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con);
|
FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D);
|
||||||
if (ConstructorTmpl->isInvalidDecl())
|
if (ConstructorTmpl->isInvalidDecl())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// RUN: %clang_cc1 -std=c++11 %s -emit-pch -o %t.pch
|
||||||
|
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -include-pch %t.pch -verify
|
||||||
|
// expected-no-diagnostics
|
||||||
|
|
||||||
|
// rdar://12631281
|
||||||
|
// This reduced test case exposed a use-after-free memory bug, which was reliable
|
||||||
|
// reproduced only on guarded malloc (and probably valgrind).
|
||||||
|
|
||||||
|
#ifndef HEADER
|
||||||
|
#define HEADER
|
||||||
|
|
||||||
|
template < class _T2> struct is_convertible;
|
||||||
|
template <> struct is_convertible<int> { typedef int type; };
|
||||||
|
|
||||||
|
template <class _T1, class _T2> struct pair {
|
||||||
|
typedef _T1 first_type;
|
||||||
|
typedef _T2 second_type;
|
||||||
|
template <class _U1, class _U2, class = typename is_convertible< first_type>::type>
|
||||||
|
pair(_U1&& , _U2&& ); // expected-note {{candidate}}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class _ForwardIterator>
|
||||||
|
pair<_ForwardIterator, _ForwardIterator> __equal_range(_ForwardIterator) {
|
||||||
|
return pair<_ForwardIterator, _ForwardIterator>(0, 0); // expected-error {{no matching constructor}}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class _ForwardIterator>
|
||||||
|
pair<_ForwardIterator, _ForwardIterator> equal_range( _ForwardIterator a) {
|
||||||
|
return __equal_range(a); // expected-note {{instantiation}}
|
||||||
|
}
|
||||||
|
|
||||||
|
class A {
|
||||||
|
pair<int, int> range() {
|
||||||
|
return equal_range(0); // expected-note {{instantiation}}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue