forked from OSchip/llvm-project
[PCH] Deserializing the DeclContext of a template parameter is not safe
until recursive loading is finished. Otherwise we may end up with a template trying to deserialize a template parameter that is in the process of getting loaded. rdar://13135282 llvm-svn: 175329
This commit is contained in:
parent
0062ba6494
commit
83a6e3bfab
|
@ -833,6 +833,21 @@ private:
|
||||||
/// \brief Keeps track of the elements added to PendingDeclChains.
|
/// \brief Keeps track of the elements added to PendingDeclChains.
|
||||||
llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown;
|
llvm::SmallSet<serialization::DeclID, 16> PendingDeclChainsKnown;
|
||||||
|
|
||||||
|
/// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has
|
||||||
|
/// been loaded but its DeclContext was not set yet.
|
||||||
|
struct PendingDeclContextInfo {
|
||||||
|
Decl *D;
|
||||||
|
serialization::GlobalDeclID SemaDC;
|
||||||
|
serialization::GlobalDeclID LexicalDC;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief The set of Decls that have been loaded but their DeclContexts are
|
||||||
|
/// not set yet.
|
||||||
|
///
|
||||||
|
/// The DeclContexts for these Decls will be set once recursive loading has
|
||||||
|
/// been completed.
|
||||||
|
std::deque<PendingDeclContextInfo> PendingDeclContextInfos;
|
||||||
|
|
||||||
/// \brief The set of Objective-C categories that have been deserialized
|
/// \brief The set of Objective-C categories that have been deserialized
|
||||||
/// since the last time the declaration chains were linked.
|
/// since the last time the declaration chains were linked.
|
||||||
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
|
llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized;
|
||||||
|
@ -1076,6 +1091,14 @@ private:
|
||||||
|
|
||||||
void finishPendingActions();
|
void finishPendingActions();
|
||||||
|
|
||||||
|
void addPendingDeclContextInfo(Decl *D,
|
||||||
|
serialization::GlobalDeclID SemaDC,
|
||||||
|
serialization::GlobalDeclID LexicalDC) {
|
||||||
|
assert(D);
|
||||||
|
PendingDeclContextInfo Info = { D, SemaDC, LexicalDC };
|
||||||
|
PendingDeclContextInfos.push_back(Info);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Produce an error diagnostic and return true.
|
/// \brief Produce an error diagnostic and return true.
|
||||||
///
|
///
|
||||||
/// This routine should only be used for fatal errors that have to
|
/// This routine should only be used for fatal errors that have to
|
||||||
|
|
|
@ -6986,7 +6986,7 @@ void ASTReader::ReadComments() {
|
||||||
|
|
||||||
void ASTReader::finishPendingActions() {
|
void ASTReader::finishPendingActions() {
|
||||||
while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
|
while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() ||
|
||||||
!PendingMacroIDs.empty()) {
|
!PendingMacroIDs.empty() || !PendingDeclContextInfos.empty()) {
|
||||||
// If any identifiers with corresponding top-level declarations have
|
// If any identifiers with corresponding top-level declarations have
|
||||||
// been loaded, load those declarations now.
|
// been loaded, load those declarations now.
|
||||||
while (!PendingIdentifierInfos.empty()) {
|
while (!PendingIdentifierInfos.empty()) {
|
||||||
|
@ -7013,6 +7013,16 @@ void ASTReader::finishPendingActions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PendingMacroIDs.clear();
|
PendingMacroIDs.clear();
|
||||||
|
|
||||||
|
// Wire up the DeclContexts for Decls that we delayed setting until
|
||||||
|
// recursive loading is completed.
|
||||||
|
while (!PendingDeclContextInfos.empty()) {
|
||||||
|
PendingDeclContextInfo Info = PendingDeclContextInfos.front();
|
||||||
|
PendingDeclContextInfos.pop_front();
|
||||||
|
DeclContext *SemaDC = cast<DeclContext>(GetDecl(Info.SemaDC));
|
||||||
|
DeclContext *LexicalDC = cast<DeclContext>(GetDecl(Info.LexicalDC));
|
||||||
|
Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we deserialized any C++ or Objective-C class definitions, any
|
// If we deserialized any C++ or Objective-C class definitions, any
|
||||||
|
|
|
@ -44,9 +44,6 @@ namespace clang {
|
||||||
unsigned &Idx;
|
unsigned &Idx;
|
||||||
TypeID TypeIDForTypeDecl;
|
TypeID TypeIDForTypeDecl;
|
||||||
|
|
||||||
DeclID DeclContextIDForTemplateParmDecl;
|
|
||||||
DeclID LexicalDeclContextIDForTemplateParmDecl;
|
|
||||||
|
|
||||||
bool HasPendingBody;
|
bool HasPendingBody;
|
||||||
|
|
||||||
uint64_t GetCurrentCursorOffset();
|
uint64_t GetCurrentCursorOffset();
|
||||||
|
@ -329,14 +326,6 @@ void ASTDeclReader::Visit(Decl *D) {
|
||||||
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
|
Reader.PendingBodies[FD] = GetCurrentCursorOffset();
|
||||||
HasPendingBody = true;
|
HasPendingBody = true;
|
||||||
}
|
}
|
||||||
} else if (D->isTemplateParameter()) {
|
|
||||||
// If we have a fully initialized template parameter, we can now
|
|
||||||
// set its DeclContext.
|
|
||||||
DeclContext *SemaDC = cast<DeclContext>(
|
|
||||||
Reader.GetDecl(DeclContextIDForTemplateParmDecl));
|
|
||||||
DeclContext *LexicalDC = cast<DeclContext>(
|
|
||||||
Reader.GetDecl(LexicalDeclContextIDForTemplateParmDecl));
|
|
||||||
D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,8 +335,11 @@ void ASTDeclReader::VisitDecl(Decl *D) {
|
||||||
// parameter immediately, because the template parameter might be
|
// parameter immediately, because the template parameter might be
|
||||||
// used in the formulation of its DeclContext. Use the translation
|
// used in the formulation of its DeclContext. Use the translation
|
||||||
// unit DeclContext as a placeholder.
|
// unit DeclContext as a placeholder.
|
||||||
DeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
||||||
LexicalDeclContextIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID(Record, Idx);
|
||||||
|
Reader.addPendingDeclContextInfo(D,
|
||||||
|
SemaDCIDForTemplateParmDecl,
|
||||||
|
LexicalDCIDForTemplateParmDecl);
|
||||||
D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
|
D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
|
||||||
} else {
|
} else {
|
||||||
DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
|
DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx);
|
||||||
|
|
|
@ -79,3 +79,9 @@ namespace TestNestedExpansion {
|
||||||
Int &g(Int, int, double);
|
Int &g(Int, int, double);
|
||||||
Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0);
|
Int &test = NestedExpansion<char, char, char>().f(0, 1, 2, Int(3), 4, 5.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace rdar13135282 {
|
||||||
|
void test() {
|
||||||
|
__mt_alloc<> mt = __mt_alloc<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -220,3 +220,29 @@ template<typename...A> struct NestedExpansion {
|
||||||
template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...));
|
template<typename...B> auto f(A...a, B...b) -> decltype(g(a + b...));
|
||||||
};
|
};
|
||||||
template struct NestedExpansion<char, char, char>;
|
template struct NestedExpansion<char, char, char>;
|
||||||
|
|
||||||
|
namespace rdar13135282 {
|
||||||
|
template < typename _Alloc >
|
||||||
|
void foo(_Alloc = _Alloc());
|
||||||
|
|
||||||
|
template < bool > class __pool;
|
||||||
|
|
||||||
|
template < template < bool > class _PoolTp >
|
||||||
|
struct __common_pool {
|
||||||
|
typedef _PoolTp < 0 > pool_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < template < bool > class _PoolTp >
|
||||||
|
struct __common_pool_base : __common_pool < _PoolTp > {};
|
||||||
|
|
||||||
|
template < template < bool > class _PoolTp >
|
||||||
|
struct A : __common_pool_base < _PoolTp > {};
|
||||||
|
|
||||||
|
template < typename _Poolp = A < __pool > >
|
||||||
|
struct __mt_alloc {
|
||||||
|
typedef typename _Poolp::pool_type __pool_type;
|
||||||
|
__mt_alloc() {
|
||||||
|
foo<__mt_alloc<> >();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue