DeclUnloader: do not delete instantiated member functions

The body of member functions of a templated class only gets instantiated
when the function is used.  These `CXXMethodDecl` should not be deleted
from the AST; instead return them to the 'instantiation pending' state.
This commit is contained in:
Javier Lopez-Gomez 2023-08-29 16:43:05 +02:00 committed by jenkins
parent 33a63913b3
commit d3e42235c1
2 changed files with 49 additions and 1 deletions

View File

@ -678,6 +678,36 @@ namespace cling {
// DeclContext and when trying to remove them we need the full redecl chain
// still in place.
bool Successful = VisitDeclContext(FD);
// The body of member functions of a templated class only gets instantiated
// when the function is used, i.e.
// `-ClassTemplateDecl
// |-TemplateTypeParmDecl referenced typename depth 0 index 0 T
// |-CXXRecordDecl struct Foo definition
// | |-DefinitionData
// | `-CXXMethodDecl f 'T (T)'
// | |-ParmVarDecl 0x55e5787cac70 referenced x 'T'
// | `-CompoundStmt
// | `-ReturnStmt
// | `-DeclRefExpr 'T' lvalue ParmVar 0x55e5787cac70 'x' 'T'
// `-ClassTemplateSpecializationDecl struct Foo definition
// |-DefinitionData
// |-TemplateArgument type 'int'
// | `-BuiltinType 'int'
// |-CXXMethodDecl f 'int (int)' <<<< Instantiation pending
// | `-ParmVarDecl x 'int':'int'
// |-CXXConstructorDecl implicit used constexpr Foo 'void () noexcept'
// inline default trivial
//
// Such functions should not be deleted from the AST, but returned to the
// 'pending instantiation' state.
if (auto MSI = FD->getMemberSpecializationInfo()) {
MSI->setPointOfInstantiation(SourceLocation());
MSI->setTemplateSpecializationKind(
TemplateSpecializationKind::TSK_ImplicitInstantiation);
FD->setBody(nullptr);
FD->setInstantiationIsPending(true);
return Successful;
}
Successful &= VisitRedeclarable(FD, FD->getDeclContext());
Successful &= VisitDeclaratorDecl(FD);

View File

@ -8,6 +8,9 @@
// RUN: cat %s | %cling 2>&1 | FileCheck %s
#include <memory>
#include <string>
extern "C" int printf(const char* fmt, ...);
.storeState "preUnload"
class MyClass{
@ -22,5 +25,20 @@ public:
.compareState "preUnload"
//CHECK-NOT: Differences
float MyClass = 1.1
//CHECK: (float) 1.1
//CHECK: (float) 1.10000f
template <typename T>
struct MyStruct { T f(T x) { return x; } };
MyStruct<float> obj;
obj.f(42.0)
//CHECK: (float) 42.0000f
.undo
obj.f(42.0)
//CHECK: (float) 42.0000f
auto p = std::make_unique<std::string>("string");
(unsigned long)p.size() // expected-error{{no member named 'size' in 'std::unique_ptr<std::basic_string<char>>'; did you mean to use '->' instead of '.'?}}
(unsigned long)p->size()
//CHECK: (unsigned long) 6
.q