@@ -34,15 +34,37 @@ class ClangDeclRefFinder
34
34
return true ;
35
35
}
36
36
};
37
+
38
+ // If any (re)declaration of `decl` contains executable code, returns that
39
+ // redeclaration; otherwise, returns nullptr.
40
+ // In the case of a function, executable code is contained in the function
41
+ // definition. In the case of a variable, executable code can be contained in
42
+ // the initializer of the variable.
43
+ clang::Decl *getDeclWithExecutableCode (clang::Decl *decl) {
44
+ if (auto fd = dyn_cast<clang::FunctionDecl>(decl)) {
45
+ const clang::FunctionDecl *definition;
46
+ if (fd->hasBody (definition)) {
47
+ return const_cast <clang::FunctionDecl *>(definition);
48
+ }
49
+ } else if (auto vd = dyn_cast<clang::VarDecl>(decl)) {
50
+ clang::VarDecl *initializingDecl = vd->getInitializingDeclaration ();
51
+ if (initializingDecl) {
52
+ return initializingDecl;
53
+ }
54
+ }
55
+
56
+ return nullptr ;
57
+ }
58
+
37
59
} // end anonymous namespace
38
60
39
61
void IRGenModule::emitClangDecl (const clang::Decl *decl) {
40
- auto valueDecl = dyn_cast<clang::ValueDecl>(decl);
41
- if (!valueDecl || valueDecl->isExternallyVisible ()) {
62
+ // Fast path for the case where `decl` doesn't contain executable code, so it
63
+ // can't reference any other declarations that we would need to emit.
64
+ if (getDeclWithExecutableCode (const_cast <clang::Decl *>(decl)) == nullptr ) {
42
65
ClangCodeGen->HandleTopLevelDecl (
43
66
clang::DeclGroupRef (const_cast <clang::Decl*>(decl)));
44
- if (!valueDecl)
45
- return ;
67
+ return ;
46
68
}
47
69
48
70
if (!GlobalClangDecls.insert (decl->getCanonicalDecl ()).second )
@@ -70,12 +92,9 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
70
92
71
93
while (!stack.empty ()) {
72
94
auto *next = const_cast <clang::Decl *>(stack.pop_back_val ());
73
- if (auto fn = dyn_cast<clang::FunctionDecl>(next)) {
74
- const clang::FunctionDecl *definition;
75
- if (fn->hasBody (definition)) {
76
- refFinder.TraverseDecl (const_cast <clang::FunctionDecl *>(definition));
77
- next = const_cast <clang::FunctionDecl *>(definition);
78
- }
95
+ if (clang::Decl *executableDecl = getDeclWithExecutableCode (next)) {
96
+ refFinder.TraverseDecl (executableDecl);
97
+ next = executableDecl;
79
98
}
80
99
ClangCodeGen->HandleTopLevelDecl (clang::DeclGroupRef (next));
81
100
}
0 commit comments