@@ -84,29 +84,28 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
84
84
if (!IsCollectingDecls)
85
85
return ;
86
86
if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) ||
87
- isa<NamespaceDecl>(D)) {
87
+ isa<NamespaceDecl>(D) || isa<ExportDecl>(D) ) {
88
88
// These decls cover a lot of nested declarations that might not be used,
89
89
// reducing the granularity and making the output less useful.
90
90
return ;
91
91
}
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.
96
94
return ;
97
95
}
96
+ auto *DC = D->getLexicalDeclContext ();
97
+ if (!DC || !shouldIncludeDeclsIn (DC))
98
+ return ;
98
99
99
100
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));
110
109
}
111
110
}
112
111
@@ -205,12 +204,38 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
205
204
206
205
private:
207
206
std::vector<const Decl *> PendingDecls;
208
- llvm::SmallPtrSet<const NamespaceDecl *, 0 > ProcessedNamespaces ;
207
+ llvm::SmallPtrSet<const DeclContext *, 0 > ProcessedDeclContexts ;
209
208
bool IsCollectingDecls = true ;
210
209
const SourceManager &SM;
211
210
std::unique_ptr<llvm::raw_ostream> OS;
212
211
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
+
213
228
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
+
214
239
auto *NS = dyn_cast<NamespaceDecl>(D);
215
240
if (!NS)
216
241
return {SM.getExpansionRange (D->getSourceRange ())};
@@ -232,17 +257,7 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
232
257
}
233
258
}
234
259
}
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 ());
246
261
}
247
262
return {SM.getExpansionRange (SourceRange (NS->getBeginLoc (), LBraceLoc)),
248
263
SM.getExpansionRange (NS->getRBraceLoc ())};
@@ -285,6 +300,20 @@ class DeserializedDeclsSourceRangePrinter : public ASTConsumer,
285
300
286
301
OS->flush ();
287
302
}
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
+ }
288
317
};
289
318
290
319
// / Dumps deserialized declarations.
0 commit comments