@@ -84,29 +84,28 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
8484 if (!IsCollectingDecls)
8585 return ;
8686 if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) ||
87- isa<NamespaceDecl>(D)) {
87+ isa<NamespaceDecl>(D) || isa<ExportDecl>(D) ) {
8888 // These decls cover a lot of nested declarations that might not be used,
8989 // reducing the granularity and making the output less useful.
9090 return ;
9191 }
92- auto *DC = D->getLexicalDeclContext ();
93- if (!DC || !DC->isFileContext ()) {
94- // We choose to work at namespace level to reduce complexity and the
95- // number of cases we care about.
92+ if (isa<ParmVarDecl>(D)) {
93+ // Parameters are covered by their functions.
9694 return ;
9795 }
96+ auto *DC = D->getLexicalDeclContext ();
97+ if (!DC || !shouldIncludeDeclsIn (DC))
98+ return ;
9899
99100 PendingDecls.push_back (D);
100- if (auto *NS = dyn_cast<NamespaceDecl>(DC)) {
101- // Add any namespaces we have not seen before.
102- // Note that we filter out namespaces from DeclRead as it includes too
103- // all redeclarations and we only want the ones that had other used
104- // declarations.
105- while (NS && ProcessedNamespaces.insert (NS).second ) {
106- PendingDecls.push_back (NS);
107-
108- NS = dyn_cast<NamespaceDecl>(NS->getLexicalParent ());
109- }
101+ for (; (isa<ExportDecl>(DC) || isa<NamespaceDecl>(DC)) &&
102+ ProcessedDeclContexts.insert (DC).second ;
103+ DC = DC->getLexicalParent ()) {
104+ // Add any interesting decl contexts that we have not seen before.
105+ // Note that we filter them out from DeclRead as that would include all
106+ // redeclarations of namespaces, potentially those that do not have any
107+ // imported declarations.
108+ PendingDecls.push_back (cast<Decl>(DC));
110109 }
111110 }
112111
@@ -205,12 +204,38 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
205204
206205private:
207206 std::vector<const Decl *> PendingDecls;
208- llvm::SmallPtrSet<const NamespaceDecl *, 0 > ProcessedNamespaces ;
207+ llvm::SmallPtrSet<const DeclContext *, 0 > ProcessedDeclContexts ;
209208 bool IsCollectingDecls = true ;
210209 const SourceManager &SM;
211210 std::unique_ptr<llvm::raw_ostream> OS;
212211
212+ static bool shouldIncludeDeclsIn (const DeclContext *DC) {
213+ assert (DC && " DC is null" );
214+ // We choose to work at namespace level to reduce complexity and the number
215+ // of cases we care about.
216+ // We still need to carefully handle composite declarations like
217+ // `ExportDecl`.
218+ for (; DC; DC = DC->getLexicalParent ()) {
219+ if (DC->isFileContext ())
220+ return true ;
221+ if (isa<ExportDecl>(DC))
222+ continue ; // Depends on the parent.
223+ return false ;
224+ }
225+ llvm_unreachable (" DeclContext chain must end with a translation unit" );
226+ }
227+
213228 llvm::SmallVector<CharSourceRange, 2 > getRangesToMark (const Decl *D) {
229+ if (auto *ED = dyn_cast<ExportDecl>(D)) {
230+ if (!ED->hasBraces ())
231+ return {SM.getExpansionRange (ED->getExportLoc ())};
232+
233+ return {SM.getExpansionRange (SourceRange (
234+ ED->getExportLoc (),
235+ lexForLBrace (ED->getExportLoc (), D->getLangOpts ()))),
236+ SM.getExpansionRange (ED->getRBraceLoc ())};
237+ }
238+
214239 auto *NS = dyn_cast<NamespaceDecl>(D);
215240 if (!NS)
216241 return {SM.getExpansionRange (D->getSourceRange ())};
@@ -232,17 +257,7 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
232257 }
233258 }
234259 }
235- auto &LangOpts = D->getLangOpts ();
236- // Now skip one token, the next should be the lbrace.
237- Token Tok;
238- if (Lexer::getRawToken (TokenBeforeLBrace, Tok, SM, LangOpts, true ) ||
239- Lexer::getRawToken (Tok.getEndLoc (), Tok, SM, LangOpts, true ) ||
240- Tok.getKind () != tok::l_brace) {
241- // On error or if we did not find the token we expected, avoid marking
242- // everything inside the namespace as used.
243- return {};
244- }
245- LBraceLoc = Tok.getLocation ();
260+ LBraceLoc = lexForLBrace (TokenBeforeLBrace, D->getLangOpts ());
246261 }
247262 return {SM.getExpansionRange (SourceRange (NS->getBeginLoc (), LBraceLoc)),
248263 SM.getExpansionRange (NS->getRBraceLoc ())};
@@ -285,6 +300,20 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
285300
286301 OS->flush ();
287302 }
303+
304+ SourceLocation lexForLBrace (SourceLocation TokenBeforeLBrace,
305+ const LangOptions &LangOpts) {
306+ // Now skip one token, the next should be the lbrace.
307+ Token Tok;
308+ if (Lexer::getRawToken (TokenBeforeLBrace, Tok, SM, LangOpts, true ) ||
309+ Lexer::getRawToken (Tok.getEndLoc (), Tok, SM, LangOpts, true ) ||
310+ Tok.getKind () != tok::l_brace) {
311+ // On error or if we did not find the token we expected, avoid marking
312+ // everything inside the namespace as used.
313+ return SourceLocation ();
314+ }
315+ return Tok.getLocation ();
316+ }
288317};
289318
290319// / Dumps deserialized declarations.
0 commit comments