Fixes issue in DeclUnloader: do not unload templates intantiated in the PCH

This commit is contained in:
Javier Lopez-Gomez 2019-09-29 21:12:16 +02:00 committed by SFT
parent ed3b079e93
commit 13485246a7
3 changed files with 23 additions and 8 deletions

View File

@ -29,6 +29,20 @@
namespace cling {
using namespace clang;
///\brief Return whether `D' is a template that was first instantiated non-
/// locally, i.e. in a PCH/module. If `D' is not an instantiation, return false.
bool DeclUnloader::isInstantiatedInPCH(const Decl *D) {
SourceManager &SM = D->getASTContext().getSourceManager();
if (const auto FD = dyn_cast<FunctionDecl>(D))
return FD->isTemplateInstantiation() &&
!SM.isLocalSourceLocation(FD->getPointOfInstantiation());
else if (const auto CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
return !SM.isLocalSourceLocation(CTSD->getPointOfInstantiation());
else if (const auto VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
return !SM.isLocalSourceLocation(VTSD->getPointOfInstantiation());
return false;
}
bool DeclUnloader::isDefinition(TagDecl* R) {
return R->isCompleteDefinition() && isa<CXXRecordDecl>(R);
}

View File

@ -54,13 +54,13 @@ namespace cling {
: m_Sema(S), m_CodeGen(CG), m_CurTransaction(T) { }
~DeclUnloader();
///\brief Interface with nice name, forwarding to Visit.
///
///\param[in] D - The declaration to forward.
///\brief Forwards to Visit(), excluding PCH declarations (known to cause
/// problems). If unsure, call this function instead of plain `Visit()'.
///\param[in] D - The declaration to unload
///\returns true on success.
///
bool UnloadDecl(clang::Decl* D) {
if (D->isFromASTFile())
if (D->isFromASTFile() || isInstantiatedInPCH(D))
return true;
return Visit(D);
}
@ -264,6 +264,8 @@ namespace cling {
///
void CollectFilesToUncache(clang::SourceLocation Loc);
bool isInstantiatedInPCH(const clang::Decl *D);
constexpr static bool isDefinition(void*) { return false; }
static bool isDefinition(clang::TagDecl* R);

View File

@ -85,10 +85,9 @@ namespace cling {
const DeclGroupRef& DGR = (*I).m_DGR;
for (DeclGroupRef::const_iterator
Di = DGR.end() - 1, E = DGR.begin() - 1; Di != E; --Di) {
// We only want to revert all that came through parseForModule, and
// not the PCH.
if (!(*Di)->isFromASTFile())
Successful = DeclU.UnloadDecl(*Di) && Successful;
// UnloadDecl() shall unload decls that came through `parseForModule()',
// but not those that came from the PCH.
Successful = DeclU.UnloadDecl(*Di) && Successful;
#ifndef NDEBUG
assert(Successful && "Cannot handle that yet!");
#endif