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:
parent
33a63913b3
commit
d3e42235c1
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user