@@ -40,6 +40,7 @@ class ClangDeclFinder
40
40
isa<clang::VarDecl>(DRE->getDecl ())) {
41
41
callback (DRE->getDecl ());
42
42
}
43
+
43
44
return true ;
44
45
}
45
46
@@ -56,6 +57,17 @@ class ClangDeclFinder
56
57
callback (CXXCE->getConstructor ());
57
58
return true ;
58
59
}
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 ; }
59
71
};
60
72
61
73
// If any (re)declaration of `decl` contains executable code, returns that
@@ -65,6 +77,11 @@ class ClangDeclFinder
65
77
// the initializer of the variable.
66
78
clang::Decl *getDeclWithExecutableCode (clang::Decl *decl) {
67
79
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
+
68
85
const clang::FunctionDecl *definition;
69
86
if (fd->hasBody (definition)) {
70
87
return const_cast <clang::FunctionDecl *>(definition);
@@ -100,7 +117,7 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
100
117
SmallVector<const clang::Decl *, 8 > stack;
101
118
stack.push_back (decl);
102
119
103
- ClangDeclFinder refFinder ( [&](const clang::Decl *D) {
120
+ auto callback = [&](const clang::Decl *D) {
104
121
for (auto *DC = D->getDeclContext ();; DC = DC->getParent ()) {
105
122
// Check that this is not a local declaration inside a function.
106
123
if (DC->isFunctionOrMethod ()) {
@@ -117,31 +134,55 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
117
134
if (!GlobalClangDecls.insert (D->getCanonicalDecl ()).second ) {
118
135
return ;
119
136
}
137
+
120
138
stack.push_back (D);
121
- });
139
+ };
140
+
141
+ ClangDeclFinder refFinder (callback);
122
142
123
143
while (!stack.empty ()) {
124
144
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
+
125
156
if (clang::Decl *executableDecl = getDeclWithExecutableCode (next)) {
126
157
refFinder.TraverseDecl (executableDecl);
127
158
next = executableDecl;
128
159
}
129
160
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
+
130
179
if (auto var = dyn_cast<clang::VarDecl>(next))
131
180
if (!var->isFileVarDecl ())
132
181
continue ;
133
182
if (isa<clang::FieldDecl>(next)) {
134
183
continue ;
135
184
}
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
+
145
186
ClangCodeGen->HandleTopLevelDecl (clang::DeclGroupRef (next));
146
187
}
147
188
}
0 commit comments