1616#include " clang/AST/DeclTemplate.h"
1717#include " clang/AST/DeclVisitor.h"
1818#include " clang/AST/Expr.h"
19+ #include " clang/AST/ODRHash.h"
1920#include " clang/AST/OpenMPClause.h"
2021#include " clang/AST/PrettyDeclStackTrace.h"
2122#include " clang/Basic/SourceManager.h"
@@ -40,11 +41,14 @@ namespace clang {
4041 serialization::DeclCode Code;
4142 unsigned AbbrevToUse;
4243
44+ bool GeneratingReducedBMI = false ;
45+
4346 public:
4447 ASTDeclWriter (ASTWriter &Writer, ASTContext &Context,
45- ASTWriter::RecordDataImpl &Record)
48+ ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI )
4649 : Writer(Writer), Context(Context), Record(Writer, Record),
47- Code ((serialization::DeclCode)0), AbbrevToUse(0 ) {}
50+ Code ((serialization::DeclCode)0), AbbrevToUse(0 ),
51+ GeneratingReducedBMI(GeneratingReducedBMI) {}
4852
4953 uint64_t Emit (Decl *D) {
5054 if (!Code)
@@ -270,6 +274,27 @@ namespace clang {
270274 };
271275}
272276
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+
273298void ASTDeclWriter::Visit (Decl *D) {
274299 DeclVisitor<ASTDeclWriter>::Visit (D);
275300
@@ -285,17 +310,23 @@ void ASTDeclWriter::Visit(Decl *D) {
285310 // have been written. We want it last because we will not read it back when
286311 // retrieving it from the AST, we'll just lazily set the offset.
287312 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 );
291319 }
292320
293321 // Similar to FunctionDecls, handle VarDecl's initializer here and write it
294322 // after all other Stmts/Exprs. We will not read the initializer until after
295323 // we have finished recursive deserialization, because it can recursively
296324 // refer back to the variable.
297325 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 );
299330 }
300331
301332 // And similarly for FieldDecls. We already serialized whether there is a
@@ -2729,7 +2760,7 @@ void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
27292760 assert (ID >= FirstDeclID && " invalid decl ID" );
27302761
27312762 RecordData Record;
2732- ASTDeclWriter W (*this , Context, Record);
2763+ ASTDeclWriter W (*this , Context, Record, GeneratingReducedBMI );
27332764
27342765 // Build a record for this declaration
27352766 W.Visit (D);
0 commit comments