@@ -40,6 +40,7 @@ class ClangDeclFinder
4040 isa<clang::VarDecl>(DRE->getDecl ())) {
4141 callback (DRE->getDecl ());
4242 }
43+
4344 return true ;
4445 }
4546
@@ -56,6 +57,17 @@ class ClangDeclFinder
5657 callback (CXXCE->getConstructor ());
5758 return true ;
5859 }
60+
61+ bool VisitVarDecl (clang::VarDecl *VD) {
62+ if (auto cxxRecord = VD->getType ()->getAsCXXRecordDecl ())
63+ if (auto dtor = cxxRecord->getDestructor ())
64+ callback (dtor);
65+
66+ return true ;
67+ }
68+
69+ bool shouldVisitTemplateInstantiations () const { return true ; }
70+ bool shouldVisitImplicitCode () const { return true ; }
5971};
6072
6173// If any (re)declaration of `decl` contains executable code, returns that
@@ -65,6 +77,11 @@ class ClangDeclFinder
6577// the initializer of the variable.
6678clang::Decl *getDeclWithExecutableCode (clang::Decl *decl) {
6779 if (auto fd = dyn_cast<clang::FunctionDecl>(decl)) {
80+ // If this is a potentially not-yet-instanciated template, we might
81+ // still have a body.
82+ if (fd->getTemplateInstantiationPattern ())
83+ return fd;
84+
6885 const clang::FunctionDecl *definition;
6986 if (fd->hasBody (definition)) {
7087 return const_cast <clang::FunctionDecl *>(definition);
@@ -100,7 +117,7 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
100117 SmallVector<const clang::Decl *, 8 > stack;
101118 stack.push_back (decl);
102119
103- ClangDeclFinder refFinder ( [&](const clang::Decl *D) {
120+ auto callback = [&](const clang::Decl *D) {
104121 for (auto *DC = D->getDeclContext ();; DC = DC->getParent ()) {
105122 // Check that this is not a local declaration inside a function.
106123 if (DC->isFunctionOrMethod ()) {
@@ -117,31 +134,55 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
117134 if (!GlobalClangDecls.insert (D->getCanonicalDecl ()).second ) {
118135 return ;
119136 }
137+
120138 stack.push_back (D);
121- });
139+ };
140+
141+ ClangDeclFinder refFinder (callback);
122142
123143 while (!stack.empty ()) {
124144 auto *next = const_cast <clang::Decl *>(stack.pop_back_val ());
145+
146+ // If a function calls another method in a class template specialization, we
147+ // need to instantiate that other function. Do that here.
148+ if (auto *fn = dyn_cast<clang::FunctionDecl>(next)) {
149+ // Make sure that this method is part of a class template specialization.
150+ if (fn->getTemplateInstantiationPattern ())
151+ Context.getClangModuleLoader ()
152+ ->getClangSema ()
153+ .InstantiateFunctionDefinition (fn->getLocation (), fn);
154+ }
155+
125156 if (clang::Decl *executableDecl = getDeclWithExecutableCode (next)) {
126157 refFinder.TraverseDecl (executableDecl);
127158 next = executableDecl;
128159 }
129160
161+ // Unfortunately, implicitly defined CXXDestructorDecls don't have a real
162+ // body, so we need to traverse these manually.
163+ if (auto *dtor = dyn_cast<clang::CXXDestructorDecl>(next)) {
164+ auto cxxRecord = dtor->getParent ();
165+
166+ for (auto field : cxxRecord->fields ()) {
167+ if (auto fieldCxxRecord = field->getType ()->getAsCXXRecordDecl ())
168+ if (auto *fieldDtor = fieldCxxRecord->getDestructor ())
169+ callback (fieldDtor);
170+ }
171+
172+ for (auto base : cxxRecord->bases ()) {
173+ if (auto baseCxxRecord = base.getType ()->getAsCXXRecordDecl ())
174+ if (auto *baseDtor = baseCxxRecord->getDestructor ())
175+ callback (baseDtor);
176+ }
177+ }
178+
130179 if (auto var = dyn_cast<clang::VarDecl>(next))
131180 if (!var->isFileVarDecl ())
132181 continue ;
133182 if (isa<clang::FieldDecl>(next)) {
134183 continue ;
135184 }
136- // If a method calls another method in a class template specialization, we
137- // need to instantiate that other method. Do that here.
138- if (auto *method = dyn_cast<clang::CXXMethodDecl>(next)) {
139- // Make sure that this method is part of a class template specialization.
140- if (method->getTemplateInstantiationPattern ())
141- Context.getClangModuleLoader ()
142- ->getClangSema ()
143- .InstantiateFunctionDefinition (method->getLocation (), method);
144- }
185+
145186 ClangCodeGen->HandleTopLevelDecl (clang::DeclGroupRef (next));
146187 }
147188}
0 commit comments