diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1031,6 +1031,39 @@ return LangOpts.CPlusPlus ? Language::CXX : Language::C; } +template +void SaveIteratorDebug(T &Container, SmallVectorImpl &Saver) { +#if _ITERATOR_DEBUG_LEVEL == 2 + std::_Container_proxy *C = Container._Myproxy(); + if (!C) + return; + std::_Lockit _Lock(_LOCK_DEBUG); + for (std::_Iterator_base12 *P = C->_Myfirstiter; P != nullptr; + P = P->_Mynextiter) { + Saver.push_back(P); + } +#endif +} + +// NOTE: This doesn't try to clear out the nodes that weren't there before, +// because they might have an address further down the (old) stack, and the OS +// might have freed those virtual pages already, which would cause a GPF. +template +void ApplyIteratorDebug(T &Container, const SmallVectorImpl &Saver) { +#if _ITERATOR_DEBUG_LEVEL == 2 + std::_Container_proxy *C = Container._Myproxy(); + if (!C) + return; + std::_Lockit _Lock(_LOCK_DEBUG); + std::_Iterator_base12 **P = &C->_Myfirstiter; + for (auto S : Saver) { + *P = (std::_Iterator_base12 *)S; + P = &(*P)->_Mynextiter; + } + *P = nullptr; +#endif +} + /// Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. @@ -1139,6 +1172,9 @@ PreBuildStep(Instance); + SmallVector Iters; + SaveIteratorDebug(Instance.getFrontendOpts().Inputs, Iters); + // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. llvm::CrashRecoveryContext CRC; @@ -1149,6 +1185,8 @@ }, DesiredStackSize); + ApplyIteratorDebug(Instance.getFrontendOpts().Inputs, Iters); + PostBuildStep(Instance); ImportingInstance.getDiagnostics().Report(ImportLoc,