16
16
#include " clang/AST/DeclTemplate.h"
17
17
#include " clang/AST/DeclVisitor.h"
18
18
#include " clang/AST/Expr.h"
19
+ #include " clang/AST/ODRHash.h"
19
20
#include " clang/AST/OpenMPClause.h"
20
21
#include " clang/AST/PrettyDeclStackTrace.h"
21
22
#include " clang/Basic/SourceManager.h"
@@ -40,11 +41,14 @@ namespace clang {
40
41
serialization::DeclCode Code;
41
42
unsigned AbbrevToUse;
42
43
44
+ bool GeneratingReducedBMI = false ;
45
+
43
46
public:
44
47
ASTDeclWriter (ASTWriter &Writer, ASTContext &Context,
45
- ASTWriter::RecordDataImpl &Record)
48
+ ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI )
46
49
: Writer(Writer), Context(Context), Record(Writer, Record),
47
- Code ((serialization::DeclCode)0), AbbrevToUse(0 ) {}
50
+ Code ((serialization::DeclCode)0), AbbrevToUse(0 ),
51
+ GeneratingReducedBMI(GeneratingReducedBMI) {}
48
52
49
53
uint64_t Emit (Decl *D) {
50
54
if (!Code)
@@ -270,6 +274,27 @@ namespace clang {
270
274
};
271
275
}
272
276
277
+ bool clang::CanElideDeclDef (const Decl *D) {
278
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
279
+ if (FD->isInlined () || FD->isConstexpr ())
280
+ return false ;
281
+
282
+ if (FD->isDependentContext ())
283
+ return false ;
284
+ }
285
+
286
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
287
+ if (!VD->getDeclContext ()->getRedeclContext ()->isFileContext () ||
288
+ VD->isInline () || VD->isConstexpr () || isa<ParmVarDecl>(VD))
289
+ return false ;
290
+
291
+ if (VD->getTemplateSpecializationKind () == TSK_ImplicitInstantiation)
292
+ return false ;
293
+ }
294
+
295
+ return true ;
296
+ }
297
+
273
298
void ASTDeclWriter::Visit (Decl *D) {
274
299
DeclVisitor<ASTDeclWriter>::Visit (D);
275
300
@@ -285,17 +310,23 @@ void ASTDeclWriter::Visit(Decl *D) {
285
310
// have been written. We want it last because we will not read it back when
286
311
// retrieving it from the AST, we'll just lazily set the offset.
287
312
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
288
- Record.push_back (FD->doesThisDeclarationHaveABody ());
289
- if (FD->doesThisDeclarationHaveABody ())
290
- Record.AddFunctionDefinition (FD);
313
+ if (!GeneratingReducedBMI || !CanElideDeclDef (FD)) {
314
+ Record.push_back (FD->doesThisDeclarationHaveABody ());
315
+ if (FD->doesThisDeclarationHaveABody ())
316
+ Record.AddFunctionDefinition (FD);
317
+ } else
318
+ Record.push_back (0 );
291
319
}
292
320
293
321
// Similar to FunctionDecls, handle VarDecl's initializer here and write it
294
322
// after all other Stmts/Exprs. We will not read the initializer until after
295
323
// we have finished recursive deserialization, because it can recursively
296
324
// refer back to the variable.
297
325
if (auto *VD = dyn_cast<VarDecl>(D)) {
298
- Record.AddVarDeclInit (VD);
326
+ if (!GeneratingReducedBMI || !CanElideDeclDef (VD))
327
+ Record.AddVarDeclInit (VD);
328
+ else
329
+ Record.push_back (0 );
299
330
}
300
331
301
332
// And similarly for FieldDecls. We already serialized whether there is a
@@ -2729,7 +2760,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
2729
2760
assert (ID >= FirstDeclID && " invalid decl ID" );
2730
2761
2731
2762
RecordData Record;
2732
- ASTDeclWriter W (*this , Context, Record);
2763
+ ASTDeclWriter W (*this , Context, Record, GeneratingReducedBMI );
2733
2764
2734
2765
// Build a record for this declaration
2735
2766
W.Visit (D);
0 commit comments