@@ -34,15 +34,37 @@ class ClangDeclRefFinder
3434 return true ;
3535 }
3636};
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+
3759} // end anonymous namespace
3860
3961void 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 ) {
4265 ClangCodeGen->HandleTopLevelDecl (
4366 clang::DeclGroupRef (const_cast <clang::Decl*>(decl)));
44- if (!valueDecl)
45- return ;
67+ return ;
4668 }
4769
4870 if (!GlobalClangDecls.insert (decl->getCanonicalDecl ()).second )
@@ -70,12 +92,9 @@ void IRGenModule::emitClangDecl(const clang::Decl *decl) {
7092
7193 while (!stack.empty ()) {
7294 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;
7998 }
8099 ClangCodeGen->HandleTopLevelDecl (clang::DeclGroupRef (next));
81100 }
0 commit comments