aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Serialization/ASTWriterDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTWriterDecl.cpp')
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp166
1 files changed, 126 insertions, 40 deletions
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index a58e0d796b31..59dbc36d24e8 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -278,7 +278,7 @@ void ASTDeclWriter::Visit(Decl *D) {
// Source locations require array (variable-length) abbreviations. The
// abbreviation infrastructure requires that arrays are encoded last, so
// we handle it here in the case of those classes derived from DeclaratorDecl
- if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
+ if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
if (auto *TInfo = DD->getTypeSourceInfo())
Record.AddTypeLoc(TInfo->getTypeLoc());
}
@@ -286,16 +286,38 @@ void ASTDeclWriter::Visit(Decl *D) {
// Handle FunctionDecl's body here and write it after all other Stmts/Exprs
// have been written. We want it last because we will not read it back when
// retrieving it from the AST, we'll just lazily set the offset.
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (auto *FD = dyn_cast<FunctionDecl>(D)) {
Record.push_back(FD->doesThisDeclarationHaveABody());
if (FD->doesThisDeclarationHaveABody())
Record.AddFunctionDefinition(FD);
}
+ // Similar to FunctionDecls, handle VarDecl's initializer here and write it
+ // after all other Stmts/Exprs. We will not read the initializer until after
+ // we have finished recursive deserialization, because it can recursively
+ // refer back to the variable.
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ Record.AddVarDeclInit(VD);
+ }
+
+ // And similarly for FieldDecls. We already serialized whether there is a
+ // default member initializer.
+ if (auto *FD = dyn_cast<FieldDecl>(D)) {
+ if (FD->hasInClassInitializer()) {
+ if (Expr *Init = FD->getInClassInitializer()) {
+ Record.push_back(1);
+ Record.AddStmt(Init);
+ } else {
+ Record.push_back(0);
+ // Initializer has not been instantiated yet.
+ }
+ }
+ }
+
// If this declaration is also a DeclContext, write blocks for the
// declarations that lexically stored inside its context and those
// declarations that are visible from its context.
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
+ if (auto *DC = dyn_cast<DeclContext>(D))
VisitDeclContext(DC);
}
@@ -411,6 +433,10 @@ void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
}
void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
+ static_assert(DeclContext::NumTagDeclBits == 10,
+ "You need to update the serializer after you change the "
+ "TagDeclBits");
+
VisitRedeclarable(D);
VisitTypeDecl(D);
Record.push_back(D->getIdentifierNamespace());
@@ -435,6 +461,10 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
}
void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
+ static_assert(DeclContext::NumEnumDeclBits == 20,
+ "You need to update the serializer after you change the "
+ "EnumDeclBits");
+
VisitTagDecl(D);
Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo());
if (!D->getIntegerTypeSourceInfo())
@@ -478,6 +508,10 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
}
void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
+ static_assert(DeclContext::NumRecordDeclBits == 41,
+ "You need to update the serializer after you change the "
+ "RecordDeclBits");
+
VisitTagDecl(D);
Record.push_back(D->hasFlexibleArrayMember());
Record.push_back(D->isAnonymousStructOrUnion());
@@ -546,6 +580,10 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
}
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
+ static_assert(DeclContext::NumFunctionDeclBits == 30,
+ "You need to update the serializer after you change the "
+ "FunctionDeclBits");
+
VisitRedeclarable(D);
Record.push_back(D->getTemplatedKind());
@@ -692,11 +730,15 @@ void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
Record.AddDeclRef(D->Ctor);
VisitFunctionDecl(D);
- Record.push_back(D->isCopyDeductionCandidate());
+ Record.push_back(static_cast<unsigned char>(D->getDeductionCandidateKind()));
Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}
void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ static_assert(DeclContext::NumObjCMethodDeclBits == 24,
+ "You need to update the serializer after you change the "
+ "ObjCMethodDeclBits");
+
VisitNamedDecl(D);
// FIXME: convert to LazyStmtPtr?
// Unlike C/C++, method bodies will never be in header files.
@@ -755,6 +797,10 @@ void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
}
void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ static_assert(DeclContext::NumObjCContainerDeclBits == 51,
+ "You need to update the serializer after you change the "
+ "ObjCContainerDeclBits");
+
VisitNamedDecl(D);
Record.AddSourceLocation(D->getAtStartLoc());
Record.AddSourceRange(D->getAtEndRange());
@@ -935,14 +981,11 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
VisitDeclaratorDecl(D);
Record.push_back(D->isMutable());
- FieldDecl::InitStorageKind ISK = D->InitStorage.getInt();
- Record.push_back(ISK);
- if (ISK == FieldDecl::ISK_CapturedVLAType)
+ Record.push_back((D->StorageKind << 1) | D->BitField);
+ if (D->StorageKind == FieldDecl::ISK_CapturedVLAType)
Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0));
- else if (ISK)
- Record.AddStmt(D->getInClassInitializer());
-
- Record.AddStmt(D->getBitWidth());
+ else if (D->BitField)
+ Record.AddStmt(D->getBitWidth());
if (!D->getDeclName())
Record.AddDeclRef(Context.getInstantiatedFromUnnamedFieldDecl(D));
@@ -1013,6 +1056,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
Record.push_back(D->getTSCSpec());
Record.push_back(D->getInitStyle());
Record.push_back(D->isARCPseudoStrong());
+ bool HasDeducedType = false;
if (!isa<ParmVarDecl>(D)) {
Record.push_back(D->isThisDeclarationADemotedDefinition());
Record.push_back(D->isExceptionVariable());
@@ -1029,36 +1073,34 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
else
Record.push_back(0);
Record.push_back(D->isEscapingByref());
+ HasDeducedType = D->getType()->getContainedDeducedType();
+ Record.push_back(HasDeducedType);
}
Record.push_back(D->getLinkageInternal());
- Record.AddVarDeclInit(D);
-
- if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) {
+ if (D->hasAttr<BlocksAttr>()) {
BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D);
Record.AddStmt(Init.getCopyExpr());
if (Init.getCopyExpr())
Record.push_back(Init.canThrow());
}
- if (D->getStorageDuration() == SD_Static) {
- bool ModulesCodegen = false;
- if (Writer.WritingModule &&
- !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo()) {
- // When building a C++20 module interface unit or a partition unit, a
- // strong definition in the module interface is provided by the
- // compilation of that unit, not by its users. (Inline variables are still
- // emitted in module users.)
- ModulesCodegen =
- (Writer.WritingModule->isInterfaceOrPartition() ||
- (D->hasAttr<DLLExportAttr>() &&
- Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) &&
- Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal;
- }
- Record.push_back(ModulesCodegen);
- if (ModulesCodegen)
- Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
+ bool ModulesCodegen = false;
+ if (Writer.WritingModule && D->getStorageDuration() == SD_Static &&
+ !D->getDescribedVarTemplate()) {
+ // When building a C++20 module interface unit or a partition unit, a
+ // strong definition in the module interface is provided by the
+ // compilation of that unit, not by its users. (Inline variables are still
+ // emitted in module users.)
+ ModulesCodegen =
+ (Writer.WritingModule->isInterfaceOrPartition() ||
+ (D->hasAttr<DLLExportAttr>() &&
+ Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) &&
+ Writer.Context->GetGVALinkageForVariable(D) >= GVA_StrongExternal;
}
+ Record.push_back(ModulesCodegen);
+ if (ModulesCodegen)
+ Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
enum {
VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
@@ -1094,9 +1136,10 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
!D->isConstexpr() &&
!D->isInitCapture() &&
!D->isPreviousDeclInSameBlockScope() &&
- !(D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) &&
!D->isEscapingByref() &&
+ !HasDeducedType &&
D->getStorageDuration() != SD_Static &&
+ !D->getDescribedVarTemplate() &&
!D->getMemberSpecializationInfo())
AbbrevToUse = Writer.getDeclVarAbbrev();
@@ -1241,6 +1284,10 @@ void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) {
}
void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+ static_assert(DeclContext::NumLinkageSpecDeclBits == 4,
+ "You need to update the serializer after you change the"
+ "LinkageSpecDeclBits");
+
VisitDecl(D);
Record.push_back(D->getLanguage());
Record.AddSourceLocation(D->getExternLoc());
@@ -1385,7 +1432,10 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
VisitRecordDecl(D);
enum {
- CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
+ CXXRecNotTemplate = 0,
+ CXXRecTemplate,
+ CXXRecMemberSpecialization,
+ CXXLambda
};
if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) {
Record.push_back(CXXRecTemplate);
@@ -1396,6 +1446,15 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
Record.AddDeclRef(MSInfo->getInstantiatedFrom());
Record.push_back(MSInfo->getTemplateSpecializationKind());
Record.AddSourceLocation(MSInfo->getPointOfInstantiation());
+ } else if (D->isLambda()) {
+ // For a lambda, we need some information early for merging.
+ Record.push_back(CXXLambda);
+ if (auto *Context = D->getLambdaContextDecl()) {
+ Record.AddDeclRef(Context);
+ Record.push_back(D->getLambdaIndexInContext());
+ } else {
+ Record.push_back(0);
+ }
} else {
Record.push_back(CXXRecNotTemplate);
}
@@ -1436,6 +1495,10 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
}
void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
+ "You need to update the serializer after you change the "
+ "CXXConstructorDeclBits");
+
Record.push_back(D->getTrailingAllocKind());
addExplicitSpecifier(D->getExplicitSpecifier(), Record);
if (auto Inherited = D->getInheritedConstructor()) {
@@ -1812,6 +1875,10 @@ void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
/// Emit the DeclContext part of a declaration context decl.
void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
+ static_assert(DeclContext::NumDeclContextBits == 13,
+ "You need to update the serializer after you change the "
+ "DeclContextBits");
+
Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC));
Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC));
}
@@ -1922,6 +1989,10 @@ void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
}
void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
+ static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 2,
+ "You need to update the serializer after you change the "
+ "NumOMPDeclareReductionDeclBits");
+
VisitValueDecl(D);
Record.AddSourceLocation(D->getBeginLoc());
Record.AddStmt(D->getCombinerIn());
@@ -1984,7 +2055,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
// FieldDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
- Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
+ Abv->Add(BitCodeAbbrevOp(0)); // StorageKind
// Type Source Info
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
@@ -2173,8 +2244,8 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // InitStyle
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
Abv->Add(BitCodeAbbrevOp(0)); // Linkage
- Abv->Add(BitCodeAbbrevOp(0)); // HasInit
- Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo
+ Abv->Add(BitCodeAbbrevOp(0)); // ModulesCodegen
+ Abv->Add(BitCodeAbbrevOp(0)); // VarKind (local enum)
// ParmVarDecl
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter
Abv->Add(BitCodeAbbrevOp(0)); // ScopeDepth
@@ -2261,9 +2332,10 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope
Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind
Abv->Add(BitCodeAbbrevOp(0)); // EscapingByref
+ Abv->Add(BitCodeAbbrevOp(0)); // HasDeducedType
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // HasConstant*
- Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // VarKind (local enum)
+ Abv->Add(BitCodeAbbrevOp(0)); // ModulesCodeGen
+ Abv->Add(BitCodeAbbrevOp(0)); // VarKind (local enum)
// Type Source Info
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
@@ -2353,6 +2425,7 @@ void ASTWriter::WriteDeclAbbrevs() {
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates
Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture
Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason
+ Abv->Add(BitCodeAbbrevOp(0)); // IsImmediateEscalating
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv));
@@ -2428,7 +2501,20 @@ void ASTWriter::WriteDeclAbbrevs() {
/// relatively painless since they would presumably only do it for top-level
/// decls.
static bool isRequiredDecl(const Decl *D, ASTContext &Context,
- bool WritingModule) {
+ Module *WritingModule) {
+ // Named modules have different semantics than header modules. Every named
+ // module units owns a translation unit. So the importer of named modules
+ // doesn't need to deserilize everything ahead of time.
+ if (WritingModule && WritingModule->isModulePurview()) {
+ // The PragmaCommentDecl and PragmaDetectMismatchDecl are MSVC's extension.
+ // And the behavior of MSVC for such cases will leak this to the module
+ // users. Given pragma is not a standard thing, the compiler has the space
+ // to do their own decision. Let's follow MSVC here.
+ if (isa<PragmaCommentDecl, PragmaDetectMismatchDecl>(D))
+ return true;
+ return false;
+ }
+
// An ObjCMethodDecl is never considered as "required" because its
// implementation container always is.
@@ -2510,7 +2596,7 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
// compilation of that unit, not by its users. (Inline functions are still
// emitted in module users.)
Linkage = Writer->Context->GetGVALinkageForFunction(FD);
- ModulesCodegen = *Linkage == GVA_StrongExternal;
+ ModulesCodegen = *Linkage >= GVA_StrongExternal;
}
if (Writer->Context->getLangOpts().ModulesCodegen ||
(FD->hasAttr<DLLExportAttr>() &&