Path: blob/main/contrib/llvm-project/clang/lib/Serialization/ASTWriter.cpp
35234 views
//===- ASTWriter.cpp - AST File Writer ------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the ASTWriter class, which writes AST files.9//10//===----------------------------------------------------------------------===//1112#include "ASTCommon.h"13#include "ASTReaderInternals.h"14#include "MultiOnDiskHashTable.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/ASTUnresolvedSet.h"17#include "clang/AST/AbstractTypeWriter.h"18#include "clang/AST/Attr.h"19#include "clang/AST/Decl.h"20#include "clang/AST/DeclBase.h"21#include "clang/AST/DeclCXX.h"22#include "clang/AST/DeclContextInternals.h"23#include "clang/AST/DeclFriend.h"24#include "clang/AST/DeclObjC.h"25#include "clang/AST/DeclTemplate.h"26#include "clang/AST/DeclarationName.h"27#include "clang/AST/Expr.h"28#include "clang/AST/ExprCXX.h"29#include "clang/AST/LambdaCapture.h"30#include "clang/AST/NestedNameSpecifier.h"31#include "clang/AST/OpenACCClause.h"32#include "clang/AST/OpenMPClause.h"33#include "clang/AST/RawCommentList.h"34#include "clang/AST/TemplateName.h"35#include "clang/AST/Type.h"36#include "clang/AST/TypeLocVisitor.h"37#include "clang/Basic/Diagnostic.h"38#include "clang/Basic/DiagnosticOptions.h"39#include "clang/Basic/FileManager.h"40#include "clang/Basic/FileSystemOptions.h"41#include "clang/Basic/IdentifierTable.h"42#include "clang/Basic/LLVM.h"43#include "clang/Basic/Lambda.h"44#include "clang/Basic/LangOptions.h"45#include "clang/Basic/Module.h"46#include "clang/Basic/ObjCRuntime.h"47#include "clang/Basic/OpenACCKinds.h"48#include "clang/Basic/OpenCLOptions.h"49#include "clang/Basic/SourceLocation.h"50#include "clang/Basic/SourceManager.h"51#include "clang/Basic/SourceManagerInternals.h"52#include "clang/Basic/Specifiers.h"53#include "clang/Basic/TargetInfo.h"54#include "clang/Basic/TargetOptions.h"55#include "clang/Basic/Version.h"56#include "clang/Lex/HeaderSearch.h"57#include "clang/Lex/HeaderSearchOptions.h"58#include "clang/Lex/MacroInfo.h"59#include "clang/Lex/ModuleMap.h"60#include "clang/Lex/PreprocessingRecord.h"61#include "clang/Lex/Preprocessor.h"62#include "clang/Lex/PreprocessorOptions.h"63#include "clang/Lex/Token.h"64#include "clang/Sema/IdentifierResolver.h"65#include "clang/Sema/ObjCMethodList.h"66#include "clang/Sema/Sema.h"67#include "clang/Sema/SemaCUDA.h"68#include "clang/Sema/SemaObjC.h"69#include "clang/Sema/Weak.h"70#include "clang/Serialization/ASTBitCodes.h"71#include "clang/Serialization/ASTReader.h"72#include "clang/Serialization/ASTRecordWriter.h"73#include "clang/Serialization/InMemoryModuleCache.h"74#include "clang/Serialization/ModuleFile.h"75#include "clang/Serialization/ModuleFileExtension.h"76#include "clang/Serialization/SerializationDiagnostic.h"77#include "llvm/ADT/APFloat.h"78#include "llvm/ADT/APInt.h"79#include "llvm/ADT/APSInt.h"80#include "llvm/ADT/ArrayRef.h"81#include "llvm/ADT/DenseMap.h"82#include "llvm/ADT/Hashing.h"83#include "llvm/ADT/PointerIntPair.h"84#include "llvm/ADT/STLExtras.h"85#include "llvm/ADT/ScopeExit.h"86#include "llvm/ADT/SmallPtrSet.h"87#include "llvm/ADT/SmallString.h"88#include "llvm/ADT/SmallVector.h"89#include "llvm/ADT/StringMap.h"90#include "llvm/ADT/StringRef.h"91#include "llvm/Bitstream/BitCodes.h"92#include "llvm/Bitstream/BitstreamWriter.h"93#include "llvm/Support/Casting.h"94#include "llvm/Support/Compression.h"95#include "llvm/Support/DJB.h"96#include "llvm/Support/Endian.h"97#include "llvm/Support/EndianStream.h"98#include "llvm/Support/Error.h"99#include "llvm/Support/ErrorHandling.h"100#include "llvm/Support/LEB128.h"101#include "llvm/Support/MemoryBuffer.h"102#include "llvm/Support/OnDiskHashTable.h"103#include "llvm/Support/Path.h"104#include "llvm/Support/SHA1.h"105#include "llvm/Support/TimeProfiler.h"106#include "llvm/Support/VersionTuple.h"107#include "llvm/Support/raw_ostream.h"108#include <algorithm>109#include <cassert>110#include <cstdint>111#include <cstdlib>112#include <cstring>113#include <ctime>114#include <limits>115#include <memory>116#include <optional>117#include <queue>118#include <tuple>119#include <utility>120#include <vector>121122using namespace clang;123using namespace clang::serialization;124125template <typename T, typename Allocator>126static StringRef bytes(const std::vector<T, Allocator> &v) {127if (v.empty()) return StringRef();128return StringRef(reinterpret_cast<const char*>(&v[0]),129sizeof(T) * v.size());130}131132template <typename T>133static StringRef bytes(const SmallVectorImpl<T> &v) {134return StringRef(reinterpret_cast<const char*>(v.data()),135sizeof(T) * v.size());136}137138static std::string bytes(const std::vector<bool> &V) {139std::string Str;140Str.reserve(V.size() / 8);141for (unsigned I = 0, E = V.size(); I < E;) {142char Byte = 0;143for (unsigned Bit = 0; Bit < 8 && I < E; ++Bit, ++I)144Byte |= V[I] << Bit;145Str += Byte;146}147return Str;148}149150//===----------------------------------------------------------------------===//151// Type serialization152//===----------------------------------------------------------------------===//153154static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) {155switch (id) {156#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \157case Type::CLASS_ID: return TYPE_##CODE_ID;158#include "clang/Serialization/TypeBitCodes.def"159case Type::Builtin:160llvm_unreachable("shouldn't be serializing a builtin type this way");161}162llvm_unreachable("bad type kind");163}164165namespace {166167std::optional<std::set<const FileEntry *>>168GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {169if (!PP.getHeaderSearchInfo()170.getHeaderSearchOpts()171.ModulesPruneNonAffectingModuleMaps)172return std::nullopt;173174const HeaderSearch &HS = PP.getHeaderSearchInfo();175const ModuleMap &MM = HS.getModuleMap();176177std::set<const FileEntry *> ModuleMaps;178std::set<const Module *> ProcessedModules;179auto CollectModuleMapsForHierarchy = [&](const Module *M) {180M = M->getTopLevelModule();181182if (!ProcessedModules.insert(M).second)183return;184185std::queue<const Module *> Q;186Q.push(M);187while (!Q.empty()) {188const Module *Mod = Q.front();189Q.pop();190191// The containing module map is affecting, because it's being pointed192// into by Module::DefinitionLoc.193if (auto FE = MM.getContainingModuleMapFile(Mod))194ModuleMaps.insert(*FE);195// For inferred modules, the module map that allowed inferring is not196// related to the virtual containing module map file. It did affect the197// compilation, though.198if (auto FE = MM.getModuleMapFileForUniquing(Mod))199ModuleMaps.insert(*FE);200201for (auto *SubM : Mod->submodules())202Q.push(SubM);203}204};205206// Handle all the affecting modules referenced from the root module.207208CollectModuleMapsForHierarchy(RootModule);209210std::queue<const Module *> Q;211Q.push(RootModule);212while (!Q.empty()) {213const Module *CurrentModule = Q.front();214Q.pop();215216for (const Module *ImportedModule : CurrentModule->Imports)217CollectModuleMapsForHierarchy(ImportedModule);218for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)219CollectModuleMapsForHierarchy(UndeclaredModule);220221for (auto *M : CurrentModule->submodules())222Q.push(M);223}224225// Handle textually-included headers that belong to other modules.226227SmallVector<OptionalFileEntryRef, 16> FilesByUID;228HS.getFileMgr().GetUniqueIDMapping(FilesByUID);229230if (FilesByUID.size() > HS.header_file_size())231FilesByUID.resize(HS.header_file_size());232233for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {234OptionalFileEntryRef File = FilesByUID[UID];235if (!File)236continue;237238const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);239if (!HFI)240continue; // We have no information on this being a header file.241if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)242continue; // Modular header, handled in the above module-based loop.243if (!HFI->isCompilingModuleHeader && !HFI->IsLocallyIncluded)244continue; // Non-modular header not included locally is not affecting.245246for (const auto &KH : HS.findResolvedModulesForHeader(*File))247if (const Module *M = KH.getModule())248CollectModuleMapsForHierarchy(M);249}250251// FIXME: This algorithm is not correct for module map hierarchies where252// module map file defining a (sub)module of a top-level module X includes253// a module map file that defines a (sub)module of another top-level module Y.254// Whenever X is affecting and Y is not, "replaying" this PCM file will fail255// when parsing module map files for X due to not knowing about the `extern`256// module map for Y.257//258// We don't have a good way to fix it here. We could mark all children of259// affecting module map files as being affecting as well, but that's260// expensive. SourceManager does not model the edge from parent to child261// SLocEntries, so instead, we would need to iterate over leaf module map262// files, walk up their include hierarchy and check whether we arrive at an263// affecting module map.264//265// Instead of complicating and slowing down this function, we should probably266// just ban module map hierarchies where module map defining a (sub)module X267// includes a module map defining a module that's not a submodule of X.268269return ModuleMaps;270}271272class ASTTypeWriter {273ASTWriter &Writer;274ASTWriter::RecordData Record;275ASTRecordWriter BasicWriter;276277public:278ASTTypeWriter(ASTWriter &Writer)279: Writer(Writer), BasicWriter(Writer, Record) {}280281uint64_t write(QualType T) {282if (T.hasLocalNonFastQualifiers()) {283Qualifiers Qs = T.getLocalQualifiers();284BasicWriter.writeQualType(T.getLocalUnqualifiedType());285BasicWriter.writeQualifiers(Qs);286return BasicWriter.Emit(TYPE_EXT_QUAL, Writer.getTypeExtQualAbbrev());287}288289const Type *typePtr = T.getTypePtr();290serialization::AbstractTypeWriter<ASTRecordWriter> atw(BasicWriter);291atw.write(typePtr);292return BasicWriter.Emit(getTypeCodeForTypeClass(typePtr->getTypeClass()),293/*abbrev*/ 0);294}295};296297class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {298using LocSeq = SourceLocationSequence;299300ASTRecordWriter &Record;301LocSeq *Seq;302303void addSourceLocation(SourceLocation Loc) {304Record.AddSourceLocation(Loc, Seq);305}306void addSourceRange(SourceRange Range) { Record.AddSourceRange(Range, Seq); }307308public:309TypeLocWriter(ASTRecordWriter &Record, LocSeq *Seq)310: Record(Record), Seq(Seq) {}311312#define ABSTRACT_TYPELOC(CLASS, PARENT)313#define TYPELOC(CLASS, PARENT) \314void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);315#include "clang/AST/TypeLocNodes.def"316317void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);318void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);319};320321} // namespace322323void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {324// nothing to do325}326327void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {328addSourceLocation(TL.getBuiltinLoc());329if (TL.needsExtraLocalData()) {330Record.push_back(TL.getWrittenTypeSpec());331Record.push_back(static_cast<uint64_t>(TL.getWrittenSignSpec()));332Record.push_back(static_cast<uint64_t>(TL.getWrittenWidthSpec()));333Record.push_back(TL.hasModeAttr());334}335}336337void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {338addSourceLocation(TL.getNameLoc());339}340341void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {342addSourceLocation(TL.getStarLoc());343}344345void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {346// nothing to do347}348349void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {350// nothing to do351}352353void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) {354// nothing to do355}356357void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {358addSourceLocation(TL.getCaretLoc());359}360361void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {362addSourceLocation(TL.getAmpLoc());363}364365void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {366addSourceLocation(TL.getAmpAmpLoc());367}368369void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {370addSourceLocation(TL.getStarLoc());371Record.AddTypeSourceInfo(TL.getClassTInfo());372}373374void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {375addSourceLocation(TL.getLBracketLoc());376addSourceLocation(TL.getRBracketLoc());377Record.push_back(TL.getSizeExpr() ? 1 : 0);378if (TL.getSizeExpr())379Record.AddStmt(TL.getSizeExpr());380}381382void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {383VisitArrayTypeLoc(TL);384}385386void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {387VisitArrayTypeLoc(TL);388}389390void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {391VisitArrayTypeLoc(TL);392}393394void TypeLocWriter::VisitDependentSizedArrayTypeLoc(395DependentSizedArrayTypeLoc TL) {396VisitArrayTypeLoc(TL);397}398399void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(400DependentAddressSpaceTypeLoc TL) {401addSourceLocation(TL.getAttrNameLoc());402SourceRange range = TL.getAttrOperandParensRange();403addSourceLocation(range.getBegin());404addSourceLocation(range.getEnd());405Record.AddStmt(TL.getAttrExprOperand());406}407408void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(409DependentSizedExtVectorTypeLoc TL) {410addSourceLocation(TL.getNameLoc());411}412413void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {414addSourceLocation(TL.getNameLoc());415}416417void TypeLocWriter::VisitDependentVectorTypeLoc(418DependentVectorTypeLoc TL) {419addSourceLocation(TL.getNameLoc());420}421422void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {423addSourceLocation(TL.getNameLoc());424}425426void TypeLocWriter::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {427addSourceLocation(TL.getAttrNameLoc());428SourceRange range = TL.getAttrOperandParensRange();429addSourceLocation(range.getBegin());430addSourceLocation(range.getEnd());431Record.AddStmt(TL.getAttrRowOperand());432Record.AddStmt(TL.getAttrColumnOperand());433}434435void TypeLocWriter::VisitDependentSizedMatrixTypeLoc(436DependentSizedMatrixTypeLoc TL) {437addSourceLocation(TL.getAttrNameLoc());438SourceRange range = TL.getAttrOperandParensRange();439addSourceLocation(range.getBegin());440addSourceLocation(range.getEnd());441Record.AddStmt(TL.getAttrRowOperand());442Record.AddStmt(TL.getAttrColumnOperand());443}444445void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {446addSourceLocation(TL.getLocalRangeBegin());447addSourceLocation(TL.getLParenLoc());448addSourceLocation(TL.getRParenLoc());449addSourceRange(TL.getExceptionSpecRange());450addSourceLocation(TL.getLocalRangeEnd());451for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)452Record.AddDeclRef(TL.getParam(i));453}454455void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {456VisitFunctionTypeLoc(TL);457}458459void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {460VisitFunctionTypeLoc(TL);461}462463void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {464addSourceLocation(TL.getNameLoc());465}466467void TypeLocWriter::VisitUsingTypeLoc(UsingTypeLoc TL) {468addSourceLocation(TL.getNameLoc());469}470471void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {472addSourceLocation(TL.getNameLoc());473}474475void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {476if (TL.getNumProtocols()) {477addSourceLocation(TL.getProtocolLAngleLoc());478addSourceLocation(TL.getProtocolRAngleLoc());479}480for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)481addSourceLocation(TL.getProtocolLoc(i));482}483484void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {485addSourceLocation(TL.getTypeofLoc());486addSourceLocation(TL.getLParenLoc());487addSourceLocation(TL.getRParenLoc());488}489490void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {491addSourceLocation(TL.getTypeofLoc());492addSourceLocation(TL.getLParenLoc());493addSourceLocation(TL.getRParenLoc());494Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo());495}496497void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {498addSourceLocation(TL.getDecltypeLoc());499addSourceLocation(TL.getRParenLoc());500}501502void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {503addSourceLocation(TL.getKWLoc());504addSourceLocation(TL.getLParenLoc());505addSourceLocation(TL.getRParenLoc());506Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());507}508509void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) {510assert(CR);511AddNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc());512AddSourceLocation(CR->getTemplateKWLoc());513AddDeclarationNameInfo(CR->getConceptNameInfo());514AddDeclRef(CR->getFoundDecl());515AddDeclRef(CR->getNamedConcept());516push_back(CR->getTemplateArgsAsWritten() != nullptr);517if (CR->getTemplateArgsAsWritten())518AddASTTemplateArgumentListInfo(CR->getTemplateArgsAsWritten());519}520521void TypeLocWriter::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {522addSourceLocation(TL.getEllipsisLoc());523}524525void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {526addSourceLocation(TL.getNameLoc());527auto *CR = TL.getConceptReference();528Record.push_back(TL.isConstrained() && CR);529if (TL.isConstrained() && CR)530Record.AddConceptReference(CR);531Record.push_back(TL.isDecltypeAuto());532if (TL.isDecltypeAuto())533addSourceLocation(TL.getRParenLoc());534}535536void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(537DeducedTemplateSpecializationTypeLoc TL) {538addSourceLocation(TL.getTemplateNameLoc());539}540541void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {542addSourceLocation(TL.getNameLoc());543}544545void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) {546addSourceLocation(TL.getNameLoc());547}548549void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {550Record.AddAttr(TL.getAttr());551}552553void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) {554// Nothing to do555}556557void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {558// Nothing to do.559}560561void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {562addSourceLocation(TL.getNameLoc());563}564565void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(566SubstTemplateTypeParmTypeLoc TL) {567addSourceLocation(TL.getNameLoc());568}569570void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(571SubstTemplateTypeParmPackTypeLoc TL) {572addSourceLocation(TL.getNameLoc());573}574575void TypeLocWriter::VisitTemplateSpecializationTypeLoc(576TemplateSpecializationTypeLoc TL) {577addSourceLocation(TL.getTemplateKeywordLoc());578addSourceLocation(TL.getTemplateNameLoc());579addSourceLocation(TL.getLAngleLoc());580addSourceLocation(TL.getRAngleLoc());581for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)582Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i).getArgument().getKind(),583TL.getArgLoc(i).getLocInfo());584}585586void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {587addSourceLocation(TL.getLParenLoc());588addSourceLocation(TL.getRParenLoc());589}590591void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {592addSourceLocation(TL.getExpansionLoc());593}594595void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {596addSourceLocation(TL.getElaboratedKeywordLoc());597Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());598}599600void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {601addSourceLocation(TL.getNameLoc());602}603604void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {605addSourceLocation(TL.getElaboratedKeywordLoc());606Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());607addSourceLocation(TL.getNameLoc());608}609610void TypeLocWriter::VisitDependentTemplateSpecializationTypeLoc(611DependentTemplateSpecializationTypeLoc TL) {612addSourceLocation(TL.getElaboratedKeywordLoc());613Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());614addSourceLocation(TL.getTemplateKeywordLoc());615addSourceLocation(TL.getTemplateNameLoc());616addSourceLocation(TL.getLAngleLoc());617addSourceLocation(TL.getRAngleLoc());618for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)619Record.AddTemplateArgumentLocInfo(TL.getArgLoc(I).getArgument().getKind(),620TL.getArgLoc(I).getLocInfo());621}622623void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {624addSourceLocation(TL.getEllipsisLoc());625}626627void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {628addSourceLocation(TL.getNameLoc());629addSourceLocation(TL.getNameEndLoc());630}631632void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {633Record.push_back(TL.hasBaseTypeAsWritten());634addSourceLocation(TL.getTypeArgsLAngleLoc());635addSourceLocation(TL.getTypeArgsRAngleLoc());636for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)637Record.AddTypeSourceInfo(TL.getTypeArgTInfo(i));638addSourceLocation(TL.getProtocolLAngleLoc());639addSourceLocation(TL.getProtocolRAngleLoc());640for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)641addSourceLocation(TL.getProtocolLoc(i));642}643644void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {645addSourceLocation(TL.getStarLoc());646}647648void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {649addSourceLocation(TL.getKWLoc());650addSourceLocation(TL.getLParenLoc());651addSourceLocation(TL.getRParenLoc());652}653654void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {655addSourceLocation(TL.getKWLoc());656}657658void TypeLocWriter::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) {659addSourceLocation(TL.getNameLoc());660}661void TypeLocWriter::VisitDependentBitIntTypeLoc(662clang::DependentBitIntTypeLoc TL) {663addSourceLocation(TL.getNameLoc());664}665666void ASTWriter::WriteTypeAbbrevs() {667using namespace llvm;668669std::shared_ptr<BitCodeAbbrev> Abv;670671// Abbreviation for TYPE_EXT_QUAL672Abv = std::make_shared<BitCodeAbbrev>();673Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL));674Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type675Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3)); // Quals676TypeExtQualAbbrev = Stream.EmitAbbrev(std::move(Abv));677}678679//===----------------------------------------------------------------------===//680// ASTWriter Implementation681//===----------------------------------------------------------------------===//682683static void EmitBlockID(unsigned ID, const char *Name,684llvm::BitstreamWriter &Stream,685ASTWriter::RecordDataImpl &Record) {686Record.clear();687Record.push_back(ID);688Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);689690// Emit the block name if present.691if (!Name || Name[0] == 0)692return;693Record.clear();694while (*Name)695Record.push_back(*Name++);696Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);697}698699static void EmitRecordID(unsigned ID, const char *Name,700llvm::BitstreamWriter &Stream,701ASTWriter::RecordDataImpl &Record) {702Record.clear();703Record.push_back(ID);704while (*Name)705Record.push_back(*Name++);706Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);707}708709static void AddStmtsExprs(llvm::BitstreamWriter &Stream,710ASTWriter::RecordDataImpl &Record) {711#define RECORD(X) EmitRecordID(X, #X, Stream, Record)712RECORD(STMT_STOP);713RECORD(STMT_NULL_PTR);714RECORD(STMT_REF_PTR);715RECORD(STMT_NULL);716RECORD(STMT_COMPOUND);717RECORD(STMT_CASE);718RECORD(STMT_DEFAULT);719RECORD(STMT_LABEL);720RECORD(STMT_ATTRIBUTED);721RECORD(STMT_IF);722RECORD(STMT_SWITCH);723RECORD(STMT_WHILE);724RECORD(STMT_DO);725RECORD(STMT_FOR);726RECORD(STMT_GOTO);727RECORD(STMT_INDIRECT_GOTO);728RECORD(STMT_CONTINUE);729RECORD(STMT_BREAK);730RECORD(STMT_RETURN);731RECORD(STMT_DECL);732RECORD(STMT_GCCASM);733RECORD(STMT_MSASM);734RECORD(EXPR_PREDEFINED);735RECORD(EXPR_DECL_REF);736RECORD(EXPR_INTEGER_LITERAL);737RECORD(EXPR_FIXEDPOINT_LITERAL);738RECORD(EXPR_FLOATING_LITERAL);739RECORD(EXPR_IMAGINARY_LITERAL);740RECORD(EXPR_STRING_LITERAL);741RECORD(EXPR_CHARACTER_LITERAL);742RECORD(EXPR_PAREN);743RECORD(EXPR_PAREN_LIST);744RECORD(EXPR_UNARY_OPERATOR);745RECORD(EXPR_SIZEOF_ALIGN_OF);746RECORD(EXPR_ARRAY_SUBSCRIPT);747RECORD(EXPR_CALL);748RECORD(EXPR_MEMBER);749RECORD(EXPR_BINARY_OPERATOR);750RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);751RECORD(EXPR_CONDITIONAL_OPERATOR);752RECORD(EXPR_IMPLICIT_CAST);753RECORD(EXPR_CSTYLE_CAST);754RECORD(EXPR_COMPOUND_LITERAL);755RECORD(EXPR_EXT_VECTOR_ELEMENT);756RECORD(EXPR_INIT_LIST);757RECORD(EXPR_DESIGNATED_INIT);758RECORD(EXPR_DESIGNATED_INIT_UPDATE);759RECORD(EXPR_IMPLICIT_VALUE_INIT);760RECORD(EXPR_NO_INIT);761RECORD(EXPR_VA_ARG);762RECORD(EXPR_ADDR_LABEL);763RECORD(EXPR_STMT);764RECORD(EXPR_CHOOSE);765RECORD(EXPR_GNU_NULL);766RECORD(EXPR_SHUFFLE_VECTOR);767RECORD(EXPR_BLOCK);768RECORD(EXPR_GENERIC_SELECTION);769RECORD(EXPR_OBJC_STRING_LITERAL);770RECORD(EXPR_OBJC_BOXED_EXPRESSION);771RECORD(EXPR_OBJC_ARRAY_LITERAL);772RECORD(EXPR_OBJC_DICTIONARY_LITERAL);773RECORD(EXPR_OBJC_ENCODE);774RECORD(EXPR_OBJC_SELECTOR_EXPR);775RECORD(EXPR_OBJC_PROTOCOL_EXPR);776RECORD(EXPR_OBJC_IVAR_REF_EXPR);777RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);778RECORD(EXPR_OBJC_KVC_REF_EXPR);779RECORD(EXPR_OBJC_MESSAGE_EXPR);780RECORD(STMT_OBJC_FOR_COLLECTION);781RECORD(STMT_OBJC_CATCH);782RECORD(STMT_OBJC_FINALLY);783RECORD(STMT_OBJC_AT_TRY);784RECORD(STMT_OBJC_AT_SYNCHRONIZED);785RECORD(STMT_OBJC_AT_THROW);786RECORD(EXPR_OBJC_BOOL_LITERAL);787RECORD(STMT_CXX_CATCH);788RECORD(STMT_CXX_TRY);789RECORD(STMT_CXX_FOR_RANGE);790RECORD(EXPR_CXX_OPERATOR_CALL);791RECORD(EXPR_CXX_MEMBER_CALL);792RECORD(EXPR_CXX_REWRITTEN_BINARY_OPERATOR);793RECORD(EXPR_CXX_CONSTRUCT);794RECORD(EXPR_CXX_TEMPORARY_OBJECT);795RECORD(EXPR_CXX_STATIC_CAST);796RECORD(EXPR_CXX_DYNAMIC_CAST);797RECORD(EXPR_CXX_REINTERPRET_CAST);798RECORD(EXPR_CXX_CONST_CAST);799RECORD(EXPR_CXX_ADDRSPACE_CAST);800RECORD(EXPR_CXX_FUNCTIONAL_CAST);801RECORD(EXPR_USER_DEFINED_LITERAL);802RECORD(EXPR_CXX_STD_INITIALIZER_LIST);803RECORD(EXPR_CXX_BOOL_LITERAL);804RECORD(EXPR_CXX_PAREN_LIST_INIT);805RECORD(EXPR_CXX_NULL_PTR_LITERAL);806RECORD(EXPR_CXX_TYPEID_EXPR);807RECORD(EXPR_CXX_TYPEID_TYPE);808RECORD(EXPR_CXX_THIS);809RECORD(EXPR_CXX_THROW);810RECORD(EXPR_CXX_DEFAULT_ARG);811RECORD(EXPR_CXX_DEFAULT_INIT);812RECORD(EXPR_CXX_BIND_TEMPORARY);813RECORD(EXPR_CXX_SCALAR_VALUE_INIT);814RECORD(EXPR_CXX_NEW);815RECORD(EXPR_CXX_DELETE);816RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR);817RECORD(EXPR_EXPR_WITH_CLEANUPS);818RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER);819RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF);820RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);821RECORD(EXPR_CXX_UNRESOLVED_MEMBER);822RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);823RECORD(EXPR_CXX_EXPRESSION_TRAIT);824RECORD(EXPR_CXX_NOEXCEPT);825RECORD(EXPR_OPAQUE_VALUE);826RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR);827RECORD(EXPR_TYPE_TRAIT);828RECORD(EXPR_ARRAY_TYPE_TRAIT);829RECORD(EXPR_PACK_EXPANSION);830RECORD(EXPR_SIZEOF_PACK);831RECORD(EXPR_PACK_INDEXING);832RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM);833RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);834RECORD(EXPR_FUNCTION_PARM_PACK);835RECORD(EXPR_MATERIALIZE_TEMPORARY);836RECORD(EXPR_CUDA_KERNEL_CALL);837RECORD(EXPR_CXX_UUIDOF_EXPR);838RECORD(EXPR_CXX_UUIDOF_TYPE);839RECORD(EXPR_LAMBDA);840#undef RECORD841}842843void ASTWriter::WriteBlockInfoBlock() {844RecordData Record;845Stream.EnterBlockInfoBlock();846847#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)848#define RECORD(X) EmitRecordID(X, #X, Stream, Record)849850// Control Block.851BLOCK(CONTROL_BLOCK);852RECORD(METADATA);853RECORD(MODULE_NAME);854RECORD(MODULE_DIRECTORY);855RECORD(MODULE_MAP_FILE);856RECORD(IMPORTS);857RECORD(ORIGINAL_FILE);858RECORD(ORIGINAL_FILE_ID);859RECORD(INPUT_FILE_OFFSETS);860861BLOCK(OPTIONS_BLOCK);862RECORD(LANGUAGE_OPTIONS);863RECORD(TARGET_OPTIONS);864RECORD(FILE_SYSTEM_OPTIONS);865RECORD(HEADER_SEARCH_OPTIONS);866RECORD(PREPROCESSOR_OPTIONS);867868BLOCK(INPUT_FILES_BLOCK);869RECORD(INPUT_FILE);870RECORD(INPUT_FILE_HASH);871872// AST Top-Level Block.873BLOCK(AST_BLOCK);874RECORD(TYPE_OFFSET);875RECORD(DECL_OFFSET);876RECORD(IDENTIFIER_OFFSET);877RECORD(IDENTIFIER_TABLE);878RECORD(EAGERLY_DESERIALIZED_DECLS);879RECORD(MODULAR_CODEGEN_DECLS);880RECORD(SPECIAL_TYPES);881RECORD(STATISTICS);882RECORD(TENTATIVE_DEFINITIONS);883RECORD(SELECTOR_OFFSETS);884RECORD(METHOD_POOL);885RECORD(PP_COUNTER_VALUE);886RECORD(SOURCE_LOCATION_OFFSETS);887RECORD(EXT_VECTOR_DECLS);888RECORD(UNUSED_FILESCOPED_DECLS);889RECORD(PPD_ENTITIES_OFFSETS);890RECORD(VTABLE_USES);891RECORD(PPD_SKIPPED_RANGES);892RECORD(REFERENCED_SELECTOR_POOL);893RECORD(TU_UPDATE_LEXICAL);894RECORD(SEMA_DECL_REFS);895RECORD(WEAK_UNDECLARED_IDENTIFIERS);896RECORD(PENDING_IMPLICIT_INSTANTIATIONS);897RECORD(UPDATE_VISIBLE);898RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);899RECORD(DECL_UPDATE_OFFSETS);900RECORD(DECL_UPDATES);901RECORD(CUDA_SPECIAL_DECL_REFS);902RECORD(HEADER_SEARCH_TABLE);903RECORD(FP_PRAGMA_OPTIONS);904RECORD(OPENCL_EXTENSIONS);905RECORD(OPENCL_EXTENSION_TYPES);906RECORD(OPENCL_EXTENSION_DECLS);907RECORD(DELEGATING_CTORS);908RECORD(KNOWN_NAMESPACES);909RECORD(MODULE_OFFSET_MAP);910RECORD(SOURCE_MANAGER_LINE_TABLE);911RECORD(OBJC_CATEGORIES_MAP);912RECORD(FILE_SORTED_DECLS);913RECORD(IMPORTED_MODULES);914RECORD(OBJC_CATEGORIES);915RECORD(MACRO_OFFSET);916RECORD(INTERESTING_IDENTIFIERS);917RECORD(UNDEFINED_BUT_USED);918RECORD(LATE_PARSED_TEMPLATE);919RECORD(OPTIMIZE_PRAGMA_OPTIONS);920RECORD(MSSTRUCT_PRAGMA_OPTIONS);921RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);922RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);923RECORD(DELETE_EXPRS_TO_ANALYZE);924RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);925RECORD(PP_CONDITIONAL_STACK);926RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);927RECORD(PP_ASSUME_NONNULL_LOC);928RECORD(PP_UNSAFE_BUFFER_USAGE);929RECORD(VTABLES_TO_EMIT);930931// SourceManager Block.932BLOCK(SOURCE_MANAGER_BLOCK);933RECORD(SM_SLOC_FILE_ENTRY);934RECORD(SM_SLOC_BUFFER_ENTRY);935RECORD(SM_SLOC_BUFFER_BLOB);936RECORD(SM_SLOC_BUFFER_BLOB_COMPRESSED);937RECORD(SM_SLOC_EXPANSION_ENTRY);938939// Preprocessor Block.940BLOCK(PREPROCESSOR_BLOCK);941RECORD(PP_MACRO_DIRECTIVE_HISTORY);942RECORD(PP_MACRO_FUNCTION_LIKE);943RECORD(PP_MACRO_OBJECT_LIKE);944RECORD(PP_MODULE_MACRO);945RECORD(PP_TOKEN);946947// Submodule Block.948BLOCK(SUBMODULE_BLOCK);949RECORD(SUBMODULE_METADATA);950RECORD(SUBMODULE_DEFINITION);951RECORD(SUBMODULE_UMBRELLA_HEADER);952RECORD(SUBMODULE_HEADER);953RECORD(SUBMODULE_TOPHEADER);954RECORD(SUBMODULE_UMBRELLA_DIR);955RECORD(SUBMODULE_IMPORTS);956RECORD(SUBMODULE_AFFECTING_MODULES);957RECORD(SUBMODULE_EXPORTS);958RECORD(SUBMODULE_REQUIRES);959RECORD(SUBMODULE_EXCLUDED_HEADER);960RECORD(SUBMODULE_LINK_LIBRARY);961RECORD(SUBMODULE_CONFIG_MACRO);962RECORD(SUBMODULE_CONFLICT);963RECORD(SUBMODULE_PRIVATE_HEADER);964RECORD(SUBMODULE_TEXTUAL_HEADER);965RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);966RECORD(SUBMODULE_INITIALIZERS);967RECORD(SUBMODULE_EXPORT_AS);968969// Comments Block.970BLOCK(COMMENTS_BLOCK);971RECORD(COMMENTS_RAW_COMMENT);972973// Decls and Types block.974BLOCK(DECLTYPES_BLOCK);975RECORD(TYPE_EXT_QUAL);976RECORD(TYPE_COMPLEX);977RECORD(TYPE_POINTER);978RECORD(TYPE_BLOCK_POINTER);979RECORD(TYPE_LVALUE_REFERENCE);980RECORD(TYPE_RVALUE_REFERENCE);981RECORD(TYPE_MEMBER_POINTER);982RECORD(TYPE_CONSTANT_ARRAY);983RECORD(TYPE_INCOMPLETE_ARRAY);984RECORD(TYPE_VARIABLE_ARRAY);985RECORD(TYPE_VECTOR);986RECORD(TYPE_EXT_VECTOR);987RECORD(TYPE_FUNCTION_NO_PROTO);988RECORD(TYPE_FUNCTION_PROTO);989RECORD(TYPE_TYPEDEF);990RECORD(TYPE_TYPEOF_EXPR);991RECORD(TYPE_TYPEOF);992RECORD(TYPE_RECORD);993RECORD(TYPE_ENUM);994RECORD(TYPE_OBJC_INTERFACE);995RECORD(TYPE_OBJC_OBJECT_POINTER);996RECORD(TYPE_DECLTYPE);997RECORD(TYPE_ELABORATED);998RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM);999RECORD(TYPE_UNRESOLVED_USING);1000RECORD(TYPE_INJECTED_CLASS_NAME);1001RECORD(TYPE_OBJC_OBJECT);1002RECORD(TYPE_TEMPLATE_TYPE_PARM);1003RECORD(TYPE_TEMPLATE_SPECIALIZATION);1004RECORD(TYPE_DEPENDENT_NAME);1005RECORD(TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION);1006RECORD(TYPE_DEPENDENT_SIZED_ARRAY);1007RECORD(TYPE_PAREN);1008RECORD(TYPE_MACRO_QUALIFIED);1009RECORD(TYPE_PACK_EXPANSION);1010RECORD(TYPE_ATTRIBUTED);1011RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);1012RECORD(TYPE_AUTO);1013RECORD(TYPE_UNARY_TRANSFORM);1014RECORD(TYPE_ATOMIC);1015RECORD(TYPE_DECAYED);1016RECORD(TYPE_ADJUSTED);1017RECORD(TYPE_OBJC_TYPE_PARAM);1018RECORD(LOCAL_REDECLARATIONS);1019RECORD(DECL_TYPEDEF);1020RECORD(DECL_TYPEALIAS);1021RECORD(DECL_ENUM);1022RECORD(DECL_RECORD);1023RECORD(DECL_ENUM_CONSTANT);1024RECORD(DECL_FUNCTION);1025RECORD(DECL_OBJC_METHOD);1026RECORD(DECL_OBJC_INTERFACE);1027RECORD(DECL_OBJC_PROTOCOL);1028RECORD(DECL_OBJC_IVAR);1029RECORD(DECL_OBJC_AT_DEFS_FIELD);1030RECORD(DECL_OBJC_CATEGORY);1031RECORD(DECL_OBJC_CATEGORY_IMPL);1032RECORD(DECL_OBJC_IMPLEMENTATION);1033RECORD(DECL_OBJC_COMPATIBLE_ALIAS);1034RECORD(DECL_OBJC_PROPERTY);1035RECORD(DECL_OBJC_PROPERTY_IMPL);1036RECORD(DECL_FIELD);1037RECORD(DECL_MS_PROPERTY);1038RECORD(DECL_VAR);1039RECORD(DECL_IMPLICIT_PARAM);1040RECORD(DECL_PARM_VAR);1041RECORD(DECL_FILE_SCOPE_ASM);1042RECORD(DECL_BLOCK);1043RECORD(DECL_CONTEXT_LEXICAL);1044RECORD(DECL_CONTEXT_VISIBLE);1045RECORD(DECL_NAMESPACE);1046RECORD(DECL_NAMESPACE_ALIAS);1047RECORD(DECL_USING);1048RECORD(DECL_USING_SHADOW);1049RECORD(DECL_USING_DIRECTIVE);1050RECORD(DECL_UNRESOLVED_USING_VALUE);1051RECORD(DECL_UNRESOLVED_USING_TYPENAME);1052RECORD(DECL_LINKAGE_SPEC);1053RECORD(DECL_EXPORT);1054RECORD(DECL_CXX_RECORD);1055RECORD(DECL_CXX_METHOD);1056RECORD(DECL_CXX_CONSTRUCTOR);1057RECORD(DECL_CXX_DESTRUCTOR);1058RECORD(DECL_CXX_CONVERSION);1059RECORD(DECL_ACCESS_SPEC);1060RECORD(DECL_FRIEND);1061RECORD(DECL_FRIEND_TEMPLATE);1062RECORD(DECL_CLASS_TEMPLATE);1063RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);1064RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);1065RECORD(DECL_VAR_TEMPLATE);1066RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION);1067RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION);1068RECORD(DECL_FUNCTION_TEMPLATE);1069RECORD(DECL_TEMPLATE_TYPE_PARM);1070RECORD(DECL_NON_TYPE_TEMPLATE_PARM);1071RECORD(DECL_TEMPLATE_TEMPLATE_PARM);1072RECORD(DECL_CONCEPT);1073RECORD(DECL_REQUIRES_EXPR_BODY);1074RECORD(DECL_TYPE_ALIAS_TEMPLATE);1075RECORD(DECL_STATIC_ASSERT);1076RECORD(DECL_CXX_BASE_SPECIFIERS);1077RECORD(DECL_CXX_CTOR_INITIALIZERS);1078RECORD(DECL_INDIRECTFIELD);1079RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);1080RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK);1081RECORD(DECL_IMPORT);1082RECORD(DECL_OMP_THREADPRIVATE);1083RECORD(DECL_EMPTY);1084RECORD(DECL_OBJC_TYPE_PARAM);1085RECORD(DECL_OMP_CAPTUREDEXPR);1086RECORD(DECL_PRAGMA_COMMENT);1087RECORD(DECL_PRAGMA_DETECT_MISMATCH);1088RECORD(DECL_OMP_DECLARE_REDUCTION);1089RECORD(DECL_OMP_ALLOCATE);1090RECORD(DECL_HLSL_BUFFER);10911092// Statements and Exprs can occur in the Decls and Types block.1093AddStmtsExprs(Stream, Record);10941095BLOCK(PREPROCESSOR_DETAIL_BLOCK);1096RECORD(PPD_MACRO_EXPANSION);1097RECORD(PPD_MACRO_DEFINITION);1098RECORD(PPD_INCLUSION_DIRECTIVE);10991100// Decls and Types block.1101BLOCK(EXTENSION_BLOCK);1102RECORD(EXTENSION_METADATA);11031104BLOCK(UNHASHED_CONTROL_BLOCK);1105RECORD(SIGNATURE);1106RECORD(AST_BLOCK_HASH);1107RECORD(DIAGNOSTIC_OPTIONS);1108RECORD(HEADER_SEARCH_PATHS);1109RECORD(DIAG_PRAGMA_MAPPINGS);11101111#undef RECORD1112#undef BLOCK1113Stream.ExitBlock();1114}11151116/// Prepares a path for being written to an AST file by converting it1117/// to an absolute path and removing nested './'s.1118///1119/// \return \c true if the path was changed.1120static bool cleanPathForOutput(FileManager &FileMgr,1121SmallVectorImpl<char> &Path) {1122bool Changed = FileMgr.makeAbsolutePath(Path);1123return Changed | llvm::sys::path::remove_dots(Path);1124}11251126/// Adjusts the given filename to only write out the portion of the1127/// filename that is not part of the system root directory.1128///1129/// \param Filename the file name to adjust.1130///1131/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and1132/// the returned filename will be adjusted by this root directory.1133///1134/// \returns either the original filename (if it needs no adjustment) or the1135/// adjusted filename (which points into the @p Filename parameter).1136static const char *1137adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {1138assert(Filename && "No file name to adjust?");11391140if (BaseDir.empty())1141return Filename;11421143// Verify that the filename and the system root have the same prefix.1144unsigned Pos = 0;1145for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)1146if (Filename[Pos] != BaseDir[Pos])1147return Filename; // Prefixes don't match.11481149// We hit the end of the filename before we hit the end of the system root.1150if (!Filename[Pos])1151return Filename;11521153// If there's not a path separator at the end of the base directory nor1154// immediately after it, then this isn't within the base directory.1155if (!llvm::sys::path::is_separator(Filename[Pos])) {1156if (!llvm::sys::path::is_separator(BaseDir.back()))1157return Filename;1158} else {1159// If the file name has a '/' at the current position, skip over the '/'.1160// We distinguish relative paths from absolute paths by the1161// absence of '/' at the beginning of relative paths.1162//1163// FIXME: This is wrong. We distinguish them by asking if the path is1164// absolute, which isn't the same thing. And there might be multiple '/'s1165// in a row. Use a better mechanism to indicate whether we have emitted an1166// absolute or relative path.1167++Pos;1168}11691170return Filename + Pos;1171}11721173std::pair<ASTFileSignature, ASTFileSignature>1174ASTWriter::createSignature() const {1175StringRef AllBytes(Buffer.data(), Buffer.size());11761177llvm::SHA1 Hasher;1178Hasher.update(AllBytes.slice(ASTBlockRange.first, ASTBlockRange.second));1179ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hasher.result());11801181// Add the remaining bytes:1182// 1. Before the unhashed control block.1183Hasher.update(AllBytes.slice(0, UnhashedControlBlockRange.first));1184// 2. Between the unhashed control block and the AST block.1185Hasher.update(1186AllBytes.slice(UnhashedControlBlockRange.second, ASTBlockRange.first));1187// 3. After the AST block.1188Hasher.update(AllBytes.slice(ASTBlockRange.second, StringRef::npos));1189ASTFileSignature Signature = ASTFileSignature::create(Hasher.result());11901191return std::make_pair(ASTBlockHash, Signature);1192}11931194ASTFileSignature ASTWriter::createSignatureForNamedModule() const {1195llvm::SHA1 Hasher;1196Hasher.update(StringRef(Buffer.data(), Buffer.size()));11971198assert(WritingModule);1199assert(WritingModule->isNamedModule());12001201// We need to combine all the export imported modules no matter1202// we used it or not.1203for (auto [ExportImported, _] : WritingModule->Exports)1204Hasher.update(ExportImported->Signature);12051206// We combine all the used modules to make sure the signature is precise.1207// Consider the case like:1208//1209// // a.cppm1210// export module a;1211// export inline int a() { ... }1212//1213// // b.cppm1214// export module b;1215// import a;1216// export inline int b() { return a(); }1217//1218// Since both `a()` and `b()` are inline, we need to make sure the BMI of1219// `b.pcm` will change after the implementation of `a()` changes. We can't1220// get that naturally since we won't record the body of `a()` during the1221// writing process. We can't reuse ODRHash here since ODRHash won't calculate1222// the called function recursively. So ODRHash will be problematic if `a()`1223// calls other inline functions.1224//1225// Probably we can solve this by a new hash mechanism. But the safety and1226// efficiency may a problem too. Here we just combine the hash value of the1227// used modules conservatively.1228for (Module *M : TouchedTopLevelModules)1229Hasher.update(M->Signature);12301231return ASTFileSignature::create(Hasher.result());1232}12331234static void BackpatchSignatureAt(llvm::BitstreamWriter &Stream,1235const ASTFileSignature &S, uint64_t BitNo) {1236for (uint8_t Byte : S) {1237Stream.BackpatchByte(BitNo, Byte);1238BitNo += 8;1239}1240}12411242ASTFileSignature ASTWriter::backpatchSignature() {1243if (isWritingStdCXXNamedModules()) {1244ASTFileSignature Signature = createSignatureForNamedModule();1245BackpatchSignatureAt(Stream, Signature, SignatureOffset);1246return Signature;1247}12481249if (!WritingModule ||1250!PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)1251return {};12521253// For implicit modules, write the hash of the PCM as its signature.1254ASTFileSignature ASTBlockHash;1255ASTFileSignature Signature;1256std::tie(ASTBlockHash, Signature) = createSignature();12571258BackpatchSignatureAt(Stream, ASTBlockHash, ASTBlockHashOffset);1259BackpatchSignatureAt(Stream, Signature, SignatureOffset);12601261return Signature;1262}12631264void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP,1265ASTContext &Context) {1266using namespace llvm;12671268// Flush first to prepare the PCM hash (signature).1269Stream.FlushToWord();1270UnhashedControlBlockRange.first = Stream.GetCurrentBitNo() >> 3;12711272// Enter the block and prepare to write records.1273RecordData Record;1274Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5);12751276// For implicit modules and C++20 named modules, write the hash of the PCM as1277// its signature.1278if (isWritingStdCXXNamedModules() ||1279(WritingModule &&1280PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)) {1281// At this point, we don't know the actual signature of the file or the AST1282// block - we're only able to compute those at the end of the serialization1283// process. Let's store dummy signatures for now, and replace them with the1284// real ones later on.1285// The bitstream VBR-encodes record elements, which makes backpatching them1286// really difficult. Let's store the signatures as blobs instead - they are1287// guaranteed to be word-aligned, and we control their format/encoding.1288auto Dummy = ASTFileSignature::createDummy();1289SmallString<128> Blob{Dummy.begin(), Dummy.end()};12901291// We don't need AST Block hash in named modules.1292if (!isWritingStdCXXNamedModules()) {1293auto Abbrev = std::make_shared<BitCodeAbbrev>();1294Abbrev->Add(BitCodeAbbrevOp(AST_BLOCK_HASH));1295Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));1296unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev(std::move(Abbrev));12971298Record.push_back(AST_BLOCK_HASH);1299Stream.EmitRecordWithBlob(ASTBlockHashAbbrev, Record, Blob);1300ASTBlockHashOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;1301Record.clear();1302}13031304auto Abbrev = std::make_shared<BitCodeAbbrev>();1305Abbrev->Add(BitCodeAbbrevOp(SIGNATURE));1306Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));1307unsigned SignatureAbbrev = Stream.EmitAbbrev(std::move(Abbrev));13081309Record.push_back(SIGNATURE);1310Stream.EmitRecordWithBlob(SignatureAbbrev, Record, Blob);1311SignatureOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;1312Record.clear();1313}13141315const auto &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();13161317// Diagnostic options.1318const auto &Diags = Context.getDiagnostics();1319const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();1320if (!HSOpts.ModulesSkipDiagnosticOptions) {1321#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name);1322#define ENUM_DIAGOPT(Name, Type, Bits, Default) \1323Record.push_back(static_cast<unsigned>(DiagOpts.get##Name()));1324#include "clang/Basic/DiagnosticOptions.def"1325Record.push_back(DiagOpts.Warnings.size());1326for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I)1327AddString(DiagOpts.Warnings[I], Record);1328Record.push_back(DiagOpts.Remarks.size());1329for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I)1330AddString(DiagOpts.Remarks[I], Record);1331// Note: we don't serialize the log or serialization file names, because1332// they are generally transient files and will almost always be overridden.1333Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record);1334Record.clear();1335}13361337// Header search paths.1338if (!HSOpts.ModulesSkipHeaderSearchPaths) {1339// Include entries.1340Record.push_back(HSOpts.UserEntries.size());1341for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) {1342const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I];1343AddString(Entry.Path, Record);1344Record.push_back(static_cast<unsigned>(Entry.Group));1345Record.push_back(Entry.IsFramework);1346Record.push_back(Entry.IgnoreSysRoot);1347}13481349// System header prefixes.1350Record.push_back(HSOpts.SystemHeaderPrefixes.size());1351for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) {1352AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record);1353Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader);1354}13551356// VFS overlay files.1357Record.push_back(HSOpts.VFSOverlayFiles.size());1358for (StringRef VFSOverlayFile : HSOpts.VFSOverlayFiles)1359AddString(VFSOverlayFile, Record);13601361Stream.EmitRecord(HEADER_SEARCH_PATHS, Record);1362}13631364if (!HSOpts.ModulesSkipPragmaDiagnosticMappings)1365WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule);13661367// Header search entry usage.1368{1369auto HSEntryUsage = PP.getHeaderSearchInfo().computeUserEntryUsage();1370auto Abbrev = std::make_shared<BitCodeAbbrev>();1371Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_ENTRY_USAGE));1372Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.1373Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector.1374unsigned HSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1375RecordData::value_type Record[] = {HEADER_SEARCH_ENTRY_USAGE,1376HSEntryUsage.size()};1377Stream.EmitRecordWithBlob(HSUsageAbbrevCode, Record, bytes(HSEntryUsage));1378}13791380// VFS usage.1381{1382auto VFSUsage = PP.getHeaderSearchInfo().collectVFSUsageAndClear();1383auto Abbrev = std::make_shared<BitCodeAbbrev>();1384Abbrev->Add(BitCodeAbbrevOp(VFS_USAGE));1385Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.1386Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Bit vector.1387unsigned VFSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1388RecordData::value_type Record[] = {VFS_USAGE, VFSUsage.size()};1389Stream.EmitRecordWithBlob(VFSUsageAbbrevCode, Record, bytes(VFSUsage));1390}13911392// Leave the options block.1393Stream.ExitBlock();1394UnhashedControlBlockRange.second = Stream.GetCurrentBitNo() >> 3;1395}13961397/// Write the control block.1398void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,1399StringRef isysroot) {1400using namespace llvm;14011402Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);1403RecordData Record;14041405// Metadata1406auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>();1407MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));1408MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major1409MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor1410MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj.1411MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.1412MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable1413// Standard C++ module1414MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));1415MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps1416MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors1417MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag1418unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev));1419assert((!WritingModule || isysroot.empty()) &&1420"writing module as a relocatable PCH?");1421{1422RecordData::value_type Record[] = {METADATA,1423VERSION_MAJOR,1424VERSION_MINOR,1425CLANG_VERSION_MAJOR,1426CLANG_VERSION_MINOR,1427!isysroot.empty(),1428isWritingStdCXXNamedModules(),1429IncludeTimestamps,1430ASTHasCompilerErrors};1431Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,1432getClangFullRepositoryVersion());1433}14341435if (WritingModule) {1436// Module name1437auto Abbrev = std::make_shared<BitCodeAbbrev>();1438Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));1439Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name1440unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));1441RecordData::value_type Record[] = {MODULE_NAME};1442Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);1443}14441445if (WritingModule && WritingModule->Directory) {1446SmallString<128> BaseDir;1447if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) {1448// Use the current working directory as the base path for all inputs.1449auto CWD =1450Context.getSourceManager().getFileManager().getOptionalDirectoryRef(1451".");1452BaseDir.assign(CWD->getName());1453} else {1454BaseDir.assign(WritingModule->Directory->getName());1455}1456cleanPathForOutput(Context.getSourceManager().getFileManager(), BaseDir);14571458// If the home of the module is the current working directory, then we1459// want to pick up the cwd of the build process loading the module, not1460// our cwd, when we load this module.1461if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd &&1462(!PP.getHeaderSearchInfo()1463.getHeaderSearchOpts()1464.ModuleMapFileHomeIsCwd ||1465WritingModule->Directory->getName() != ".")) {1466// Module directory.1467auto Abbrev = std::make_shared<BitCodeAbbrev>();1468Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));1469Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory1470unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));14711472RecordData::value_type Record[] = {MODULE_DIRECTORY};1473Stream.EmitRecordWithBlob(AbbrevCode, Record, BaseDir);1474}14751476// Write out all other paths relative to the base directory if possible.1477BaseDirectory.assign(BaseDir.begin(), BaseDir.end());1478} else if (!isysroot.empty()) {1479// Write out paths relative to the sysroot if possible.1480BaseDirectory = std::string(isysroot);1481}14821483// Module map file1484if (WritingModule && WritingModule->Kind == Module::ModuleMapModule) {1485Record.clear();14861487auto &Map = PP.getHeaderSearchInfo().getModuleMap();1488AddPath(WritingModule->PresumedModuleMapFile.empty()1489? Map.getModuleMapFileForUniquing(WritingModule)1490->getNameAsRequested()1491: StringRef(WritingModule->PresumedModuleMapFile),1492Record);14931494// Additional module map files.1495if (auto *AdditionalModMaps =1496Map.getAdditionalModuleMapFiles(WritingModule)) {1497Record.push_back(AdditionalModMaps->size());1498SmallVector<FileEntryRef, 1> ModMaps(AdditionalModMaps->begin(),1499AdditionalModMaps->end());1500llvm::sort(ModMaps, [](FileEntryRef A, FileEntryRef B) {1501return A.getName() < B.getName();1502});1503for (FileEntryRef F : ModMaps)1504AddPath(F.getName(), Record);1505} else {1506Record.push_back(0);1507}15081509Stream.EmitRecord(MODULE_MAP_FILE, Record);1510}15111512// Imports1513if (Chain) {1514serialization::ModuleManager &Mgr = Chain->getModuleManager();1515Record.clear();15161517for (ModuleFile &M : Mgr) {1518// Skip modules that weren't directly imported.1519if (!M.isDirectlyImported())1520continue;15211522Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding1523Record.push_back(M.StandardCXXModule);1524AddSourceLocation(M.ImportLoc, Record);15251526// We don't want to hard code the information about imported modules1527// in the C++20 named modules.1528if (!M.StandardCXXModule) {1529// If we have calculated signature, there is no need to store1530// the size or timestamp.1531Record.push_back(M.Signature ? 0 : M.File.getSize());1532Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File));1533llvm::append_range(Record, M.Signature);1534}15351536AddString(M.ModuleName, Record);15371538if (!M.StandardCXXModule)1539AddPath(M.FileName, Record);1540}1541Stream.EmitRecord(IMPORTS, Record);1542}15431544// Write the options block.1545Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4);15461547// Language options.1548Record.clear();1549const LangOptions &LangOpts = Context.getLangOpts();1550#define LANGOPT(Name, Bits, Default, Description) \1551Record.push_back(LangOpts.Name);1552#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \1553Record.push_back(static_cast<unsigned>(LangOpts.get##Name()));1554#include "clang/Basic/LangOptions.def"1555#define SANITIZER(NAME, ID) \1556Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID));1557#include "clang/Basic/Sanitizers.def"15581559Record.push_back(LangOpts.ModuleFeatures.size());1560for (StringRef Feature : LangOpts.ModuleFeatures)1561AddString(Feature, Record);15621563Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());1564AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);15651566AddString(LangOpts.CurrentModule, Record);15671568// Comment options.1569Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size());1570for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) {1571AddString(I, Record);1572}1573Record.push_back(LangOpts.CommentOpts.ParseAllComments);15741575// OpenMP offloading options.1576Record.push_back(LangOpts.OMPTargetTriples.size());1577for (auto &T : LangOpts.OMPTargetTriples)1578AddString(T.getTriple(), Record);15791580AddString(LangOpts.OMPHostIRFile, Record);15811582Stream.EmitRecord(LANGUAGE_OPTIONS, Record);15831584// Target options.1585Record.clear();1586const TargetInfo &Target = Context.getTargetInfo();1587const TargetOptions &TargetOpts = Target.getTargetOpts();1588AddString(TargetOpts.Triple, Record);1589AddString(TargetOpts.CPU, Record);1590AddString(TargetOpts.TuneCPU, Record);1591AddString(TargetOpts.ABI, Record);1592Record.push_back(TargetOpts.FeaturesAsWritten.size());1593for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {1594AddString(TargetOpts.FeaturesAsWritten[I], Record);1595}1596Record.push_back(TargetOpts.Features.size());1597for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) {1598AddString(TargetOpts.Features[I], Record);1599}1600Stream.EmitRecord(TARGET_OPTIONS, Record);16011602// File system options.1603Record.clear();1604const FileSystemOptions &FSOpts =1605Context.getSourceManager().getFileManager().getFileSystemOpts();1606AddString(FSOpts.WorkingDir, Record);1607Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record);16081609// Header search options.1610Record.clear();1611const HeaderSearchOptions &HSOpts =1612PP.getHeaderSearchInfo().getHeaderSearchOpts();16131614AddString(HSOpts.Sysroot, Record);1615AddString(HSOpts.ResourceDir, Record);1616AddString(HSOpts.ModuleCachePath, Record);1617AddString(HSOpts.ModuleUserBuildPath, Record);1618Record.push_back(HSOpts.DisableModuleHash);1619Record.push_back(HSOpts.ImplicitModuleMaps);1620Record.push_back(HSOpts.ModuleMapFileHomeIsCwd);1621Record.push_back(HSOpts.EnablePrebuiltImplicitModules);1622Record.push_back(HSOpts.UseBuiltinIncludes);1623Record.push_back(HSOpts.UseStandardSystemIncludes);1624Record.push_back(HSOpts.UseStandardCXXIncludes);1625Record.push_back(HSOpts.UseLibcxx);1626// Write out the specific module cache path that contains the module files.1627AddString(PP.getHeaderSearchInfo().getModuleCachePath(), Record);1628Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);16291630// Preprocessor options.1631Record.clear();1632const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts();16331634// If we're building an implicit module with a context hash, the importer is1635// guaranteed to have the same macros defined on the command line. Skip1636// writing them.1637bool SkipMacros = BuildingImplicitModule && !HSOpts.DisableModuleHash;1638bool WriteMacros = !SkipMacros;1639Record.push_back(WriteMacros);1640if (WriteMacros) {1641// Macro definitions.1642Record.push_back(PPOpts.Macros.size());1643for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {1644AddString(PPOpts.Macros[I].first, Record);1645Record.push_back(PPOpts.Macros[I].second);1646}1647}16481649// Includes1650Record.push_back(PPOpts.Includes.size());1651for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I)1652AddString(PPOpts.Includes[I], Record);16531654// Macro includes1655Record.push_back(PPOpts.MacroIncludes.size());1656for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I)1657AddString(PPOpts.MacroIncludes[I], Record);16581659Record.push_back(PPOpts.UsePredefines);1660// Detailed record is important since it is used for the module cache hash.1661Record.push_back(PPOpts.DetailedRecord);1662AddString(PPOpts.ImplicitPCHInclude, Record);1663Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary));1664Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record);16651666// Leave the options block.1667Stream.ExitBlock();16681669// Original file name and file ID1670SourceManager &SM = Context.getSourceManager();1671if (auto MainFile = SM.getFileEntryRefForID(SM.getMainFileID())) {1672auto FileAbbrev = std::make_shared<BitCodeAbbrev>();1673FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE));1674FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID1675FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name1676unsigned FileAbbrevCode = Stream.EmitAbbrev(std::move(FileAbbrev));16771678Record.clear();1679Record.push_back(ORIGINAL_FILE);1680AddFileID(SM.getMainFileID(), Record);1681EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName());1682}16831684Record.clear();1685AddFileID(SM.getMainFileID(), Record);1686Stream.EmitRecord(ORIGINAL_FILE_ID, Record);16871688WriteInputFiles(Context.SourceMgr,1689PP.getHeaderSearchInfo().getHeaderSearchOpts());1690Stream.ExitBlock();1691}16921693namespace {16941695/// An input file.1696struct InputFileEntry {1697FileEntryRef File;1698bool IsSystemFile;1699bool IsTransient;1700bool BufferOverridden;1701bool IsTopLevel;1702bool IsModuleMap;1703uint32_t ContentHash[2];17041705InputFileEntry(FileEntryRef File) : File(File) {}1706};17071708} // namespace17091710SourceLocation ASTWriter::getAffectingIncludeLoc(const SourceManager &SourceMgr,1711const SrcMgr::FileInfo &File) {1712SourceLocation IncludeLoc = File.getIncludeLoc();1713if (IncludeLoc.isValid()) {1714FileID IncludeFID = SourceMgr.getFileID(IncludeLoc);1715assert(IncludeFID.isValid() && "IncludeLoc in invalid file");1716if (!IsSLocAffecting[IncludeFID.ID])1717IncludeLoc = SourceLocation();1718}1719return IncludeLoc;1720}17211722void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,1723HeaderSearchOptions &HSOpts) {1724using namespace llvm;17251726Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);17271728// Create input-file abbreviation.1729auto IFAbbrev = std::make_shared<BitCodeAbbrev>();1730IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE));1731IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID1732IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size1733IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time1734IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden1735IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient1736IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Top-level1737IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map1738IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Name as req. len1739IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name as req. + name1740unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev));17411742// Create input file hash abbreviation.1743auto IFHAbbrev = std::make_shared<BitCodeAbbrev>();1744IFHAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_HASH));1745IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));1746IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));1747unsigned IFHAbbrevCode = Stream.EmitAbbrev(std::move(IFHAbbrev));17481749uint64_t InputFilesOffsetBase = Stream.GetCurrentBitNo();17501751// Get all ContentCache objects for files.1752std::vector<InputFileEntry> UserFiles;1753std::vector<InputFileEntry> SystemFiles;1754for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) {1755// Get this source location entry.1756const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);1757assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc);17581759// We only care about file entries that were not overridden.1760if (!SLoc->isFile())1761continue;1762const SrcMgr::FileInfo &File = SLoc->getFile();1763const SrcMgr::ContentCache *Cache = &File.getContentCache();1764if (!Cache->OrigEntry)1765continue;17661767// Do not emit input files that do not affect current module.1768if (!IsSLocAffecting[I])1769continue;17701771InputFileEntry Entry(*Cache->OrigEntry);1772Entry.IsSystemFile = isSystem(File.getFileCharacteristic());1773Entry.IsTransient = Cache->IsTransient;1774Entry.BufferOverridden = Cache->BufferOverridden;1775Entry.IsTopLevel = getAffectingIncludeLoc(SourceMgr, File).isInvalid();1776Entry.IsModuleMap = isModuleMap(File.getFileCharacteristic());17771778uint64_t ContentHash = 0;1779if (PP->getHeaderSearchInfo()1780.getHeaderSearchOpts()1781.ValidateASTInputFilesContent) {1782auto MemBuff = Cache->getBufferIfLoaded();1783if (MemBuff)1784ContentHash = xxh3_64bits(MemBuff->getBuffer());1785else1786PP->Diag(SourceLocation(), diag::err_module_unable_to_hash_content)1787<< Entry.File.getName();1788}1789Entry.ContentHash[0] = uint32_t(ContentHash);1790Entry.ContentHash[1] = uint32_t(ContentHash >> 32);1791if (Entry.IsSystemFile)1792SystemFiles.push_back(Entry);1793else1794UserFiles.push_back(Entry);1795}17961797// User files go at the front, system files at the back.1798auto SortedFiles = llvm::concat<InputFileEntry>(std::move(UserFiles),1799std::move(SystemFiles));18001801unsigned UserFilesNum = 0;1802// Write out all of the input files.1803std::vector<uint64_t> InputFileOffsets;1804for (const auto &Entry : SortedFiles) {1805uint32_t &InputFileID = InputFileIDs[Entry.File];1806if (InputFileID != 0)1807continue; // already recorded this file.18081809// Record this entry's offset.1810InputFileOffsets.push_back(Stream.GetCurrentBitNo() - InputFilesOffsetBase);18111812InputFileID = InputFileOffsets.size();18131814if (!Entry.IsSystemFile)1815++UserFilesNum;18161817// Emit size/modification time for this file.1818// And whether this file was overridden.1819{1820SmallString<128> NameAsRequested = Entry.File.getNameAsRequested();1821SmallString<128> Name = Entry.File.getName();18221823PreparePathForOutput(NameAsRequested);1824PreparePathForOutput(Name);18251826if (Name == NameAsRequested)1827Name.clear();18281829RecordData::value_type Record[] = {1830INPUT_FILE,1831InputFileOffsets.size(),1832(uint64_t)Entry.File.getSize(),1833(uint64_t)getTimestampForOutput(Entry.File),1834Entry.BufferOverridden,1835Entry.IsTransient,1836Entry.IsTopLevel,1837Entry.IsModuleMap,1838NameAsRequested.size()};18391840Stream.EmitRecordWithBlob(IFAbbrevCode, Record,1841(NameAsRequested + Name).str());1842}18431844// Emit content hash for this file.1845{1846RecordData::value_type Record[] = {INPUT_FILE_HASH, Entry.ContentHash[0],1847Entry.ContentHash[1]};1848Stream.EmitRecordWithAbbrev(IFHAbbrevCode, Record);1849}1850}18511852Stream.ExitBlock();18531854// Create input file offsets abbreviation.1855auto OffsetsAbbrev = std::make_shared<BitCodeAbbrev>();1856OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS));1857OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files1858OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system1859// input files1860OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Array1861unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(std::move(OffsetsAbbrev));18621863// Write input file offsets.1864RecordData::value_type Record[] = {INPUT_FILE_OFFSETS,1865InputFileOffsets.size(), UserFilesNum};1866Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));1867}18681869//===----------------------------------------------------------------------===//1870// Source Manager Serialization1871//===----------------------------------------------------------------------===//18721873/// Create an abbreviation for the SLocEntry that refers to a1874/// file.1875static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {1876using namespace llvm;18771878auto Abbrev = std::make_shared<BitCodeAbbrev>();1879Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));1880Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset1881Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location1882Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic1883Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives1884// FileEntry fields.1885Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID1886Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs1887Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex1888Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls1889return Stream.EmitAbbrev(std::move(Abbrev));1890}18911892/// Create an abbreviation for the SLocEntry that refers to a1893/// buffer.1894static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {1895using namespace llvm;18961897auto Abbrev = std::make_shared<BitCodeAbbrev>();1898Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));1899Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset1900Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location1901Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic1902Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives1903Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob1904return Stream.EmitAbbrev(std::move(Abbrev));1905}19061907/// Create an abbreviation for the SLocEntry that refers to a1908/// buffer's blob.1909static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream,1910bool Compressed) {1911using namespace llvm;19121913auto Abbrev = std::make_shared<BitCodeAbbrev>();1914Abbrev->Add(BitCodeAbbrevOp(Compressed ? SM_SLOC_BUFFER_BLOB_COMPRESSED1915: SM_SLOC_BUFFER_BLOB));1916if (Compressed)1917Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Uncompressed size1918Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob1919return Stream.EmitAbbrev(std::move(Abbrev));1920}19211922/// Create an abbreviation for the SLocEntry that refers to a macro1923/// expansion.1924static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {1925using namespace llvm;19261927auto Abbrev = std::make_shared<BitCodeAbbrev>();1928Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY));1929Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset1930Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location1931Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Start location1932Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // End location1933Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range1934Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length1935return Stream.EmitAbbrev(std::move(Abbrev));1936}19371938/// Emit key length and data length as ULEB-encoded data, and return them as a1939/// pair.1940static std::pair<unsigned, unsigned>1941emitULEBKeyDataLength(unsigned KeyLen, unsigned DataLen, raw_ostream &Out) {1942llvm::encodeULEB128(KeyLen, Out);1943llvm::encodeULEB128(DataLen, Out);1944return std::make_pair(KeyLen, DataLen);1945}19461947namespace {19481949// Trait used for the on-disk hash table of header search information.1950class HeaderFileInfoTrait {1951ASTWriter &Writer;19521953// Keep track of the framework names we've used during serialization.1954SmallString<128> FrameworkStringData;1955llvm::StringMap<unsigned> FrameworkNameOffset;19561957public:1958HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}19591960struct key_type {1961StringRef Filename;1962off_t Size;1963time_t ModTime;1964};1965using key_type_ref = const key_type &;19661967using UnresolvedModule =1968llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;19691970struct data_type {1971data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded,1972ArrayRef<ModuleMap::KnownHeader> KnownHeaders,1973UnresolvedModule Unresolved)1974: HFI(HFI), AlreadyIncluded(AlreadyIncluded),1975KnownHeaders(KnownHeaders), Unresolved(Unresolved) {}19761977HeaderFileInfo HFI;1978bool AlreadyIncluded;1979SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders;1980UnresolvedModule Unresolved;1981};1982using data_type_ref = const data_type &;19831984using hash_value_type = unsigned;1985using offset_type = unsigned;19861987hash_value_type ComputeHash(key_type_ref key) {1988// The hash is based only on size/time of the file, so that the reader can1989// match even when symlinking or excess path elements ("foo/../", "../")1990// change the form of the name. However, complete path is still the key.1991uint8_t buf[sizeof(key.Size) + sizeof(key.ModTime)];1992memcpy(buf, &key.Size, sizeof(key.Size));1993memcpy(buf + sizeof(key.Size), &key.ModTime, sizeof(key.ModTime));1994return llvm::xxh3_64bits(buf);1995}19961997std::pair<unsigned, unsigned>1998EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {1999unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;2000unsigned DataLen = 1 + sizeof(IdentifierID) + 4;2001for (auto ModInfo : Data.KnownHeaders)2002if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))2003DataLen += 4;2004if (Data.Unresolved.getPointer())2005DataLen += 4;2006return emitULEBKeyDataLength(KeyLen, DataLen, Out);2007}20082009void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {2010using namespace llvm::support;20112012endian::Writer LE(Out, llvm::endianness::little);2013LE.write<uint64_t>(key.Size);2014KeyLen -= 8;2015LE.write<uint64_t>(key.ModTime);2016KeyLen -= 8;2017Out.write(key.Filename.data(), KeyLen);2018}20192020void EmitData(raw_ostream &Out, key_type_ref key,2021data_type_ref Data, unsigned DataLen) {2022using namespace llvm::support;20232024endian::Writer LE(Out, llvm::endianness::little);2025uint64_t Start = Out.tell(); (void)Start;20262027unsigned char Flags = (Data.AlreadyIncluded << 6)2028| (Data.HFI.isImport << 5)2029| (Writer.isWritingStdCXXNamedModules() ? 0 :2030Data.HFI.isPragmaOnce << 4)2031| (Data.HFI.DirInfo << 1)2032| Data.HFI.IndexHeaderMapHeader;2033LE.write<uint8_t>(Flags);20342035if (Data.HFI.LazyControllingMacro.isID())2036LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID());2037else2038LE.write<IdentifierID>(2039Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr()));20402041unsigned Offset = 0;2042if (!Data.HFI.Framework.empty()) {2043// If this header refers into a framework, save the framework name.2044llvm::StringMap<unsigned>::iterator Pos2045= FrameworkNameOffset.find(Data.HFI.Framework);2046if (Pos == FrameworkNameOffset.end()) {2047Offset = FrameworkStringData.size() + 1;2048FrameworkStringData.append(Data.HFI.Framework);2049FrameworkStringData.push_back(0);20502051FrameworkNameOffset[Data.HFI.Framework] = Offset;2052} else2053Offset = Pos->second;2054}2055LE.write<uint32_t>(Offset);20562057auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {2058if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {2059uint32_t Value = (ModID << 3) | (unsigned)Role;2060assert((Value >> 3) == ModID && "overflow in header module info");2061LE.write<uint32_t>(Value);2062}2063};20642065for (auto ModInfo : Data.KnownHeaders)2066EmitModule(ModInfo.getModule(), ModInfo.getRole());2067if (Data.Unresolved.getPointer())2068EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt());20692070assert(Out.tell() - Start == DataLen && "Wrong data length");2071}20722073const char *strings_begin() const { return FrameworkStringData.begin(); }2074const char *strings_end() const { return FrameworkStringData.end(); }2075};20762077} // namespace20782079/// Write the header search block for the list of files that2080///2081/// \param HS The header search structure to save.2082void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {2083HeaderFileInfoTrait GeneratorTrait(*this);2084llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;2085SmallVector<const char *, 4> SavedStrings;2086unsigned NumHeaderSearchEntries = 0;20872088// Find all unresolved headers for the current module. We generally will2089// have resolved them before we get here, but not necessarily: we might be2090// compiling a preprocessed module, where there is no requirement for the2091// original files to exist any more.2092const HeaderFileInfo Empty; // So we can take a reference.2093if (WritingModule) {2094llvm::SmallVector<Module *, 16> Worklist(1, WritingModule);2095while (!Worklist.empty()) {2096Module *M = Worklist.pop_back_val();2097// We don't care about headers in unimportable submodules.2098if (M->isUnimportable())2099continue;21002101// Map to disk files where possible, to pick up any missing stat2102// information. This also means we don't need to check the unresolved2103// headers list when emitting resolved headers in the first loop below.2104// FIXME: It'd be preferable to avoid doing this if we were given2105// sufficient stat information in the module map.2106HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/std::nullopt);21072108// If the file didn't exist, we can still create a module if we were given2109// enough information in the module map.2110for (const auto &U : M->MissingHeaders) {2111// Check that we were given enough information to build a module2112// without this file existing on disk.2113if (!U.Size || (!U.ModTime && IncludeTimestamps)) {2114PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header)2115<< WritingModule->getFullModuleName() << U.Size.has_value()2116<< U.FileName;2117continue;2118}21192120// Form the effective relative pathname for the file.2121SmallString<128> Filename(M->Directory->getName());2122llvm::sys::path::append(Filename, U.FileName);2123PreparePathForOutput(Filename);21242125StringRef FilenameDup = strdup(Filename.c_str());2126SavedStrings.push_back(FilenameDup.data());21272128HeaderFileInfoTrait::key_type Key = {2129FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0};2130HeaderFileInfoTrait::data_type Data = {2131Empty, false, {}, {M, ModuleMap::headerKindToRole(U.Kind)}};2132// FIXME: Deal with cases where there are multiple unresolved header2133// directives in different submodules for the same header.2134Generator.insert(Key, Data, GeneratorTrait);2135++NumHeaderSearchEntries;2136}2137auto SubmodulesRange = M->submodules();2138Worklist.append(SubmodulesRange.begin(), SubmodulesRange.end());2139}2140}21412142SmallVector<OptionalFileEntryRef, 16> FilesByUID;2143HS.getFileMgr().GetUniqueIDMapping(FilesByUID);21442145if (FilesByUID.size() > HS.header_file_size())2146FilesByUID.resize(HS.header_file_size());21472148for (unsigned UID = 0, LastUID = FilesByUID.size(); UID != LastUID; ++UID) {2149OptionalFileEntryRef File = FilesByUID[UID];2150if (!File)2151continue;21522153const HeaderFileInfo *HFI = HS.getExistingLocalFileInfo(*File);2154if (!HFI)2155continue; // We have no information on this being a header file.2156if (!HFI->isCompilingModuleHeader && HFI->isModuleHeader)2157continue; // Header file info is tracked by the owning module file.2158if (!HFI->isCompilingModuleHeader && !PP->alreadyIncluded(*File))2159continue; // Non-modular header not included is not needed.21602161// Massage the file path into an appropriate form.2162StringRef Filename = File->getName();2163SmallString<128> FilenameTmp(Filename);2164if (PreparePathForOutput(FilenameTmp)) {2165// If we performed any translation on the file name at all, we need to2166// save this string, since the generator will refer to it later.2167Filename = StringRef(strdup(FilenameTmp.c_str()));2168SavedStrings.push_back(Filename.data());2169}21702171bool Included = PP->alreadyIncluded(*File);21722173HeaderFileInfoTrait::key_type Key = {2174Filename, File->getSize(), getTimestampForOutput(*File)2175};2176HeaderFileInfoTrait::data_type Data = {2177*HFI, Included, HS.getModuleMap().findResolvedModulesForHeader(*File), {}2178};2179Generator.insert(Key, Data, GeneratorTrait);2180++NumHeaderSearchEntries;2181}21822183// Create the on-disk hash table in a buffer.2184SmallString<4096> TableData;2185uint32_t BucketOffset;2186{2187using namespace llvm::support;21882189llvm::raw_svector_ostream Out(TableData);2190// Make sure that no bucket is at offset 02191endian::write<uint32_t>(Out, 0, llvm::endianness::little);2192BucketOffset = Generator.Emit(Out, GeneratorTrait);2193}21942195// Create a blob abbreviation2196using namespace llvm;21972198auto Abbrev = std::make_shared<BitCodeAbbrev>();2199Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE));2200Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2201Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2202Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));2203Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2204unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));22052206// Write the header search table2207RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,2208NumHeaderSearchEntries, TableData.size()};2209TableData.append(GeneratorTrait.strings_begin(),GeneratorTrait.strings_end());2210Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);22112212// Free all of the strings we had to duplicate.2213for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)2214free(const_cast<char *>(SavedStrings[I]));2215}22162217static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,2218unsigned SLocBufferBlobCompressedAbbrv,2219unsigned SLocBufferBlobAbbrv) {2220using RecordDataType = ASTWriter::RecordData::value_type;22212222// Compress the buffer if possible. We expect that almost all PCM2223// consumers will not want its contents.2224SmallVector<uint8_t, 0> CompressedBuffer;2225if (llvm::compression::zstd::isAvailable()) {2226llvm::compression::zstd::compress(2227llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer, 9);2228RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};2229Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,2230llvm::toStringRef(CompressedBuffer));2231return;2232}2233if (llvm::compression::zlib::isAvailable()) {2234llvm::compression::zlib::compress(2235llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer);2236RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};2237Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,2238llvm::toStringRef(CompressedBuffer));2239return;2240}22412242RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB};2243Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);2244}22452246/// Writes the block containing the serialized form of the2247/// source manager.2248///2249/// TODO: We should probably use an on-disk hash table (stored in a2250/// blob), indexed based on the file name, so that we only create2251/// entries for files that we actually need. In the common case (no2252/// errors), we probably won't have to create file entries for any of2253/// the files in the AST.2254void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,2255const Preprocessor &PP) {2256RecordData Record;22572258// Enter the source manager block.2259Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 4);2260const uint64_t SourceManagerBlockOffset = Stream.GetCurrentBitNo();22612262// Abbreviations for the various kinds of source-location entries.2263unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);2264unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);2265unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false);2266unsigned SLocBufferBlobCompressedAbbrv =2267CreateSLocBufferBlobAbbrev(Stream, true);2268unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream);22692270// Write out the source location entry table. We skip the first2271// entry, which is always the same dummy entry.2272std::vector<uint32_t> SLocEntryOffsets;2273uint64_t SLocEntryOffsetsBase = Stream.GetCurrentBitNo();2274SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1);2275for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size();2276I != N; ++I) {2277// Get this source location entry.2278const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);2279FileID FID = FileID::get(I);2280assert(&SourceMgr.getSLocEntry(FID) == SLoc);22812282// Record the offset of this source-location entry.2283uint64_t Offset = Stream.GetCurrentBitNo() - SLocEntryOffsetsBase;2284assert((Offset >> 32) == 0 && "SLocEntry offset too large");22852286// Figure out which record code to use.2287unsigned Code;2288if (SLoc->isFile()) {2289const SrcMgr::ContentCache *Cache = &SLoc->getFile().getContentCache();2290if (Cache->OrigEntry) {2291Code = SM_SLOC_FILE_ENTRY;2292} else2293Code = SM_SLOC_BUFFER_ENTRY;2294} else2295Code = SM_SLOC_EXPANSION_ENTRY;2296Record.clear();2297Record.push_back(Code);22982299if (SLoc->isFile()) {2300const SrcMgr::FileInfo &File = SLoc->getFile();2301const SrcMgr::ContentCache *Content = &File.getContentCache();2302// Do not emit files that were not listed as inputs.2303if (!IsSLocAffecting[I])2304continue;2305SLocEntryOffsets.push_back(Offset);2306// Starting offset of this entry within this module, so skip the dummy.2307Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);2308AddSourceLocation(getAffectingIncludeLoc(SourceMgr, File), Record);2309Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding2310Record.push_back(File.hasLineDirectives());23112312bool EmitBlob = false;2313if (Content->OrigEntry) {2314assert(Content->OrigEntry == Content->ContentsEntry &&2315"Writing to AST an overridden file is not supported");23162317// The source location entry is a file. Emit input file ID.2318assert(InputFileIDs[*Content->OrigEntry] != 0 && "Missed file entry");2319Record.push_back(InputFileIDs[*Content->OrigEntry]);23202321Record.push_back(getAdjustedNumCreatedFIDs(FID));23222323FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID);2324if (FDI != FileDeclIDs.end()) {2325Record.push_back(FDI->second->FirstDeclIndex);2326Record.push_back(FDI->second->DeclIDs.size());2327} else {2328Record.push_back(0);2329Record.push_back(0);2330}23312332Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);23332334if (Content->BufferOverridden || Content->IsTransient)2335EmitBlob = true;2336} else {2337// The source location entry is a buffer. The blob associated2338// with this entry contains the contents of the buffer.23392340// We add one to the size so that we capture the trailing NULL2341// that is required by llvm::MemoryBuffer::getMemBuffer (on2342// the reader side).2343std::optional<llvm::MemoryBufferRef> Buffer =2344Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager());2345StringRef Name = Buffer ? Buffer->getBufferIdentifier() : "";2346Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,2347StringRef(Name.data(), Name.size() + 1));2348EmitBlob = true;2349}23502351if (EmitBlob) {2352// Include the implicit terminating null character in the on-disk buffer2353// if we're writing it uncompressed.2354std::optional<llvm::MemoryBufferRef> Buffer =2355Content->getBufferOrNone(PP.getDiagnostics(), PP.getFileManager());2356if (!Buffer)2357Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", "");2358StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1);2359emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv,2360SLocBufferBlobAbbrv);2361}2362} else {2363// The source location entry is a macro expansion.2364const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion();2365SLocEntryOffsets.push_back(Offset);2366// Starting offset of this entry within this module, so skip the dummy.2367Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);2368LocSeq::State Seq;2369AddSourceLocation(Expansion.getSpellingLoc(), Record, Seq);2370AddSourceLocation(Expansion.getExpansionLocStart(), Record, Seq);2371AddSourceLocation(Expansion.isMacroArgExpansion()2372? SourceLocation()2373: Expansion.getExpansionLocEnd(),2374Record, Seq);2375Record.push_back(Expansion.isExpansionTokenRange());23762377// Compute the token length for this macro expansion.2378SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset();2379if (I + 1 != N)2380NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();2381Record.push_back(getAdjustedOffset(NextOffset - SLoc->getOffset()) - 1);2382Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record);2383}2384}23852386Stream.ExitBlock();23872388if (SLocEntryOffsets.empty())2389return;23902391// Write the source-location offsets table into the AST block. This2392// table is used for lazily loading source-location information.2393using namespace llvm;23942395auto Abbrev = std::make_shared<BitCodeAbbrev>();2396Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));2397Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs2398Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size2399Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // base offset2400Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets2401unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2402{2403RecordData::value_type Record[] = {2404SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(),2405getAdjustedOffset(SourceMgr.getNextLocalOffset()) - 1 /* skip dummy */,2406SLocEntryOffsetsBase - SourceManagerBlockOffset};2407Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,2408bytes(SLocEntryOffsets));2409}24102411// Write the line table. It depends on remapping working, so it must come2412// after the source location offsets.2413if (SourceMgr.hasLineTable()) {2414LineTableInfo &LineTable = SourceMgr.getLineTable();24152416Record.clear();24172418// Emit the needed file names.2419llvm::DenseMap<int, int> FilenameMap;2420FilenameMap[-1] = -1; // For unspecified filenames.2421for (const auto &L : LineTable) {2422if (L.first.ID < 0)2423continue;2424for (auto &LE : L.second) {2425if (FilenameMap.insert(std::make_pair(LE.FilenameID,2426FilenameMap.size() - 1)).second)2427AddPath(LineTable.getFilename(LE.FilenameID), Record);2428}2429}2430Record.push_back(0);24312432// Emit the line entries2433for (const auto &L : LineTable) {2434// Only emit entries for local files.2435if (L.first.ID < 0)2436continue;24372438AddFileID(L.first, Record);24392440// Emit the line entries2441Record.push_back(L.second.size());2442for (const auto &LE : L.second) {2443Record.push_back(LE.FileOffset);2444Record.push_back(LE.LineNo);2445Record.push_back(FilenameMap[LE.FilenameID]);2446Record.push_back((unsigned)LE.FileKind);2447Record.push_back(LE.IncludeOffset);2448}2449}24502451Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record);2452}2453}24542455//===----------------------------------------------------------------------===//2456// Preprocessor Serialization2457//===----------------------------------------------------------------------===//24582459static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,2460const Preprocessor &PP) {2461if (MacroInfo *MI = MD->getMacroInfo())2462if (MI->isBuiltinMacro())2463return true;24642465if (IsModule) {2466SourceLocation Loc = MD->getLocation();2467if (Loc.isInvalid())2468return true;2469if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID())2470return true;2471}24722473return false;2474}24752476/// Writes the block containing the serialized form of the2477/// preprocessor.2478void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {2479uint64_t MacroOffsetsBase = Stream.GetCurrentBitNo();24802481PreprocessingRecord *PPRec = PP.getPreprocessingRecord();2482if (PPRec)2483WritePreprocessorDetail(*PPRec, MacroOffsetsBase);24842485RecordData Record;2486RecordData ModuleMacroRecord;24872488// If the preprocessor __COUNTER__ value has been bumped, remember it.2489if (PP.getCounterValue() != 0) {2490RecordData::value_type Record[] = {PP.getCounterValue()};2491Stream.EmitRecord(PP_COUNTER_VALUE, Record);2492}24932494// If we have a recorded #pragma assume_nonnull, remember it so it can be2495// replayed when the preamble terminates into the main file.2496SourceLocation AssumeNonNullLoc =2497PP.getPreambleRecordedPragmaAssumeNonNullLoc();2498if (AssumeNonNullLoc.isValid()) {2499assert(PP.isRecordingPreamble());2500AddSourceLocation(AssumeNonNullLoc, Record);2501Stream.EmitRecord(PP_ASSUME_NONNULL_LOC, Record);2502Record.clear();2503}25042505if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {2506assert(!IsModule);2507auto SkipInfo = PP.getPreambleSkipInfo();2508if (SkipInfo) {2509Record.push_back(true);2510AddSourceLocation(SkipInfo->HashTokenLoc, Record);2511AddSourceLocation(SkipInfo->IfTokenLoc, Record);2512Record.push_back(SkipInfo->FoundNonSkipPortion);2513Record.push_back(SkipInfo->FoundElse);2514AddSourceLocation(SkipInfo->ElseLoc, Record);2515} else {2516Record.push_back(false);2517}2518for (const auto &Cond : PP.getPreambleConditionalStack()) {2519AddSourceLocation(Cond.IfLoc, Record);2520Record.push_back(Cond.WasSkipping);2521Record.push_back(Cond.FoundNonSkip);2522Record.push_back(Cond.FoundElse);2523}2524Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);2525Record.clear();2526}25272528// Write the safe buffer opt-out region map in PP2529for (SourceLocation &S : PP.serializeSafeBufferOptOutMap())2530AddSourceLocation(S, Record);2531Stream.EmitRecord(PP_UNSAFE_BUFFER_USAGE, Record);2532Record.clear();25332534// Enter the preprocessor block.2535Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);25362537// If the AST file contains __DATE__ or __TIME__ emit a warning about this.2538// FIXME: Include a location for the use, and say which one was used.2539if (PP.SawDateOrTime())2540PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule;25412542// Loop over all the macro directives that are live at the end of the file,2543// emitting each to the PP section.25442545// Construct the list of identifiers with macro directives that need to be2546// serialized.2547SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;2548// It is meaningless to emit macros for named modules. It only wastes times2549// and spaces.2550if (!isWritingStdCXXNamedModules())2551for (auto &Id : PP.getIdentifierTable())2552if (Id.second->hadMacroDefinition() &&2553(!Id.second->isFromAST() ||2554Id.second->hasChangedSinceDeserialization()))2555MacroIdentifiers.push_back(Id.second);2556// Sort the set of macro definitions that need to be serialized by the2557// name of the macro, to provide a stable ordering.2558llvm::sort(MacroIdentifiers, llvm::deref<std::less<>>());25592560// Emit the macro directives as a list and associate the offset with the2561// identifier they belong to.2562for (const IdentifierInfo *Name : MacroIdentifiers) {2563MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);2564uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2565assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");25662567// Write out any exported module macros.2568bool EmittedModuleMacros = false;2569// C+=20 Header Units are compiled module interfaces, but they preserve2570// macros that are live (i.e. have a defined value) at the end of the2571// compilation. So when writing a header unit, we preserve only the final2572// value of each macro (and discard any that are undefined). Header units2573// do not have sub-modules (although they might import other header units).2574// PCH files, conversely, retain the history of each macro's define/undef2575// and of leaf macros in sub modules.2576if (IsModule && WritingModule->isHeaderUnit()) {2577// This is for the main TU when it is a C++20 header unit.2578// We preserve the final state of defined macros, and we do not emit ones2579// that are undefined.2580if (!MD || shouldIgnoreMacro(MD, IsModule, PP) ||2581MD->getKind() == MacroDirective::MD_Undefine)2582continue;2583AddSourceLocation(MD->getLocation(), Record);2584Record.push_back(MD->getKind());2585if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {2586Record.push_back(getMacroRef(DefMD->getInfo(), Name));2587} else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {2588Record.push_back(VisMD->isPublic());2589}2590ModuleMacroRecord.push_back(getSubmoduleID(WritingModule));2591ModuleMacroRecord.push_back(getMacroRef(MD->getMacroInfo(), Name));2592Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);2593ModuleMacroRecord.clear();2594EmittedModuleMacros = true;2595} else {2596// Emit the macro directives in reverse source order.2597for (; MD; MD = MD->getPrevious()) {2598// Once we hit an ignored macro, we're done: the rest of the chain2599// will all be ignored macros.2600if (shouldIgnoreMacro(MD, IsModule, PP))2601break;2602AddSourceLocation(MD->getLocation(), Record);2603Record.push_back(MD->getKind());2604if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {2605Record.push_back(getMacroRef(DefMD->getInfo(), Name));2606} else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {2607Record.push_back(VisMD->isPublic());2608}2609}26102611// We write out exported module macros for PCH as well.2612auto Leafs = PP.getLeafModuleMacros(Name);2613SmallVector<ModuleMacro *, 8> Worklist(Leafs.begin(), Leafs.end());2614llvm::DenseMap<ModuleMacro *, unsigned> Visits;2615while (!Worklist.empty()) {2616auto *Macro = Worklist.pop_back_val();26172618// Emit a record indicating this submodule exports this macro.2619ModuleMacroRecord.push_back(getSubmoduleID(Macro->getOwningModule()));2620ModuleMacroRecord.push_back(getMacroRef(Macro->getMacroInfo(), Name));2621for (auto *M : Macro->overrides())2622ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));26232624Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);2625ModuleMacroRecord.clear();26262627// Enqueue overridden macros once we've visited all their ancestors.2628for (auto *M : Macro->overrides())2629if (++Visits[M] == M->getNumOverridingMacros())2630Worklist.push_back(M);26312632EmittedModuleMacros = true;2633}2634}2635if (Record.empty() && !EmittedModuleMacros)2636continue;26372638IdentMacroDirectivesOffsetMap[Name] = StartOffset;2639Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);2640Record.clear();2641}26422643/// Offsets of each of the macros into the bitstream, indexed by2644/// the local macro ID2645///2646/// For each identifier that is associated with a macro, this map2647/// provides the offset into the bitstream where that macro is2648/// defined.2649std::vector<uint32_t> MacroOffsets;26502651for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) {2652const IdentifierInfo *Name = MacroInfosToEmit[I].Name;2653MacroInfo *MI = MacroInfosToEmit[I].MI;2654MacroID ID = MacroInfosToEmit[I].ID;26552656if (ID < FirstMacroID) {2657assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?");2658continue;2659}26602661// Record the local offset of this macro.2662unsigned Index = ID - FirstMacroID;2663if (Index >= MacroOffsets.size())2664MacroOffsets.resize(Index + 1);26652666uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2667assert((Offset >> 32) == 0 && "Macro offset too large");2668MacroOffsets[Index] = Offset;26692670AddIdentifierRef(Name, Record);2671AddSourceLocation(MI->getDefinitionLoc(), Record);2672AddSourceLocation(MI->getDefinitionEndLoc(), Record);2673Record.push_back(MI->isUsed());2674Record.push_back(MI->isUsedForHeaderGuard());2675Record.push_back(MI->getNumTokens());2676unsigned Code;2677if (MI->isObjectLike()) {2678Code = PP_MACRO_OBJECT_LIKE;2679} else {2680Code = PP_MACRO_FUNCTION_LIKE;26812682Record.push_back(MI->isC99Varargs());2683Record.push_back(MI->isGNUVarargs());2684Record.push_back(MI->hasCommaPasting());2685Record.push_back(MI->getNumParams());2686for (const IdentifierInfo *Param : MI->params())2687AddIdentifierRef(Param, Record);2688}26892690// If we have a detailed preprocessing record, record the macro definition2691// ID that corresponds to this macro.2692if (PPRec)2693Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]);26942695Stream.EmitRecord(Code, Record);2696Record.clear();26972698// Emit the tokens array.2699for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {2700// Note that we know that the preprocessor does not have any annotation2701// tokens in it because they are created by the parser, and thus can't2702// be in a macro definition.2703const Token &Tok = MI->getReplacementToken(TokNo);2704AddToken(Tok, Record);2705Stream.EmitRecord(PP_TOKEN, Record);2706Record.clear();2707}2708++NumMacros;2709}27102711Stream.ExitBlock();27122713// Write the offsets table for macro IDs.2714using namespace llvm;27152716auto Abbrev = std::make_shared<BitCodeAbbrev>();2717Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));2718Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros2719Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID2720Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // base offset2721Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));27222723unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2724{2725RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(),2726FirstMacroID - NUM_PREDEF_MACRO_IDS,2727MacroOffsetsBase - ASTBlockStartOffset};2728Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets));2729}2730}27312732void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec,2733uint64_t MacroOffsetsBase) {2734if (PPRec.local_begin() == PPRec.local_end())2735return;27362737SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets;27382739// Enter the preprocessor block.2740Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3);27412742// If the preprocessor has a preprocessing record, emit it.2743unsigned NumPreprocessingRecords = 0;2744using namespace llvm;27452746// Set up the abbreviation for2747unsigned InclusionAbbrev = 0;2748{2749auto Abbrev = std::make_shared<BitCodeAbbrev>();2750Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));2751Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length2752Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes2753Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind2754Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module2755Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2756InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));2757}27582759unsigned FirstPreprocessorEntityID2760= (Chain ? PPRec.getNumLoadedPreprocessedEntities() : 0)2761+ NUM_PREDEF_PP_ENTITY_IDS;2762unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID;2763RecordData Record;2764for (PreprocessingRecord::iterator E = PPRec.local_begin(),2765EEnd = PPRec.local_end();2766E != EEnd;2767(void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {2768Record.clear();27692770uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;2771assert((Offset >> 32) == 0 && "Preprocessed entity offset too large");2772SourceRange R = getAdjustedRange((*E)->getSourceRange());2773PreprocessedEntityOffsets.emplace_back(2774getRawSourceLocationEncoding(R.getBegin()),2775getRawSourceLocationEncoding(R.getEnd()), Offset);27762777if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) {2778// Record this macro definition's ID.2779MacroDefinitions[MD] = NextPreprocessorEntityID;27802781AddIdentifierRef(MD->getName(), Record);2782Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);2783continue;2784}27852786if (auto *ME = dyn_cast<MacroExpansion>(*E)) {2787Record.push_back(ME->isBuiltinMacro());2788if (ME->isBuiltinMacro())2789AddIdentifierRef(ME->getName(), Record);2790else2791Record.push_back(MacroDefinitions[ME->getDefinition()]);2792Stream.EmitRecord(PPD_MACRO_EXPANSION, Record);2793continue;2794}27952796if (auto *ID = dyn_cast<InclusionDirective>(*E)) {2797Record.push_back(PPD_INCLUSION_DIRECTIVE);2798Record.push_back(ID->getFileName().size());2799Record.push_back(ID->wasInQuotes());2800Record.push_back(static_cast<unsigned>(ID->getKind()));2801Record.push_back(ID->importedModule());2802SmallString<64> Buffer;2803Buffer += ID->getFileName();2804// Check that the FileEntry is not null because it was not resolved and2805// we create a PCH even with compiler errors.2806if (ID->getFile())2807Buffer += ID->getFile()->getName();2808Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);2809continue;2810}28112812llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");2813}2814Stream.ExitBlock();28152816// Write the offsets table for the preprocessing record.2817if (NumPreprocessingRecords > 0) {2818assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords);28192820// Write the offsets table for identifier IDs.2821using namespace llvm;28222823auto Abbrev = std::make_shared<BitCodeAbbrev>();2824Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS));2825Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first pp entity2826Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2827unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));28282829RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS,2830FirstPreprocessorEntityID -2831NUM_PREDEF_PP_ENTITY_IDS};2832Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,2833bytes(PreprocessedEntityOffsets));2834}28352836// Write the skipped region table for the preprocessing record.2837ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges();2838if (SkippedRanges.size() > 0) {2839std::vector<PPSkippedRange> SerializedSkippedRanges;2840SerializedSkippedRanges.reserve(SkippedRanges.size());2841for (auto const& Range : SkippedRanges)2842SerializedSkippedRanges.emplace_back(2843getRawSourceLocationEncoding(Range.getBegin()),2844getRawSourceLocationEncoding(Range.getEnd()));28452846using namespace llvm;2847auto Abbrev = std::make_shared<BitCodeAbbrev>();2848Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));2849Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));2850unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev));28512852Record.clear();2853Record.push_back(PPD_SKIPPED_RANGES);2854Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,2855bytes(SerializedSkippedRanges));2856}2857}28582859unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) {2860if (!Mod)2861return 0;28622863auto Known = SubmoduleIDs.find(Mod);2864if (Known != SubmoduleIDs.end())2865return Known->second;28662867auto *Top = Mod->getTopLevelModule();2868if (Top != WritingModule &&2869(getLangOpts().CompilingPCH ||2870!Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule))))2871return 0;28722873return SubmoduleIDs[Mod] = NextSubmoduleID++;2874}28752876unsigned ASTWriter::getSubmoduleID(Module *Mod) {2877unsigned ID = getLocalOrImportedSubmoduleID(Mod);2878// FIXME: This can easily happen, if we have a reference to a submodule that2879// did not result in us loading a module file for that submodule. For2880// instance, a cross-top-level-module 'conflict' declaration will hit this.2881// assert((ID || !Mod) &&2882// "asked for module ID for non-local, non-imported module");2883return ID;2884}28852886/// Compute the number of modules within the given tree (including the2887/// given module).2888static unsigned getNumberOfModules(Module *Mod) {2889unsigned ChildModules = 0;2890for (auto *Submodule : Mod->submodules())2891ChildModules += getNumberOfModules(Submodule);28922893return ChildModules + 1;2894}28952896void ASTWriter::WriteSubmodules(Module *WritingModule) {2897// Enter the submodule description block.2898Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);28992900// Write the abbreviations needed for the submodules block.2901using namespace llvm;29022903auto Abbrev = std::make_shared<BitCodeAbbrev>();2904Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));2905Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID2906Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent2907Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind2908Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location2909Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework2910Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit2911Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem2912Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC2913Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...2914Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...2915Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...2916Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...2917Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv...2918Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NamedModuleHasN...2919Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2920unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29212922Abbrev = std::make_shared<BitCodeAbbrev>();2923Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER));2924Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2925unsigned UmbrellaAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29262927Abbrev = std::make_shared<BitCodeAbbrev>();2928Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER));2929Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2930unsigned HeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29312932Abbrev = std::make_shared<BitCodeAbbrev>();2933Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER));2934Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2935unsigned TopHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29362937Abbrev = std::make_shared<BitCodeAbbrev>();2938Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR));2939Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2940unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29412942Abbrev = std::make_shared<BitCodeAbbrev>();2943Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));2944Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State2945Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature2946unsigned RequiresAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29472948Abbrev = std::make_shared<BitCodeAbbrev>();2949Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER));2950Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2951unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29522953Abbrev = std::make_shared<BitCodeAbbrev>();2954Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER));2955Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2956unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29572958Abbrev = std::make_shared<BitCodeAbbrev>();2959Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));2960Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2961unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29622963Abbrev = std::make_shared<BitCodeAbbrev>();2964Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER));2965Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2966unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29672968Abbrev = std::make_shared<BitCodeAbbrev>();2969Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));2970Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework2971Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name2972unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29732974Abbrev = std::make_shared<BitCodeAbbrev>();2975Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO));2976Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name2977unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29782979Abbrev = std::make_shared<BitCodeAbbrev>();2980Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT));2981Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Other module2982Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Message2983unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29842985Abbrev = std::make_shared<BitCodeAbbrev>();2986Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS));2987Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Macro name2988unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));29892990// Write the submodule metadata block.2991RecordData::value_type Record[] = {2992getNumberOfModules(WritingModule),2993FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS};2994Stream.EmitRecord(SUBMODULE_METADATA, Record);29952996// Write all of the submodules.2997std::queue<Module *> Q;2998Q.push(WritingModule);2999while (!Q.empty()) {3000Module *Mod = Q.front();3001Q.pop();3002unsigned ID = getSubmoduleID(Mod);30033004uint64_t ParentID = 0;3005if (Mod->Parent) {3006assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?");3007ParentID = SubmoduleIDs[Mod->Parent];3008}30093010SourceLocationEncoding::RawLocEncoding DefinitionLoc =3011getRawSourceLocationEncoding(getAdjustedLocation(Mod->DefinitionLoc));30123013// Emit the definition of the block.3014{3015RecordData::value_type Record[] = {SUBMODULE_DEFINITION,3016ID,3017ParentID,3018(RecordData::value_type)Mod->Kind,3019DefinitionLoc,3020Mod->IsFramework,3021Mod->IsExplicit,3022Mod->IsSystem,3023Mod->IsExternC,3024Mod->InferSubmodules,3025Mod->InferExplicitSubmodules,3026Mod->InferExportWildcard,3027Mod->ConfigMacrosExhaustive,3028Mod->ModuleMapIsPrivate,3029Mod->NamedModuleHasInit};3030Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);3031}30323033// Emit the requirements.3034for (const auto &R : Mod->Requirements) {3035RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.RequiredState};3036Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.FeatureName);3037}30383039// Emit the umbrella header, if there is one.3040if (std::optional<Module::Header> UmbrellaHeader =3041Mod->getUmbrellaHeaderAsWritten()) {3042RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER};3043Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,3044UmbrellaHeader->NameAsWritten);3045} else if (std::optional<Module::DirectoryName> UmbrellaDir =3046Mod->getUmbrellaDirAsWritten()) {3047RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR};3048Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,3049UmbrellaDir->NameAsWritten);3050}30513052// Emit the headers.3053struct {3054unsigned RecordKind;3055unsigned Abbrev;3056Module::HeaderKind HeaderKind;3057} HeaderLists[] = {3058{SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal},3059{SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual},3060{SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private},3061{SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev,3062Module::HK_PrivateTextual},3063{SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded}3064};3065for (auto &HL : HeaderLists) {3066RecordData::value_type Record[] = {HL.RecordKind};3067for (auto &H : Mod->Headers[HL.HeaderKind])3068Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten);3069}30703071// Emit the top headers.3072{3073RecordData::value_type Record[] = {SUBMODULE_TOPHEADER};3074for (FileEntryRef H : Mod->getTopHeaders(PP->getFileManager())) {3075SmallString<128> HeaderName(H.getName());3076PreparePathForOutput(HeaderName);3077Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, HeaderName);3078}3079}30803081// Emit the imports.3082if (!Mod->Imports.empty()) {3083RecordData Record;3084for (auto *I : Mod->Imports)3085Record.push_back(getSubmoduleID(I));3086Stream.EmitRecord(SUBMODULE_IMPORTS, Record);3087}30883089// Emit the modules affecting compilation that were not imported.3090if (!Mod->AffectingClangModules.empty()) {3091RecordData Record;3092for (auto *I : Mod->AffectingClangModules)3093Record.push_back(getSubmoduleID(I));3094Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record);3095}30963097// Emit the exports.3098if (!Mod->Exports.empty()) {3099RecordData Record;3100for (const auto &E : Mod->Exports) {3101// FIXME: This may fail; we don't require that all exported modules3102// are local or imported.3103Record.push_back(getSubmoduleID(E.getPointer()));3104Record.push_back(E.getInt());3105}3106Stream.EmitRecord(SUBMODULE_EXPORTS, Record);3107}31083109//FIXME: How do we emit the 'use'd modules? They may not be submodules.3110// Might be unnecessary as use declarations are only used to build the3111// module itself.31123113// TODO: Consider serializing undeclared uses of modules.31143115// Emit the link libraries.3116for (const auto &LL : Mod->LinkLibraries) {3117RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY,3118LL.IsFramework};3119Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library);3120}31213122// Emit the conflicts.3123for (const auto &C : Mod->Conflicts) {3124// FIXME: This may fail; we don't require that all conflicting modules3125// are local or imported.3126RecordData::value_type Record[] = {SUBMODULE_CONFLICT,3127getSubmoduleID(C.Other)};3128Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message);3129}31303131// Emit the configuration macros.3132for (const auto &CM : Mod->ConfigMacros) {3133RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO};3134Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);3135}31363137// Emit the reachable initializers.3138// The initializer may only be unreachable in reduced BMI.3139RecordData Inits;3140for (Decl *D : Context->getModuleInitializers(Mod))3141if (wasDeclEmitted(D))3142AddDeclRef(D, Inits);3143if (!Inits.empty())3144Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);31453146// Emit the name of the re-exported module, if any.3147if (!Mod->ExportAsModule.empty()) {3148RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS};3149Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule);3150}31513152// Queue up the submodules of this module.3153for (auto *M : Mod->submodules())3154Q.push(M);3155}31563157Stream.ExitBlock();31583159assert((NextSubmoduleID - FirstSubmoduleID ==3160getNumberOfModules(WritingModule)) &&3161"Wrong # of submodules; found a reference to a non-local, "3162"non-imported submodule?");3163}31643165void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,3166bool isModule) {3167llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64>3168DiagStateIDMap;3169unsigned CurrID = 0;3170RecordData Record;31713172auto EncodeDiagStateFlags =3173[](const DiagnosticsEngine::DiagState *DS) -> unsigned {3174unsigned Result = (unsigned)DS->ExtBehavior;3175for (unsigned Val :3176{(unsigned)DS->IgnoreAllWarnings, (unsigned)DS->EnableAllWarnings,3177(unsigned)DS->WarningsAsErrors, (unsigned)DS->ErrorsAsFatal,3178(unsigned)DS->SuppressSystemWarnings})3179Result = (Result << 1) | Val;3180return Result;3181};31823183unsigned Flags = EncodeDiagStateFlags(Diag.DiagStatesByLoc.FirstDiagState);3184Record.push_back(Flags);31853186auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State,3187bool IncludeNonPragmaStates) {3188// Ensure that the diagnostic state wasn't modified since it was created.3189// We will not correctly round-trip this information otherwise.3190assert(Flags == EncodeDiagStateFlags(State) &&3191"diag state flags vary in single AST file");31923193// If we ever serialize non-pragma mappings outside the initial state, the3194// code below will need to consider more than getDefaultMapping.3195assert(!IncludeNonPragmaStates ||3196State == Diag.DiagStatesByLoc.FirstDiagState);31973198unsigned &DiagStateID = DiagStateIDMap[State];3199Record.push_back(DiagStateID);32003201if (DiagStateID == 0) {3202DiagStateID = ++CurrID;3203SmallVector<std::pair<unsigned, DiagnosticMapping>> Mappings;32043205// Add a placeholder for the number of mappings.3206auto SizeIdx = Record.size();3207Record.emplace_back();3208for (const auto &I : *State) {3209// Maybe skip non-pragmas.3210if (!I.second.isPragma() && !IncludeNonPragmaStates)3211continue;3212// Skip default mappings. We have a mapping for every diagnostic ever3213// emitted, regardless of whether it was customized.3214if (!I.second.isPragma() &&3215I.second == DiagnosticIDs::getDefaultMapping(I.first))3216continue;3217Mappings.push_back(I);3218}32193220// Sort by diag::kind for deterministic output.3221llvm::sort(Mappings, llvm::less_first());32223223for (const auto &I : Mappings) {3224Record.push_back(I.first);3225Record.push_back(I.second.serialize());3226}3227// Update the placeholder.3228Record[SizeIdx] = (Record.size() - SizeIdx) / 2;3229}3230};32313232AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule);32333234// Reserve a spot for the number of locations with state transitions.3235auto NumLocationsIdx = Record.size();3236Record.emplace_back();32373238// Emit the state transitions.3239unsigned NumLocations = 0;3240for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) {3241if (!FileIDAndFile.first.isValid() ||3242!FileIDAndFile.second.HasLocalTransitions)3243continue;3244++NumLocations;32453246AddFileID(FileIDAndFile.first, Record);32473248Record.push_back(FileIDAndFile.second.StateTransitions.size());3249for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {3250Record.push_back(getAdjustedOffset(StatePoint.Offset));3251AddDiagState(StatePoint.State, false);3252}3253}32543255// Backpatch the number of locations.3256Record[NumLocationsIdx] = NumLocations;32573258// Emit CurDiagStateLoc. Do it last in order to match source order.3259//3260// This also protects against a hypothetical corner case with simulating3261// -Werror settings for implicit modules in the ASTReader, where reading3262// CurDiagState out of context could change whether warning pragmas are3263// treated as errors.3264AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record);3265AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false);32663267Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);3268}32693270//===----------------------------------------------------------------------===//3271// Type Serialization3272//===----------------------------------------------------------------------===//32733274/// Write the representation of a type to the AST stream.3275void ASTWriter::WriteType(QualType T) {3276TypeIdx &IdxRef = TypeIdxs[T];3277if (IdxRef.getValue() == 0) // we haven't seen this type before.3278IdxRef = TypeIdx(0, NextTypeID++);3279TypeIdx Idx = IdxRef;32803281assert(Idx.getModuleFileIndex() == 0 && "Re-writing a type from a prior AST");3282assert(Idx.getValue() >= FirstTypeID && "Writing predefined type");32833284// Emit the type's representation.3285uint64_t Offset = ASTTypeWriter(*this).write(T) - DeclTypesBlockStartOffset;32863287// Record the offset for this type.3288uint64_t Index = Idx.getValue() - FirstTypeID;3289if (TypeOffsets.size() == Index)3290TypeOffsets.emplace_back(Offset);3291else if (TypeOffsets.size() < Index) {3292TypeOffsets.resize(Index + 1);3293TypeOffsets[Index].set(Offset);3294} else {3295llvm_unreachable("Types emitted in wrong order");3296}3297}32983299//===----------------------------------------------------------------------===//3300// Declaration Serialization3301//===----------------------------------------------------------------------===//33023303static bool IsInternalDeclFromFileContext(const Decl *D) {3304auto *ND = dyn_cast<NamedDecl>(D);3305if (!ND)3306return false;33073308if (!D->getDeclContext()->getRedeclContext()->isFileContext())3309return false;33103311return ND->getFormalLinkage() == Linkage::Internal;3312}33133314/// Write the block containing all of the declaration IDs3315/// lexically declared within the given DeclContext.3316///3317/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the3318/// bitstream, or 0 if no block was written.3319uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,3320const DeclContext *DC) {3321if (DC->decls_empty())3322return 0;33233324// In reduced BMI, we don't care the declarations in functions.3325if (GeneratingReducedBMI && DC->isFunctionOrMethod())3326return 0;33273328uint64_t Offset = Stream.GetCurrentBitNo();3329SmallVector<DeclID, 128> KindDeclPairs;3330for (const auto *D : DC->decls()) {3331if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))3332continue;33333334// We don't need to write decls with internal linkage into reduced BMI.3335// If such decls gets emitted due to it get used from inline functions,3336// the program illegal. However, there are too many use of static inline3337// functions in the global module fragment and it will be breaking change3338// to forbid that. So we have to allow to emit such declarations from GMF.3339if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() &&3340IsInternalDeclFromFileContext(D))3341continue;33423343KindDeclPairs.push_back(D->getKind());3344KindDeclPairs.push_back(GetDeclRef(D).getRawValue());3345}33463347++NumLexicalDeclContexts;3348RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL};3349Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,3350bytes(KindDeclPairs));3351return Offset;3352}33533354void ASTWriter::WriteTypeDeclOffsets() {3355using namespace llvm;33563357// Write the type offsets array3358auto Abbrev = std::make_shared<BitCodeAbbrev>();3359Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));3360Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types3361Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block3362unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3363{3364RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size()};3365Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));3366}33673368// Write the declaration offsets array3369Abbrev = std::make_shared<BitCodeAbbrev>();3370Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));3371Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations3372Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block3373unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));3374{3375RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size()};3376Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));3377}3378}33793380void ASTWriter::WriteFileDeclIDsMap() {3381using namespace llvm;33823383SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs;3384SortedFileDeclIDs.reserve(FileDeclIDs.size());3385for (const auto &P : FileDeclIDs)3386SortedFileDeclIDs.push_back(std::make_pair(P.first, P.second.get()));3387llvm::sort(SortedFileDeclIDs, llvm::less_first());33883389// Join the vectors of DeclIDs from all files.3390SmallVector<DeclID, 256> FileGroupedDeclIDs;3391for (auto &FileDeclEntry : SortedFileDeclIDs) {3392DeclIDInFileInfo &Info = *FileDeclEntry.second;3393Info.FirstDeclIndex = FileGroupedDeclIDs.size();3394llvm::stable_sort(Info.DeclIDs);3395for (auto &LocDeclEntry : Info.DeclIDs)3396FileGroupedDeclIDs.push_back(LocDeclEntry.second.getRawValue());3397}33983399auto Abbrev = std::make_shared<BitCodeAbbrev>();3400Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS));3401Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3402Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3403unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));3404RecordData::value_type Record[] = {FILE_SORTED_DECLS,3405FileGroupedDeclIDs.size()};3406Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs));3407}34083409void ASTWriter::WriteComments() {3410Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);3411auto _ = llvm::make_scope_exit([this] { Stream.ExitBlock(); });3412if (!PP->getPreprocessorOpts().WriteCommentListToPCH)3413return;34143415// Don't write comments to BMI to reduce the size of BMI.3416// If language services (e.g., clangd) want such abilities,3417// we can offer a special option then.3418if (isWritingStdCXXNamedModules())3419return;34203421RecordData Record;3422for (const auto &FO : Context->Comments.OrderedComments) {3423for (const auto &OC : FO.second) {3424const RawComment *I = OC.second;3425Record.clear();3426AddSourceRange(I->getSourceRange(), Record);3427Record.push_back(I->getKind());3428Record.push_back(I->isTrailingComment());3429Record.push_back(I->isAlmostTrailingComment());3430Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);3431}3432}3433}34343435//===----------------------------------------------------------------------===//3436// Global Method Pool and Selector Serialization3437//===----------------------------------------------------------------------===//34383439namespace {34403441// Trait used for the on-disk hash table used in the method pool.3442class ASTMethodPoolTrait {3443ASTWriter &Writer;34443445public:3446using key_type = Selector;3447using key_type_ref = key_type;34483449struct data_type {3450SelectorID ID;3451ObjCMethodList Instance, Factory;3452};3453using data_type_ref = const data_type &;34543455using hash_value_type = unsigned;3456using offset_type = unsigned;34573458explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {}34593460static hash_value_type ComputeHash(Selector Sel) {3461return serialization::ComputeHash(Sel);3462}34633464std::pair<unsigned, unsigned>3465EmitKeyDataLength(raw_ostream& Out, Selector Sel,3466data_type_ref Methods) {3467unsigned KeyLen =34682 + (Sel.getNumArgs() ? Sel.getNumArgs() * sizeof(IdentifierID)3469: sizeof(IdentifierID));3470unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts3471for (const ObjCMethodList *Method = &Methods.Instance; Method;3472Method = Method->getNext())3473if (ShouldWriteMethodListNode(Method))3474DataLen += sizeof(DeclID);3475for (const ObjCMethodList *Method = &Methods.Factory; Method;3476Method = Method->getNext())3477if (ShouldWriteMethodListNode(Method))3478DataLen += sizeof(DeclID);3479return emitULEBKeyDataLength(KeyLen, DataLen, Out);3480}34813482void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {3483using namespace llvm::support;34843485endian::Writer LE(Out, llvm::endianness::little);3486uint64_t Start = Out.tell();3487assert((Start >> 32) == 0 && "Selector key offset too large");3488Writer.SetSelectorOffset(Sel, Start);3489unsigned N = Sel.getNumArgs();3490LE.write<uint16_t>(N);3491if (N == 0)3492N = 1;3493for (unsigned I = 0; I != N; ++I)3494LE.write<IdentifierID>(3495Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));3496}34973498void EmitData(raw_ostream& Out, key_type_ref,3499data_type_ref Methods, unsigned DataLen) {3500using namespace llvm::support;35013502endian::Writer LE(Out, llvm::endianness::little);3503uint64_t Start = Out.tell(); (void)Start;3504LE.write<uint32_t>(Methods.ID);3505unsigned NumInstanceMethods = 0;3506for (const ObjCMethodList *Method = &Methods.Instance; Method;3507Method = Method->getNext())3508if (ShouldWriteMethodListNode(Method))3509++NumInstanceMethods;35103511unsigned NumFactoryMethods = 0;3512for (const ObjCMethodList *Method = &Methods.Factory; Method;3513Method = Method->getNext())3514if (ShouldWriteMethodListNode(Method))3515++NumFactoryMethods;35163517unsigned InstanceBits = Methods.Instance.getBits();3518assert(InstanceBits < 4);3519unsigned InstanceHasMoreThanOneDeclBit =3520Methods.Instance.hasMoreThanOneDecl();3521unsigned FullInstanceBits = (NumInstanceMethods << 3) |3522(InstanceHasMoreThanOneDeclBit << 2) |3523InstanceBits;3524unsigned FactoryBits = Methods.Factory.getBits();3525assert(FactoryBits < 4);3526unsigned FactoryHasMoreThanOneDeclBit =3527Methods.Factory.hasMoreThanOneDecl();3528unsigned FullFactoryBits = (NumFactoryMethods << 3) |3529(FactoryHasMoreThanOneDeclBit << 2) |3530FactoryBits;3531LE.write<uint16_t>(FullInstanceBits);3532LE.write<uint16_t>(FullFactoryBits);3533for (const ObjCMethodList *Method = &Methods.Instance; Method;3534Method = Method->getNext())3535if (ShouldWriteMethodListNode(Method))3536LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));3537for (const ObjCMethodList *Method = &Methods.Factory; Method;3538Method = Method->getNext())3539if (ShouldWriteMethodListNode(Method))3540LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));35413542assert(Out.tell() - Start == DataLen && "Data length is wrong");3543}35443545private:3546static bool ShouldWriteMethodListNode(const ObjCMethodList *Node) {3547return (Node->getMethod() && !Node->getMethod()->isFromASTFile());3548}3549};35503551} // namespace35523553/// Write ObjC data: selectors and the method pool.3554///3555/// The method pool contains both instance and factory methods, stored3556/// in an on-disk hash table indexed by the selector. The hash table also3557/// contains an empty entry for every other selector known to Sema.3558void ASTWriter::WriteSelectors(Sema &SemaRef) {3559using namespace llvm;35603561// Do we have to do anything at all?3562if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty())3563return;3564unsigned NumTableEntries = 0;3565// Create and write out the blob that contains selectors and the method pool.3566{3567llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;3568ASTMethodPoolTrait Trait(*this);35693570// Create the on-disk hash table representation. We walk through every3571// selector we've seen and look it up in the method pool.3572SelectorOffsets.resize(NextSelectorID - FirstSelectorID);3573for (auto &SelectorAndID : SelectorIDs) {3574Selector S = SelectorAndID.first;3575SelectorID ID = SelectorAndID.second;3576SemaObjC::GlobalMethodPool::iterator F =3577SemaRef.ObjC().MethodPool.find(S);3578ASTMethodPoolTrait::data_type Data = {3579ID,3580ObjCMethodList(),3581ObjCMethodList()3582};3583if (F != SemaRef.ObjC().MethodPool.end()) {3584Data.Instance = F->second.first;3585Data.Factory = F->second.second;3586}3587// Only write this selector if it's not in an existing AST or something3588// changed.3589if (Chain && ID < FirstSelectorID) {3590// Selector already exists. Did it change?3591bool changed = false;3592for (ObjCMethodList *M = &Data.Instance; M && M->getMethod();3593M = M->getNext()) {3594if (!M->getMethod()->isFromASTFile()) {3595changed = true;3596Data.Instance = *M;3597break;3598}3599}3600for (ObjCMethodList *M = &Data.Factory; M && M->getMethod();3601M = M->getNext()) {3602if (!M->getMethod()->isFromASTFile()) {3603changed = true;3604Data.Factory = *M;3605break;3606}3607}3608if (!changed)3609continue;3610} else if (Data.Instance.getMethod() || Data.Factory.getMethod()) {3611// A new method pool entry.3612++NumTableEntries;3613}3614Generator.insert(S, Data, Trait);3615}36163617// Create the on-disk hash table in a buffer.3618SmallString<4096> MethodPool;3619uint32_t BucketOffset;3620{3621using namespace llvm::support;36223623ASTMethodPoolTrait Trait(*this);3624llvm::raw_svector_ostream Out(MethodPool);3625// Make sure that no bucket is at offset 03626endian::write<uint32_t>(Out, 0, llvm::endianness::little);3627BucketOffset = Generator.Emit(Out, Trait);3628}36293630// Create a blob abbreviation3631auto Abbrev = std::make_shared<BitCodeAbbrev>();3632Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));3633Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3634Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3635Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3636unsigned MethodPoolAbbrev = Stream.EmitAbbrev(std::move(Abbrev));36373638// Write the method pool3639{3640RecordData::value_type Record[] = {METHOD_POOL, BucketOffset,3641NumTableEntries};3642Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);3643}36443645// Create a blob abbreviation for the selector table offsets.3646Abbrev = std::make_shared<BitCodeAbbrev>();3647Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS));3648Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size3649Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID3650Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3651unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));36523653// Write the selector offsets table.3654{3655RecordData::value_type Record[] = {3656SELECTOR_OFFSETS, SelectorOffsets.size(),3657FirstSelectorID - NUM_PREDEF_SELECTOR_IDS};3658Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,3659bytes(SelectorOffsets));3660}3661}3662}36633664/// Write the selectors referenced in @selector expression into AST file.3665void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {3666using namespace llvm;36673668if (SemaRef.ObjC().ReferencedSelectors.empty())3669return;36703671RecordData Record;3672ASTRecordWriter Writer(*this, Record);36733674// Note: this writes out all references even for a dependent AST. But it is3675// very tricky to fix, and given that @selector shouldn't really appear in3676// headers, probably not worth it. It's not a correctness issue.3677for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) {3678Selector Sel = SelectorAndLocation.first;3679SourceLocation Loc = SelectorAndLocation.second;3680Writer.AddSelectorRef(Sel);3681Writer.AddSourceLocation(Loc);3682}3683Writer.Emit(REFERENCED_SELECTOR_POOL);3684}36853686//===----------------------------------------------------------------------===//3687// Identifier Table Serialization3688//===----------------------------------------------------------------------===//36893690/// Determine the declaration that should be put into the name lookup table to3691/// represent the given declaration in this module. This is usually D itself,3692/// but if D was imported and merged into a local declaration, we want the most3693/// recent local declaration instead. The chosen declaration will be the most3694/// recent declaration in any module that imports this one.3695static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,3696NamedDecl *D) {3697if (!LangOpts.Modules || !D->isFromASTFile())3698return D;36993700if (Decl *Redecl = D->getPreviousDecl()) {3701// For Redeclarable decls, a prior declaration might be local.3702for (; Redecl; Redecl = Redecl->getPreviousDecl()) {3703// If we find a local decl, we're done.3704if (!Redecl->isFromASTFile()) {3705// Exception: in very rare cases (for injected-class-names), not all3706// redeclarations are in the same semantic context. Skip ones in a3707// different context. They don't go in this lookup table at all.3708if (!Redecl->getDeclContext()->getRedeclContext()->Equals(3709D->getDeclContext()->getRedeclContext()))3710continue;3711return cast<NamedDecl>(Redecl);3712}37133714// If we find a decl from a (chained-)PCH stop since we won't find a3715// local one.3716if (Redecl->getOwningModuleID() == 0)3717break;3718}3719} else if (Decl *First = D->getCanonicalDecl()) {3720// For Mergeable decls, the first decl might be local.3721if (!First->isFromASTFile())3722return cast<NamedDecl>(First);3723}37243725// All declarations are imported. Our most recent declaration will also be3726// the most recent one in anyone who imports us.3727return D;3728}37293730namespace {37313732bool IsInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset,3733bool IsModule, bool IsCPlusPlus) {3734bool NeedDecls = !IsModule || !IsCPlusPlus;37353736bool IsInteresting =3737II->getNotableIdentifierID() != tok::NotableIdentifierKind::not_notable ||3738II->getBuiltinID() != Builtin::ID::NotBuiltin ||3739II->getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword;3740if (MacroOffset || II->isPoisoned() || (!IsModule && IsInteresting) ||3741II->hasRevertedTokenIDToIdentifier() ||3742(NeedDecls && II->getFETokenInfo()))3743return true;37443745return false;3746}37473748bool IsInterestingNonMacroIdentifier(const IdentifierInfo *II,3749ASTWriter &Writer) {3750bool IsModule = Writer.isWritingModule();3751bool IsCPlusPlus = Writer.getLangOpts().CPlusPlus;3752return IsInterestingIdentifier(II, /*MacroOffset=*/0, IsModule, IsCPlusPlus);3753}37543755class ASTIdentifierTableTrait {3756ASTWriter &Writer;3757Preprocessor &PP;3758IdentifierResolver &IdResolver;3759bool IsModule;3760bool NeedDecls;3761ASTWriter::RecordData *InterestingIdentifierOffsets;37623763/// Determines whether this is an "interesting" identifier that needs a3764/// full IdentifierInfo structure written into the hash table. Notably, this3765/// doesn't check whether the name has macros defined; use PublicMacroIterator3766/// to check that.3767bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {3768return IsInterestingIdentifier(II, MacroOffset, IsModule,3769Writer.getLangOpts().CPlusPlus);3770}37713772public:3773using key_type = const IdentifierInfo *;3774using key_type_ref = key_type;37753776using data_type = IdentifierID;3777using data_type_ref = data_type;37783779using hash_value_type = unsigned;3780using offset_type = unsigned;37813782ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,3783IdentifierResolver &IdResolver, bool IsModule,3784ASTWriter::RecordData *InterestingIdentifierOffsets)3785: Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule),3786NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus),3787InterestingIdentifierOffsets(InterestingIdentifierOffsets) {}37883789bool needDecls() const { return NeedDecls; }37903791static hash_value_type ComputeHash(const IdentifierInfo* II) {3792return llvm::djbHash(II->getName());3793}37943795bool isInterestingIdentifier(const IdentifierInfo *II) {3796auto MacroOffset = Writer.getMacroDirectivesOffset(II);3797return isInterestingIdentifier(II, MacroOffset);3798}37993800std::pair<unsigned, unsigned>3801EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID) {3802// Record the location of the identifier data. This is used when generating3803// the mapping from persistent IDs to strings.3804Writer.SetIdentifierOffset(II, Out.tell());38053806auto MacroOffset = Writer.getMacroDirectivesOffset(II);38073808// Emit the offset of the key/data length information to the interesting3809// identifiers table if necessary.3810if (InterestingIdentifierOffsets &&3811isInterestingIdentifier(II, MacroOffset))3812InterestingIdentifierOffsets->push_back(Out.tell());38133814unsigned KeyLen = II->getLength() + 1;3815unsigned DataLen = sizeof(IdentifierID); // bytes for the persistent ID << 13816if (isInterestingIdentifier(II, MacroOffset)) {3817DataLen += 2; // 2 bytes for builtin ID3818DataLen += 2; // 2 bytes for flags3819if (MacroOffset)3820DataLen += 4; // MacroDirectives offset.38213822if (NeedDecls)3823DataLen += std::distance(IdResolver.begin(II), IdResolver.end()) *3824sizeof(DeclID);3825}3826return emitULEBKeyDataLength(KeyLen, DataLen, Out);3827}38283829void EmitKey(raw_ostream &Out, const IdentifierInfo *II, unsigned KeyLen) {3830Out.write(II->getNameStart(), KeyLen);3831}38323833void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID,3834unsigned) {3835using namespace llvm::support;38363837endian::Writer LE(Out, llvm::endianness::little);38383839auto MacroOffset = Writer.getMacroDirectivesOffset(II);3840if (!isInterestingIdentifier(II, MacroOffset)) {3841LE.write<IdentifierID>(ID << 1);3842return;3843}38443845LE.write<IdentifierID>((ID << 1) | 0x01);3846uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID();3847assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");3848LE.write<uint16_t>(Bits);3849Bits = 0;3850bool HadMacroDefinition = MacroOffset != 0;3851Bits = (Bits << 1) | unsigned(HadMacroDefinition);3852Bits = (Bits << 1) | unsigned(II->isExtensionToken());3853Bits = (Bits << 1) | unsigned(II->isPoisoned());3854Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());3855Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());3856LE.write<uint16_t>(Bits);38573858if (HadMacroDefinition)3859LE.write<uint32_t>(MacroOffset);38603861if (NeedDecls) {3862// Emit the declaration IDs in reverse order, because the3863// IdentifierResolver provides the declarations as they would be3864// visible (e.g., the function "stat" would come before the struct3865// "stat"), but the ASTReader adds declarations to the end of the list3866// (so we need to see the struct "stat" before the function "stat").3867// Only emit declarations that aren't from a chained PCH, though.3868SmallVector<NamedDecl *, 16> Decls(IdResolver.decls(II));3869for (NamedDecl *D : llvm::reverse(Decls))3870LE.write<DeclID>((DeclID)Writer.getDeclID(3871getDeclForLocalLookup(PP.getLangOpts(), D)));3872}3873}3874};38753876} // namespace38773878/// If the \param IdentifierID ID is a local Identifier ID. If the higher3879/// bits of ID is 0, it implies that the ID doesn't come from AST files.3880static bool isLocalIdentifierID(IdentifierID ID) { return !(ID >> 32); }38813882/// Write the identifier table into the AST file.3883///3884/// The identifier table consists of a blob containing string data3885/// (the actual identifiers themselves) and a separate "offsets" index3886/// that maps identifier IDs to locations within the blob.3887void ASTWriter::WriteIdentifierTable(Preprocessor &PP,3888IdentifierResolver &IdResolver,3889bool IsModule) {3890using namespace llvm;38913892RecordData InterestingIdents;38933894// Create and write out the blob that contains the identifier3895// strings.3896{3897llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;3898ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule,3899IsModule ? &InterestingIdents : nullptr);39003901// Create the on-disk hash table representation. We only store offsets3902// for identifiers that appear here for the first time.3903IdentifierOffsets.resize(NextIdentID - FirstIdentID);3904for (auto IdentIDPair : IdentifierIDs) {3905const IdentifierInfo *II = IdentIDPair.first;3906IdentifierID ID = IdentIDPair.second;3907assert(II && "NULL identifier in identifier table");39083909// Write out identifiers if either the ID is local or the identifier has3910// changed since it was loaded.3911if (isLocalIdentifierID(ID) || II->hasChangedSinceDeserialization() ||3912(Trait.needDecls() &&3913II->hasFETokenInfoChangedSinceDeserialization()))3914Generator.insert(II, ID, Trait);3915}39163917// Create the on-disk hash table in a buffer.3918SmallString<4096> IdentifierTable;3919uint32_t BucketOffset;3920{3921using namespace llvm::support;39223923llvm::raw_svector_ostream Out(IdentifierTable);3924// Make sure that no bucket is at offset 03925endian::write<uint32_t>(Out, 0, llvm::endianness::little);3926BucketOffset = Generator.Emit(Out, Trait);3927}39283929// Create a blob abbreviation3930auto Abbrev = std::make_shared<BitCodeAbbrev>();3931Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));3932Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));3933Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3934unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));39353936// Write the identifier table3937RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset};3938Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);3939}39403941// Write the offsets table for identifier IDs.3942auto Abbrev = std::make_shared<BitCodeAbbrev>();3943Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));3944Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers3945Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));3946unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));39473948#ifndef NDEBUG3949for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I)3950assert(IdentifierOffsets[I] && "Missing identifier offset?");3951#endif39523953RecordData::value_type Record[] = {IDENTIFIER_OFFSET,3954IdentifierOffsets.size()};3955Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,3956bytes(IdentifierOffsets));39573958// In C++, write the list of interesting identifiers (those that are3959// defined as macros, poisoned, or similar unusual things).3960if (!InterestingIdents.empty())3961Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);3962}39633964void ASTWriter::handleVTable(CXXRecordDecl *RD) {3965if (!RD->isInNamedModule())3966return;39673968PendingEmittingVTables.push_back(RD);3969}39703971//===----------------------------------------------------------------------===//3972// DeclContext's Name Lookup Table Serialization3973//===----------------------------------------------------------------------===//39743975namespace {39763977// Trait used for the on-disk hash table used in the method pool.3978class ASTDeclContextNameLookupTrait {3979ASTWriter &Writer;3980llvm::SmallVector<LocalDeclID, 64> DeclIDs;39813982public:3983using key_type = DeclarationNameKey;3984using key_type_ref = key_type;39853986/// A start and end index into DeclIDs, representing a sequence of decls.3987using data_type = std::pair<unsigned, unsigned>;3988using data_type_ref = const data_type &;39893990using hash_value_type = unsigned;3991using offset_type = unsigned;39923993explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : Writer(Writer) {}39943995template<typename Coll>3996data_type getData(const Coll &Decls) {3997unsigned Start = DeclIDs.size();3998for (NamedDecl *D : Decls) {3999NamedDecl *DeclForLocalLookup =4000getDeclForLocalLookup(Writer.getLangOpts(), D);40014002if (Writer.getDoneWritingDeclsAndTypes() &&4003!Writer.wasDeclEmitted(DeclForLocalLookup))4004continue;40054006// Try to avoid writing internal decls to reduced BMI.4007// See comments in ASTWriter::WriteDeclContextLexicalBlock for details.4008if (Writer.isGeneratingReducedBMI() &&4009!DeclForLocalLookup->isFromExplicitGlobalModule() &&4010IsInternalDeclFromFileContext(DeclForLocalLookup))4011continue;40124013DeclIDs.push_back(Writer.GetDeclRef(DeclForLocalLookup));4014}4015return std::make_pair(Start, DeclIDs.size());4016}40174018data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {4019unsigned Start = DeclIDs.size();4020DeclIDs.insert(4021DeclIDs.end(),4022DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.begin()),4023DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.end()));4024return std::make_pair(Start, DeclIDs.size());4025}40264027static bool EqualKey(key_type_ref a, key_type_ref b) {4028return a == b;4029}40304031hash_value_type ComputeHash(DeclarationNameKey Name) {4032return Name.getHash();4033}40344035void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {4036assert(Writer.hasChain() &&4037"have reference to loaded module file but no chain?");40384039using namespace llvm::support;40404041endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F),4042llvm::endianness::little);4043}40444045std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,4046DeclarationNameKey Name,4047data_type_ref Lookup) {4048unsigned KeyLen = 1;4049switch (Name.getKind()) {4050case DeclarationName::Identifier:4051case DeclarationName::CXXLiteralOperatorName:4052case DeclarationName::CXXDeductionGuideName:4053KeyLen += sizeof(IdentifierID);4054break;4055case DeclarationName::ObjCZeroArgSelector:4056case DeclarationName::ObjCOneArgSelector:4057case DeclarationName::ObjCMultiArgSelector:4058KeyLen += 4;4059break;4060case DeclarationName::CXXOperatorName:4061KeyLen += 1;4062break;4063case DeclarationName::CXXConstructorName:4064case DeclarationName::CXXDestructorName:4065case DeclarationName::CXXConversionFunctionName:4066case DeclarationName::CXXUsingDirective:4067break;4068}40694070// length of DeclIDs.4071unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first);40724073return emitULEBKeyDataLength(KeyLen, DataLen, Out);4074}40754076void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {4077using namespace llvm::support;40784079endian::Writer LE(Out, llvm::endianness::little);4080LE.write<uint8_t>(Name.getKind());4081switch (Name.getKind()) {4082case DeclarationName::Identifier:4083case DeclarationName::CXXLiteralOperatorName:4084case DeclarationName::CXXDeductionGuideName:4085LE.write<IdentifierID>(Writer.getIdentifierRef(Name.getIdentifier()));4086return;4087case DeclarationName::ObjCZeroArgSelector:4088case DeclarationName::ObjCOneArgSelector:4089case DeclarationName::ObjCMultiArgSelector:4090LE.write<uint32_t>(Writer.getSelectorRef(Name.getSelector()));4091return;4092case DeclarationName::CXXOperatorName:4093assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS &&4094"Invalid operator?");4095LE.write<uint8_t>(Name.getOperatorKind());4096return;4097case DeclarationName::CXXConstructorName:4098case DeclarationName::CXXDestructorName:4099case DeclarationName::CXXConversionFunctionName:4100case DeclarationName::CXXUsingDirective:4101return;4102}41034104llvm_unreachable("Invalid name kind?");4105}41064107void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,4108unsigned DataLen) {4109using namespace llvm::support;41104111endian::Writer LE(Out, llvm::endianness::little);4112uint64_t Start = Out.tell(); (void)Start;4113for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)4114LE.write<DeclID>((DeclID)DeclIDs[I]);4115assert(Out.tell() - Start == DataLen && "Data length is wrong");4116}4117};41184119} // namespace41204121bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,4122DeclContext *DC) {4123return Result.hasExternalDecls() &&4124DC->hasNeedToReconcileExternalVisibleStorage();4125}41264127/// Returns ture if all of the lookup result are either external, not emitted or4128/// predefined. In such cases, the lookup result is not interesting and we don't4129/// need to record the result in the current being written module. Return false4130/// otherwise.4131static bool isLookupResultNotInteresting(ASTWriter &Writer,4132StoredDeclsList &Result) {4133for (auto *D : Result.getLookupResult()) {4134auto *LocalD = getDeclForLocalLookup(Writer.getLangOpts(), D);4135if (LocalD->isFromASTFile())4136continue;41374138// We can only be sure whether the local declaration is reachable4139// after we done writing the declarations and types.4140if (Writer.getDoneWritingDeclsAndTypes() && !Writer.wasDeclEmitted(LocalD))4141continue;41424143// We don't need to emit the predefined decls.4144if (Writer.isDeclPredefined(LocalD))4145continue;41464147return false;4148}41494150return true;4151}41524153void4154ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,4155llvm::SmallVectorImpl<char> &LookupTable) {4156assert(!ConstDC->hasLazyLocalLexicalLookups() &&4157!ConstDC->hasLazyExternalLexicalLookups() &&4158"must call buildLookups first");41594160// FIXME: We need to build the lookups table, which is logically const.4161auto *DC = const_cast<DeclContext*>(ConstDC);4162assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");41634164// Create the on-disk hash table representation.4165MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,4166ASTDeclContextNameLookupTrait> Generator;4167ASTDeclContextNameLookupTrait Trait(*this);41684169// The first step is to collect the declaration names which we need to4170// serialize into the name lookup table, and to collect them in a stable4171// order.4172SmallVector<DeclarationName, 16> Names;41734174// We also build up small sets of the constructor and conversion function4175// names which are visible.4176llvm::SmallPtrSet<DeclarationName, 8> ConstructorNameSet, ConversionNameSet;41774178for (auto &Lookup : *DC->buildLookup()) {4179auto &Name = Lookup.first;4180auto &Result = Lookup.second;41814182// If there are no local declarations in our lookup result, we4183// don't need to write an entry for the name at all. If we can't4184// write out a lookup set without performing more deserialization,4185// just skip this entry.4186//4187// Also in reduced BMI, we'd like to avoid writing unreachable4188// declarations in GMF, so we need to avoid writing declarations4189// that entirely external or unreachable.4190//4191// FIMXE: It looks sufficient to test4192// isLookupResultNotInteresting here. But due to bug we have4193// to test isLookupResultExternal here. See4194// https://github.com/llvm/llvm-project/issues/61065 for details.4195if ((GeneratingReducedBMI || isLookupResultExternal(Result, DC)) &&4196isLookupResultNotInteresting(*this, Result))4197continue;41984199// We also skip empty results. If any of the results could be external and4200// the currently available results are empty, then all of the results are4201// external and we skip it above. So the only way we get here with an empty4202// results is when no results could have been external *and* we have4203// external results.4204//4205// FIXME: While we might want to start emitting on-disk entries for negative4206// lookups into a decl context as an optimization, today we *have* to skip4207// them because there are names with empty lookup results in decl contexts4208// which we can't emit in any stable ordering: we lookup constructors and4209// conversion functions in the enclosing namespace scope creating empty4210// results for them. This in almost certainly a bug in Clang's name lookup,4211// but that is likely to be hard or impossible to fix and so we tolerate it4212// here by omitting lookups with empty results.4213if (Lookup.second.getLookupResult().empty())4214continue;42154216switch (Lookup.first.getNameKind()) {4217default:4218Names.push_back(Lookup.first);4219break;42204221case DeclarationName::CXXConstructorName:4222assert(isa<CXXRecordDecl>(DC) &&4223"Cannot have a constructor name outside of a class!");4224ConstructorNameSet.insert(Name);4225break;42264227case DeclarationName::CXXConversionFunctionName:4228assert(isa<CXXRecordDecl>(DC) &&4229"Cannot have a conversion function name outside of a class!");4230ConversionNameSet.insert(Name);4231break;4232}4233}42344235// Sort the names into a stable order.4236llvm::sort(Names);42374238if (auto *D = dyn_cast<CXXRecordDecl>(DC)) {4239// We need to establish an ordering of constructor and conversion function4240// names, and they don't have an intrinsic ordering.42414242// First we try the easy case by forming the current context's constructor4243// name and adding that name first. This is a very useful optimization to4244// avoid walking the lexical declarations in many cases, and it also4245// handles the only case where a constructor name can come from some other4246// lexical context -- when that name is an implicit constructor merged from4247// another declaration in the redecl chain. Any non-implicit constructor or4248// conversion function which doesn't occur in all the lexical contexts4249// would be an ODR violation.4250auto ImplicitCtorName = Context->DeclarationNames.getCXXConstructorName(4251Context->getCanonicalType(Context->getRecordType(D)));4252if (ConstructorNameSet.erase(ImplicitCtorName))4253Names.push_back(ImplicitCtorName);42544255// If we still have constructors or conversion functions, we walk all the4256// names in the decl and add the constructors and conversion functions4257// which are visible in the order they lexically occur within the context.4258if (!ConstructorNameSet.empty() || !ConversionNameSet.empty())4259for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls())4260if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {4261auto Name = ChildND->getDeclName();4262switch (Name.getNameKind()) {4263default:4264continue;42654266case DeclarationName::CXXConstructorName:4267if (ConstructorNameSet.erase(Name))4268Names.push_back(Name);4269break;42704271case DeclarationName::CXXConversionFunctionName:4272if (ConversionNameSet.erase(Name))4273Names.push_back(Name);4274break;4275}42764277if (ConstructorNameSet.empty() && ConversionNameSet.empty())4278break;4279}42804281assert(ConstructorNameSet.empty() && "Failed to find all of the visible "4282"constructors by walking all the "4283"lexical members of the context.");4284assert(ConversionNameSet.empty() && "Failed to find all of the visible "4285"conversion functions by walking all "4286"the lexical members of the context.");4287}42884289// Next we need to do a lookup with each name into this decl context to fully4290// populate any results from external sources. We don't actually use the4291// results of these lookups because we only want to use the results after all4292// results have been loaded and the pointers into them will be stable.4293for (auto &Name : Names)4294DC->lookup(Name);42954296// Now we need to insert the results for each name into the hash table. For4297// constructor names and conversion function names, we actually need to merge4298// all of the results for them into one list of results each and insert4299// those.4300SmallVector<NamedDecl *, 8> ConstructorDecls;4301SmallVector<NamedDecl *, 8> ConversionDecls;43024303// Now loop over the names, either inserting them or appending for the two4304// special cases.4305for (auto &Name : Names) {4306DeclContext::lookup_result Result = DC->noload_lookup(Name);43074308switch (Name.getNameKind()) {4309default:4310Generator.insert(Name, Trait.getData(Result), Trait);4311break;43124313case DeclarationName::CXXConstructorName:4314ConstructorDecls.append(Result.begin(), Result.end());4315break;43164317case DeclarationName::CXXConversionFunctionName:4318ConversionDecls.append(Result.begin(), Result.end());4319break;4320}4321}43224323// Handle our two special cases if we ended up having any. We arbitrarily use4324// the first declaration's name here because the name itself isn't part of4325// the key, only the kind of name is used.4326if (!ConstructorDecls.empty())4327Generator.insert(ConstructorDecls.front()->getDeclName(),4328Trait.getData(ConstructorDecls), Trait);4329if (!ConversionDecls.empty())4330Generator.insert(ConversionDecls.front()->getDeclName(),4331Trait.getData(ConversionDecls), Trait);43324333// Create the on-disk hash table. Also emit the existing imported and4334// merged table if there is one.4335auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr;4336Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr);4337}43384339/// Write the block containing all of the declaration IDs4340/// visible from the given DeclContext.4341///4342/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the4343/// bitstream, or 0 if no block was written.4344uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context,4345DeclContext *DC) {4346// If we imported a key declaration of this namespace, write the visible4347// lookup results as an update record for it rather than including them4348// on this declaration. We will only look at key declarations on reload.4349if (isa<NamespaceDecl>(DC) && Chain &&4350Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {4351// Only do this once, for the first local declaration of the namespace.4352for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;4353Prev = Prev->getPreviousDecl())4354if (!Prev->isFromASTFile())4355return 0;43564357// Note that we need to emit an update record for the primary context.4358UpdatedDeclContexts.insert(DC->getPrimaryContext());43594360// Make sure all visible decls are written. They will be recorded later. We4361// do this using a side data structure so we can sort the names into4362// a deterministic order.4363StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup();4364SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>4365LookupResults;4366if (Map) {4367LookupResults.reserve(Map->size());4368for (auto &Entry : *Map)4369LookupResults.push_back(4370std::make_pair(Entry.first, Entry.second.getLookupResult()));4371}43724373llvm::sort(LookupResults, llvm::less_first());4374for (auto &NameAndResult : LookupResults) {4375DeclarationName Name = NameAndResult.first;4376DeclContext::lookup_result Result = NameAndResult.second;4377if (Name.getNameKind() == DeclarationName::CXXConstructorName ||4378Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {4379// We have to work around a name lookup bug here where negative lookup4380// results for these names get cached in namespace lookup tables (these4381// names should never be looked up in a namespace).4382assert(Result.empty() && "Cannot have a constructor or conversion "4383"function name in a namespace!");4384continue;4385}43864387for (NamedDecl *ND : Result) {4388if (ND->isFromASTFile())4389continue;43904391if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))4392continue;43934394// We don't need to force emitting internal decls into reduced BMI.4395// See comments in ASTWriter::WriteDeclContextLexicalBlock for details.4396if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() &&4397IsInternalDeclFromFileContext(ND))4398continue;43994400GetDeclRef(ND);4401}4402}44034404return 0;4405}44064407if (DC->getPrimaryContext() != DC)4408return 0;44094410// Skip contexts which don't support name lookup.4411if (!DC->isLookupContext())4412return 0;44134414// If not in C++, we perform name lookup for the translation unit via the4415// IdentifierInfo chains, don't bother to build a visible-declarations table.4416if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus)4417return 0;44184419// Serialize the contents of the mapping used for lookup. Note that,4420// although we have two very different code paths, the serialized4421// representation is the same for both cases: a declaration name,4422// followed by a size, followed by references to the visible4423// declarations that have that name.4424uint64_t Offset = Stream.GetCurrentBitNo();4425StoredDeclsMap *Map = DC->buildLookup();4426if (!Map || Map->empty())4427return 0;44284429// Create the on-disk hash table in a buffer.4430SmallString<4096> LookupTable;4431GenerateNameLookupTable(DC, LookupTable);44324433// Write the lookup table4434RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE};4435Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,4436LookupTable);4437++NumVisibleDeclContexts;4438return Offset;4439}44404441/// Write an UPDATE_VISIBLE block for the given context.4442///4443/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing4444/// DeclContext in a dependent AST file. As such, they only exist for the TU4445/// (in C++), for namespaces, and for classes with forward-declared unscoped4446/// enumeration members (in C++11).4447void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) {4448StoredDeclsMap *Map = DC->getLookupPtr();4449if (!Map || Map->empty())4450return;44514452// Create the on-disk hash table in a buffer.4453SmallString<4096> LookupTable;4454GenerateNameLookupTable(DC, LookupTable);44554456// If we're updating a namespace, select a key declaration as the key for the4457// update record; those are the only ones that will be checked on reload.4458if (isa<NamespaceDecl>(DC))4459DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));44604461// Write the lookup table4462RecordData::value_type Record[] = {UPDATE_VISIBLE,4463getDeclID(cast<Decl>(DC)).getRawValue()};4464Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);4465}44664467/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.4468void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {4469RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};4470Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);4471}44724473/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.4474void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {4475if (!SemaRef.Context.getLangOpts().OpenCL)4476return;44774478const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();4479RecordData Record;4480for (const auto &I:Opts.OptMap) {4481AddString(I.getKey(), Record);4482auto V = I.getValue();4483Record.push_back(V.Supported ? 1 : 0);4484Record.push_back(V.Enabled ? 1 : 0);4485Record.push_back(V.WithPragma ? 1 : 0);4486Record.push_back(V.Avail);4487Record.push_back(V.Core);4488Record.push_back(V.Opt);4489}4490Stream.EmitRecord(OPENCL_EXTENSIONS, Record);4491}4492void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {4493if (SemaRef.CUDA().ForceHostDeviceDepth > 0) {4494RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth};4495Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record);4496}4497}44984499void ASTWriter::WriteObjCCategories() {4500SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;4501RecordData Categories;45024503for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {4504unsigned Size = 0;4505unsigned StartIndex = Categories.size();45064507ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];45084509// Allocate space for the size.4510Categories.push_back(0);45114512// Add the categories.4513for (ObjCInterfaceDecl::known_categories_iterator4514Cat = Class->known_categories_begin(),4515CatEnd = Class->known_categories_end();4516Cat != CatEnd; ++Cat, ++Size) {4517assert(getDeclID(*Cat).isValid() && "Bogus category");4518AddDeclRef(*Cat, Categories);4519}45204521// Update the size.4522Categories[StartIndex] = Size;45234524// Record this interface -> category map.4525ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };4526CategoriesMap.push_back(CatInfo);4527}45284529// Sort the categories map by the definition ID, since the reader will be4530// performing binary searches on this information.4531llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end());45324533// Emit the categories map.4534using namespace llvm;45354536auto Abbrev = std::make_shared<BitCodeAbbrev>();4537Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));4538Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries4539Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));4540unsigned AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));45414542RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()};4543Stream.EmitRecordWithBlob(AbbrevID, Record,4544reinterpret_cast<char *>(CategoriesMap.data()),4545CategoriesMap.size() * sizeof(ObjCCategoriesInfo));45464547// Emit the category lists.4548Stream.EmitRecord(OBJC_CATEGORIES, Categories);4549}45504551void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {4552Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap;45534554if (LPTMap.empty())4555return;45564557RecordData Record;4558for (auto &LPTMapEntry : LPTMap) {4559const FunctionDecl *FD = LPTMapEntry.first;4560LateParsedTemplate &LPT = *LPTMapEntry.second;4561AddDeclRef(FD, Record);4562AddDeclRef(LPT.D, Record);4563Record.push_back(LPT.FPO.getAsOpaqueInt());4564Record.push_back(LPT.Toks.size());45654566for (const auto &Tok : LPT.Toks) {4567AddToken(Tok, Record);4568}4569}4570Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);4571}45724573/// Write the state of 'pragma clang optimize' at the end of the module.4574void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {4575RecordData Record;4576SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();4577AddSourceLocation(PragmaLoc, Record);4578Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);4579}45804581/// Write the state of 'pragma ms_struct' at the end of the module.4582void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {4583RecordData Record;4584Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);4585Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);4586}45874588/// Write the state of 'pragma pointers_to_members' at the end of the4589//module.4590void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {4591RecordData Record;4592Record.push_back(SemaRef.MSPointerToMemberRepresentationMethod);4593AddSourceLocation(SemaRef.ImplicitMSInheritanceAttrLoc, Record);4594Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record);4595}45964597/// Write the state of 'pragma align/pack' at the end of the module.4598void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {4599// Don't serialize pragma align/pack state for modules, since it should only4600// take effect on a per-submodule basis.4601if (WritingModule)4602return;46034604RecordData Record;4605AddAlignPackInfo(SemaRef.AlignPackStack.CurrentValue, Record);4606AddSourceLocation(SemaRef.AlignPackStack.CurrentPragmaLocation, Record);4607Record.push_back(SemaRef.AlignPackStack.Stack.size());4608for (const auto &StackEntry : SemaRef.AlignPackStack.Stack) {4609AddAlignPackInfo(StackEntry.Value, Record);4610AddSourceLocation(StackEntry.PragmaLocation, Record);4611AddSourceLocation(StackEntry.PragmaPushLocation, Record);4612AddString(StackEntry.StackSlotLabel, Record);4613}4614Stream.EmitRecord(ALIGN_PACK_PRAGMA_OPTIONS, Record);4615}46164617/// Write the state of 'pragma float_control' at the end of the module.4618void ASTWriter::WriteFloatControlPragmaOptions(Sema &SemaRef) {4619// Don't serialize pragma float_control state for modules,4620// since it should only take effect on a per-submodule basis.4621if (WritingModule)4622return;46234624RecordData Record;4625Record.push_back(SemaRef.FpPragmaStack.CurrentValue.getAsOpaqueInt());4626AddSourceLocation(SemaRef.FpPragmaStack.CurrentPragmaLocation, Record);4627Record.push_back(SemaRef.FpPragmaStack.Stack.size());4628for (const auto &StackEntry : SemaRef.FpPragmaStack.Stack) {4629Record.push_back(StackEntry.Value.getAsOpaqueInt());4630AddSourceLocation(StackEntry.PragmaLocation, Record);4631AddSourceLocation(StackEntry.PragmaPushLocation, Record);4632AddString(StackEntry.StackSlotLabel, Record);4633}4634Stream.EmitRecord(FLOAT_CONTROL_PRAGMA_OPTIONS, Record);4635}46364637void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,4638ModuleFileExtensionWriter &Writer) {4639// Enter the extension block.4640Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4);46414642// Emit the metadata record abbreviation.4643auto Abv = std::make_shared<llvm::BitCodeAbbrev>();4644Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA));4645Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));4646Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));4647Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));4648Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));4649Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));4650unsigned Abbrev = Stream.EmitAbbrev(std::move(Abv));46514652// Emit the metadata record.4653RecordData Record;4654auto Metadata = Writer.getExtension()->getExtensionMetadata();4655Record.push_back(EXTENSION_METADATA);4656Record.push_back(Metadata.MajorVersion);4657Record.push_back(Metadata.MinorVersion);4658Record.push_back(Metadata.BlockName.size());4659Record.push_back(Metadata.UserInfo.size());4660SmallString<64> Buffer;4661Buffer += Metadata.BlockName;4662Buffer += Metadata.UserInfo;4663Stream.EmitRecordWithBlob(Abbrev, Record, Buffer);46644665// Emit the contents of the extension block.4666Writer.writeExtensionContents(SemaRef, Stream);46674668// Exit the extension block.4669Stream.ExitBlock();4670}46714672//===----------------------------------------------------------------------===//4673// General Serialization Routines4674//===----------------------------------------------------------------------===//46754676void ASTRecordWriter::AddAttr(const Attr *A) {4677auto &Record = *this;4678// FIXME: Clang can't handle the serialization/deserialization of4679// preferred_name properly now. See4680// https://github.com/llvm/llvm-project/issues/56490 for example.4681if (!A || (isa<PreferredNameAttr>(A) &&4682Writer->isWritingStdCXXNamedModules()))4683return Record.push_back(0);46844685Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs46864687Record.AddIdentifierRef(A->getAttrName());4688Record.AddIdentifierRef(A->getScopeName());4689Record.AddSourceRange(A->getRange());4690Record.AddSourceLocation(A->getScopeLoc());4691Record.push_back(A->getParsedKind());4692Record.push_back(A->getSyntax());4693Record.push_back(A->getAttributeSpellingListIndexRaw());4694Record.push_back(A->isRegularKeywordAttribute());46954696#include "clang/Serialization/AttrPCHWrite.inc"4697}46984699/// Emit the list of attributes to the specified record.4700void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {4701push_back(Attrs.size());4702for (const auto *A : Attrs)4703AddAttr(A);4704}47054706void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {4707AddSourceLocation(Tok.getLocation(), Record);4708// FIXME: Should translate token kind to a stable encoding.4709Record.push_back(Tok.getKind());4710// FIXME: Should translate token flags to a stable encoding.4711Record.push_back(Tok.getFlags());47124713if (Tok.isAnnotation()) {4714AddSourceLocation(Tok.getAnnotationEndLoc(), Record);4715switch (Tok.getKind()) {4716case tok::annot_pragma_loop_hint: {4717auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());4718AddToken(Info->PragmaName, Record);4719AddToken(Info->Option, Record);4720Record.push_back(Info->Toks.size());4721for (const auto &T : Info->Toks)4722AddToken(T, Record);4723break;4724}4725case tok::annot_pragma_pack: {4726auto *Info =4727static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());4728Record.push_back(static_cast<unsigned>(Info->Action));4729AddString(Info->SlotLabel, Record);4730AddToken(Info->Alignment, Record);4731break;4732}4733// Some annotation tokens do not use the PtrData field.4734case tok::annot_pragma_openmp:4735case tok::annot_pragma_openmp_end:4736case tok::annot_pragma_unused:4737case tok::annot_pragma_openacc:4738case tok::annot_pragma_openacc_end:4739break;4740default:4741llvm_unreachable("missing serialization code for annotation token");4742}4743} else {4744Record.push_back(Tok.getLength());4745// FIXME: When reading literal tokens, reconstruct the literal pointer if it4746// is needed.4747AddIdentifierRef(Tok.getIdentifierInfo(), Record);4748}4749}47504751void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {4752Record.push_back(Str.size());4753Record.insert(Record.end(), Str.begin(), Str.end());4754}47554756bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {4757assert(Context && "should have context when outputting path");47584759// Leave special file names as they are.4760StringRef PathStr(Path.data(), Path.size());4761if (PathStr == "<built-in>" || PathStr == "<command line>")4762return false;47634764bool Changed =4765cleanPathForOutput(Context->getSourceManager().getFileManager(), Path);47664767// Remove a prefix to make the path relative, if relevant.4768const char *PathBegin = Path.data();4769const char *PathPtr =4770adjustFilenameForRelocatableAST(PathBegin, BaseDirectory);4771if (PathPtr != PathBegin) {4772Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));4773Changed = true;4774}47754776return Changed;4777}47784779void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {4780SmallString<128> FilePath(Path);4781PreparePathForOutput(FilePath);4782AddString(FilePath, Record);4783}47844785void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,4786StringRef Path) {4787SmallString<128> FilePath(Path);4788PreparePathForOutput(FilePath);4789Stream.EmitRecordWithBlob(Abbrev, Record, FilePath);4790}47914792void ASTWriter::AddVersionTuple(const VersionTuple &Version,4793RecordDataImpl &Record) {4794Record.push_back(Version.getMajor());4795if (std::optional<unsigned> Minor = Version.getMinor())4796Record.push_back(*Minor + 1);4797else4798Record.push_back(0);4799if (std::optional<unsigned> Subminor = Version.getSubminor())4800Record.push_back(*Subminor + 1);4801else4802Record.push_back(0);4803}48044805/// Note that the identifier II occurs at the given offset4806/// within the identifier table.4807void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {4808IdentifierID ID = IdentifierIDs[II];4809// Only store offsets new to this AST file. Other identifier names are looked4810// up earlier in the chain and thus don't need an offset.4811if (!isLocalIdentifierID(ID))4812return;48134814// For local identifiers, the module file index must be 0.48154816assert(ID != 0);4817ID -= NUM_PREDEF_IDENT_IDS;4818assert(ID < IdentifierOffsets.size());4819IdentifierOffsets[ID] = Offset;4820}48214822/// Note that the selector Sel occurs at the given offset4823/// within the method pool/selector table.4824void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {4825unsigned ID = SelectorIDs[Sel];4826assert(ID && "Unknown selector");4827// Don't record offsets for selectors that are also available in a different4828// file.4829if (ID < FirstSelectorID)4830return;4831SelectorOffsets[ID - FirstSelectorID] = Offset;4832}48334834ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,4835SmallVectorImpl<char> &Buffer,4836InMemoryModuleCache &ModuleCache,4837ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,4838bool IncludeTimestamps, bool BuildingImplicitModule,4839bool GeneratingReducedBMI)4840: Stream(Stream), Buffer(Buffer), ModuleCache(ModuleCache),4841IncludeTimestamps(IncludeTimestamps),4842BuildingImplicitModule(BuildingImplicitModule),4843GeneratingReducedBMI(GeneratingReducedBMI) {4844for (const auto &Ext : Extensions) {4845if (auto Writer = Ext->createExtensionWriter(*this))4846ModuleFileExtensionWriters.push_back(std::move(Writer));4847}4848}48494850ASTWriter::~ASTWriter() = default;48514852const LangOptions &ASTWriter::getLangOpts() const {4853assert(WritingAST && "can't determine lang opts when not writing AST");4854return Context->getLangOpts();4855}48564857time_t ASTWriter::getTimestampForOutput(const FileEntry *E) const {4858return IncludeTimestamps ? E->getModificationTime() : 0;4859}48604861ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile,4862Module *WritingModule, StringRef isysroot,4863bool ShouldCacheASTInMemory) {4864llvm::TimeTraceScope scope("WriteAST", OutputFile);4865WritingAST = true;48664867ASTHasCompilerErrors =4868SemaRef.PP.getDiagnostics().hasUncompilableErrorOccurred();48694870// Emit the file header.4871Stream.Emit((unsigned)'C', 8);4872Stream.Emit((unsigned)'P', 8);4873Stream.Emit((unsigned)'C', 8);4874Stream.Emit((unsigned)'H', 8);48754876WriteBlockInfoBlock();48774878Context = &SemaRef.Context;4879PP = &SemaRef.PP;4880this->WritingModule = WritingModule;4881ASTFileSignature Signature = WriteASTCore(SemaRef, isysroot, WritingModule);4882Context = nullptr;4883PP = nullptr;4884this->WritingModule = nullptr;4885this->BaseDirectory.clear();48864887WritingAST = false;4888if (ShouldCacheASTInMemory) {4889// Construct MemoryBuffer and update buffer manager.4890ModuleCache.addBuiltPCM(OutputFile,4891llvm::MemoryBuffer::getMemBufferCopy(4892StringRef(Buffer.begin(), Buffer.size())));4893}4894return Signature;4895}48964897template<typename Vector>4898static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) {4899for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();4900I != E; ++I) {4901Writer.GetDeclRef(*I);4902}4903}49044905template <typename Vector>4906static void AddLazyVectorEmiitedDecls(ASTWriter &Writer, Vector &Vec,4907ASTWriter::RecordData &Record) {4908for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();4909I != E; ++I) {4910Writer.AddEmittedDeclRef(*I, Record);4911}4912}49134914void ASTWriter::computeNonAffectingInputFiles() {4915SourceManager &SrcMgr = PP->getSourceManager();4916unsigned N = SrcMgr.local_sloc_entry_size();49174918IsSLocAffecting.resize(N, true);49194920if (!WritingModule)4921return;49224923auto AffectingModuleMaps = GetAffectingModuleMaps(*PP, WritingModule);49244925unsigned FileIDAdjustment = 0;4926unsigned OffsetAdjustment = 0;49274928NonAffectingFileIDAdjustments.reserve(N);4929NonAffectingOffsetAdjustments.reserve(N);49304931NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);4932NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);49334934for (unsigned I = 1; I != N; ++I) {4935const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);4936FileID FID = FileID::get(I);4937assert(&SrcMgr.getSLocEntry(FID) == SLoc);49384939if (!SLoc->isFile())4940continue;4941const SrcMgr::FileInfo &File = SLoc->getFile();4942const SrcMgr::ContentCache *Cache = &File.getContentCache();4943if (!Cache->OrigEntry)4944continue;49454946// Don't prune anything other than module maps.4947if (!isModuleMap(File.getFileCharacteristic()))4948continue;49494950// Don't prune module maps if all are guaranteed to be affecting.4951if (!AffectingModuleMaps)4952continue;49534954// Don't prune module maps that are affecting.4955if (llvm::is_contained(*AffectingModuleMaps, *Cache->OrigEntry))4956continue;49574958IsSLocAffecting[I] = false;49594960FileIDAdjustment += 1;4961// Even empty files take up one element in the offset table.4962OffsetAdjustment += SrcMgr.getFileIDSize(FID) + 1;49634964// If the previous file was non-affecting as well, just extend its entry4965// with our information.4966if (!NonAffectingFileIDs.empty() &&4967NonAffectingFileIDs.back().ID == FID.ID - 1) {4968NonAffectingFileIDs.back() = FID;4969NonAffectingRanges.back().setEnd(SrcMgr.getLocForEndOfFile(FID));4970NonAffectingFileIDAdjustments.back() = FileIDAdjustment;4971NonAffectingOffsetAdjustments.back() = OffsetAdjustment;4972continue;4973}49744975NonAffectingFileIDs.push_back(FID);4976NonAffectingRanges.emplace_back(SrcMgr.getLocForStartOfFile(FID),4977SrcMgr.getLocForEndOfFile(FID));4978NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);4979NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);4980}49814982if (!PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesIncludeVFSUsage)4983return;49844985FileManager &FileMgr = PP->getFileManager();4986FileMgr.trackVFSUsage(true);4987// Lookup the paths in the VFS to trigger `-ivfsoverlay` usage tracking.4988for (StringRef Path :4989PP->getHeaderSearchInfo().getHeaderSearchOpts().VFSOverlayFiles)4990FileMgr.getVirtualFileSystem().exists(Path);4991for (unsigned I = 1; I != N; ++I) {4992if (IsSLocAffecting[I]) {4993const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);4994if (!SLoc->isFile())4995continue;4996const SrcMgr::FileInfo &File = SLoc->getFile();4997const SrcMgr::ContentCache *Cache = &File.getContentCache();4998if (!Cache->OrigEntry)4999continue;5000FileMgr.getVirtualFileSystem().exists(5001Cache->OrigEntry->getNameAsRequested());5002}5003}5004FileMgr.trackVFSUsage(false);5005}50065007void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {5008ASTContext &Context = SemaRef.Context;50095010bool isModule = WritingModule != nullptr;50115012// Set up predefined declaration IDs.5013auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {5014if (D) {5015assert(D->isCanonicalDecl() && "predefined decl is not canonical");5016DeclIDs[D] = ID;5017PredefinedDecls.insert(D);5018}5019};5020RegisterPredefDecl(Context.getTranslationUnitDecl(),5021PREDEF_DECL_TRANSLATION_UNIT_ID);5022RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID);5023RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID);5024RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID);5025RegisterPredefDecl(Context.ObjCProtocolClassDecl,5026PREDEF_DECL_OBJC_PROTOCOL_ID);5027RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID);5028RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID);5029RegisterPredefDecl(Context.ObjCInstanceTypeDecl,5030PREDEF_DECL_OBJC_INSTANCETYPE_ID);5031RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);5032RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG);5033RegisterPredefDecl(Context.BuiltinMSVaListDecl,5034PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);5035RegisterPredefDecl(Context.MSGuidTagDecl,5036PREDEF_DECL_BUILTIN_MS_GUID_ID);5037RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);5038RegisterPredefDecl(Context.MakeIntegerSeqDecl,5039PREDEF_DECL_MAKE_INTEGER_SEQ_ID);5040RegisterPredefDecl(Context.CFConstantStringTypeDecl,5041PREDEF_DECL_CF_CONSTANT_STRING_ID);5042RegisterPredefDecl(Context.CFConstantStringTagDecl,5043PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);5044RegisterPredefDecl(Context.TypePackElementDecl,5045PREDEF_DECL_TYPE_PACK_ELEMENT_ID);50465047const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();50485049// Force all top level declarations to be emitted.5050//5051// We start emitting top level declarations from the module purview to5052// implement the eliding unreachable declaration feature.5053for (const auto *D : TU->noload_decls()) {5054if (D->isFromASTFile())5055continue;50565057if (GeneratingReducedBMI) {5058if (D->isFromExplicitGlobalModule())5059continue;50605061// Don't force emitting static entities.5062//5063// Technically, all static entities shouldn't be in reduced BMI. The5064// language also specifies that the program exposes TU-local entities5065// is ill-formed. However, in practice, there are a lot of projects5066// uses `static inline` in the headers. So we can't get rid of all5067// static entities in reduced BMI now.5068if (IsInternalDeclFromFileContext(D))5069continue;5070}50715072// If we're writing C++ named modules, don't emit declarations which are5073// not from modules by default. They may be built in declarations (be5074// handled above) or implcit declarations (see the implementation of5075// `Sema::Initialize()` for example).5076if (isWritingStdCXXNamedModules() && !D->getOwningModule() &&5077D->isImplicit())5078continue;50795080GetDeclRef(D);5081}50825083if (GeneratingReducedBMI)5084return;50855086// Writing all of the tentative definitions in this file, in5087// TentativeDefinitions order. Generally, this record will be empty for5088// headers.5089RecordData TentativeDefinitions;5090AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions);50915092// Writing all of the file scoped decls in this file.5093if (!isModule)5094AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls);50955096// Writing all of the delegating constructors we still need5097// to resolve.5098if (!isModule)5099AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls);51005101// Writing all of the ext_vector declarations.5102AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls);51035104// Writing all of the VTable uses information.5105if (!SemaRef.VTableUses.empty())5106for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I)5107GetDeclRef(SemaRef.VTableUses[I].first);51085109// Writing all of the UnusedLocalTypedefNameCandidates.5110for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)5111GetDeclRef(TD);51125113// Writing all of pending implicit instantiations.5114for (const auto &I : SemaRef.PendingInstantiations)5115GetDeclRef(I.first);5116assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&5117"There are local ones at end of translation unit!");51185119// Writing some declaration references.5120if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {5121GetDeclRef(SemaRef.getStdNamespace());5122GetDeclRef(SemaRef.getStdBadAlloc());5123GetDeclRef(SemaRef.getStdAlignValT());5124}51255126if (Context.getcudaConfigureCallDecl())5127GetDeclRef(Context.getcudaConfigureCallDecl());51285129// Writing all of the known namespaces.5130for (const auto &I : SemaRef.KnownNamespaces)5131if (!I.second)5132GetDeclRef(I.first);51335134// Writing all used, undefined objects that require definitions.5135SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;5136SemaRef.getUndefinedButUsed(Undefined);5137for (const auto &I : Undefined)5138GetDeclRef(I.first);51395140// Writing all delete-expressions that we would like to5141// analyze later in AST.5142if (!isModule)5143for (const auto &DeleteExprsInfo :5144SemaRef.getMismatchingDeleteExpressions())5145GetDeclRef(DeleteExprsInfo.first);51465147// Make sure visible decls, added to DeclContexts previously loaded from5148// an AST file, are registered for serialization. Likewise for template5149// specializations added to imported templates.5150for (const auto *I : DeclsToEmitEvenIfUnreferenced)5151GetDeclRef(I);5152DeclsToEmitEvenIfUnreferenced.clear();51535154// Make sure all decls associated with an identifier are registered for5155// serialization, if we're storing decls with identifiers.5156if (!WritingModule || !getLangOpts().CPlusPlus) {5157llvm::SmallVector<const IdentifierInfo*, 256> IIs;5158for (const auto &ID : SemaRef.PP.getIdentifierTable()) {5159const IdentifierInfo *II = ID.second;5160if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization())5161IIs.push_back(II);5162}5163// Sort the identifiers to visit based on their name.5164llvm::sort(IIs, llvm::deref<std::less<>>());5165for (const IdentifierInfo *II : IIs)5166for (const Decl *D : SemaRef.IdResolver.decls(II))5167GetDeclRef(D);5168}51695170// Write all of the DeclsToCheckForDeferredDiags.5171for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)5172GetDeclRef(D);51735174// Write all classes that need to emit the vtable definitions if required.5175if (isWritingStdCXXNamedModules())5176for (CXXRecordDecl *RD : PendingEmittingVTables)5177GetDeclRef(RD);5178else5179PendingEmittingVTables.clear();5180}51815182void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {5183ASTContext &Context = SemaRef.Context;51845185bool isModule = WritingModule != nullptr;51865187// Write the record containing external, unnamed definitions.5188if (!EagerlyDeserializedDecls.empty())5189Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);51905191if (!ModularCodegenDecls.empty())5192Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls);51935194// Write the record containing tentative definitions.5195RecordData TentativeDefinitions;5196AddLazyVectorEmiitedDecls(*this, SemaRef.TentativeDefinitions,5197TentativeDefinitions);5198if (!TentativeDefinitions.empty())5199Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);52005201// Write the record containing unused file scoped decls.5202RecordData UnusedFileScopedDecls;5203if (!isModule)5204AddLazyVectorEmiitedDecls(*this, SemaRef.UnusedFileScopedDecls,5205UnusedFileScopedDecls);5206if (!UnusedFileScopedDecls.empty())5207Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);52085209// Write the record containing ext_vector type names.5210RecordData ExtVectorDecls;5211AddLazyVectorEmiitedDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls);5212if (!ExtVectorDecls.empty())5213Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);52145215// Write the record containing VTable uses information.5216RecordData VTableUses;5217if (!SemaRef.VTableUses.empty()) {5218for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {5219CXXRecordDecl *D = SemaRef.VTableUses[I].first;5220if (!wasDeclEmitted(D))5221continue;52225223AddDeclRef(D, VTableUses);5224AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);5225VTableUses.push_back(SemaRef.VTablesUsed[D]);5226}5227Stream.EmitRecord(VTABLE_USES, VTableUses);5228}52295230// Write the record containing potentially unused local typedefs.5231RecordData UnusedLocalTypedefNameCandidates;5232for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates)5233AddEmittedDeclRef(TD, UnusedLocalTypedefNameCandidates);5234if (!UnusedLocalTypedefNameCandidates.empty())5235Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,5236UnusedLocalTypedefNameCandidates);52375238// Write the record containing pending implicit instantiations.5239RecordData PendingInstantiations;5240for (const auto &I : SemaRef.PendingInstantiations) {5241if (!wasDeclEmitted(I.first))5242continue;52435244AddDeclRef(I.first, PendingInstantiations);5245AddSourceLocation(I.second, PendingInstantiations);5246}5247if (!PendingInstantiations.empty())5248Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);52495250// Write the record containing declaration references of Sema.5251RecordData SemaDeclRefs;5252if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {5253auto AddEmittedDeclRefOrZero = [this, &SemaDeclRefs](Decl *D) {5254if (!D || !wasDeclEmitted(D))5255SemaDeclRefs.push_back(0);5256else5257AddDeclRef(D, SemaDeclRefs);5258};52595260AddEmittedDeclRefOrZero(SemaRef.getStdNamespace());5261AddEmittedDeclRefOrZero(SemaRef.getStdBadAlloc());5262AddEmittedDeclRefOrZero(SemaRef.getStdAlignValT());5263}5264if (!SemaDeclRefs.empty())5265Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);52665267// Write the record containing decls to be checked for deferred diags.5268RecordData DeclsToCheckForDeferredDiags;5269for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)5270if (wasDeclEmitted(D))5271AddDeclRef(D, DeclsToCheckForDeferredDiags);5272if (!DeclsToCheckForDeferredDiags.empty())5273Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,5274DeclsToCheckForDeferredDiags);52755276// Write the record containing CUDA-specific declaration references.5277RecordData CUDASpecialDeclRefs;5278if (auto *CudaCallDecl = Context.getcudaConfigureCallDecl();5279CudaCallDecl && wasDeclEmitted(CudaCallDecl)) {5280AddDeclRef(CudaCallDecl, CUDASpecialDeclRefs);5281Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);5282}52835284// Write the delegating constructors.5285RecordData DelegatingCtorDecls;5286if (!isModule)5287AddLazyVectorEmiitedDecls(*this, SemaRef.DelegatingCtorDecls,5288DelegatingCtorDecls);5289if (!DelegatingCtorDecls.empty())5290Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);52915292// Write the known namespaces.5293RecordData KnownNamespaces;5294for (const auto &I : SemaRef.KnownNamespaces) {5295if (!I.second && wasDeclEmitted(I.first))5296AddDeclRef(I.first, KnownNamespaces);5297}5298if (!KnownNamespaces.empty())5299Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);53005301// Write the undefined internal functions and variables, and inline functions.5302RecordData UndefinedButUsed;5303SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;5304SemaRef.getUndefinedButUsed(Undefined);5305for (const auto &I : Undefined) {5306if (!wasDeclEmitted(I.first))5307continue;53085309AddDeclRef(I.first, UndefinedButUsed);5310AddSourceLocation(I.second, UndefinedButUsed);5311}5312if (!UndefinedButUsed.empty())5313Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);53145315// Write all delete-expressions that we would like to5316// analyze later in AST.5317RecordData DeleteExprsToAnalyze;5318if (!isModule) {5319for (const auto &DeleteExprsInfo :5320SemaRef.getMismatchingDeleteExpressions()) {5321if (!wasDeclEmitted(DeleteExprsInfo.first))5322continue;53235324AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);5325DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());5326for (const auto &DeleteLoc : DeleteExprsInfo.second) {5327AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);5328DeleteExprsToAnalyze.push_back(DeleteLoc.second);5329}5330}5331}5332if (!DeleteExprsToAnalyze.empty())5333Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);53345335RecordData VTablesToEmit;5336for (CXXRecordDecl *RD : PendingEmittingVTables) {5337if (!wasDeclEmitted(RD))5338continue;53395340AddDeclRef(RD, VTablesToEmit);5341}53425343if (!VTablesToEmit.empty())5344Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit);5345}53465347ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,5348Module *WritingModule) {5349using namespace llvm;53505351bool isModule = WritingModule != nullptr;53525353// Make sure that the AST reader knows to finalize itself.5354if (Chain)5355Chain->finalizeForWriting();53565357ASTContext &Context = SemaRef.Context;5358Preprocessor &PP = SemaRef.PP;53595360// This needs to be done very early, since everything that writes5361// SourceLocations or FileIDs depends on it.5362computeNonAffectingInputFiles();53635364writeUnhashedControlBlock(PP, Context);53655366// Don't reuse type ID and Identifier ID from readers for C++ standard named5367// modules since we want to support no-transitive-change model for named5368// modules. The theory for no-transitive-change model is,5369// for a user of a named module, the user can only access the indirectly5370// imported decls via the directly imported module. So that it is possible to5371// control what matters to the users when writing the module. It would be5372// problematic if the users can reuse the type IDs and identifier IDs from5373// indirectly imported modules arbitrarily. So we choose to clear these ID5374// here.5375if (isWritingStdCXXNamedModules()) {5376TypeIdxs.clear();5377IdentifierIDs.clear();5378}53795380// Look for any identifiers that were named while processing the5381// headers, but are otherwise not needed. We add these to the hash5382// table to enable checking of the predefines buffer in the case5383// where the user adds new macro definitions when building the AST5384// file.5385//5386// We do this before emitting any Decl and Types to make sure the5387// Identifier ID is stable.5388SmallVector<const IdentifierInfo *, 128> IIs;5389for (const auto &ID : PP.getIdentifierTable())5390if (IsInterestingNonMacroIdentifier(ID.second, *this))5391IIs.push_back(ID.second);5392// Sort the identifiers lexicographically before getting the references so5393// that their order is stable.5394llvm::sort(IIs, llvm::deref<std::less<>>());5395for (const IdentifierInfo *II : IIs)5396getIdentifierRef(II);53975398// Write the set of weak, undeclared identifiers. We always write the5399// entire table, since later PCH files in a PCH chain are only interested in5400// the results at the end of the chain.5401RecordData WeakUndeclaredIdentifiers;5402for (const auto &WeakUndeclaredIdentifierList :5403SemaRef.WeakUndeclaredIdentifiers) {5404const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first;5405for (const auto &WI : WeakUndeclaredIdentifierList.second) {5406AddIdentifierRef(II, WeakUndeclaredIdentifiers);5407AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers);5408AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers);5409}5410}54115412// Form the record of special types.5413RecordData SpecialTypes;5414AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes);5415AddTypeRef(Context.getFILEType(), SpecialTypes);5416AddTypeRef(Context.getjmp_bufType(), SpecialTypes);5417AddTypeRef(Context.getsigjmp_bufType(), SpecialTypes);5418AddTypeRef(Context.ObjCIdRedefinitionType, SpecialTypes);5419AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes);5420AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes);5421AddTypeRef(Context.getucontext_tType(), SpecialTypes);54225423PrepareWritingSpecialDecls(SemaRef);54245425// Write the control block5426WriteControlBlock(PP, Context, isysroot);54275428// Write the remaining AST contents.5429Stream.FlushToWord();5430ASTBlockRange.first = Stream.GetCurrentBitNo() >> 3;5431Stream.EnterSubblock(AST_BLOCK_ID, 5);5432ASTBlockStartOffset = Stream.GetCurrentBitNo();54335434// This is so that older clang versions, before the introduction5435// of the control block, can read and reject the newer PCH format.5436{5437RecordData Record = {VERSION_MAJOR};5438Stream.EmitRecord(METADATA_OLD_FORMAT, Record);5439}54405441// For method pool in the module, if it contains an entry for a selector,5442// the entry should be complete, containing everything introduced by that5443// module and all modules it imports. It's possible that the entry is out of5444// date, so we need to pull in the new content here.54455446// It's possible that updateOutOfDateSelector can update SelectorIDs. To be5447// safe, we copy all selectors out.5448llvm::SmallVector<Selector, 256> AllSelectors;5449for (auto &SelectorAndID : SelectorIDs)5450AllSelectors.push_back(SelectorAndID.first);5451for (auto &Selector : AllSelectors)5452SemaRef.ObjC().updateOutOfDateSelector(Selector);54535454if (Chain) {5455// Write the mapping information describing our module dependencies and how5456// each of those modules were mapped into our own offset/ID space, so that5457// the reader can build the appropriate mapping to its own offset/ID space.5458// The map consists solely of a blob with the following format:5459// *(module-kind:i85460// module-name-len:i16 module-name:len*i85461// source-location-offset:i325462// identifier-id:i325463// preprocessed-entity-id:i325464// macro-definition-id:i325465// submodule-id:i325466// selector-id:i325467// declaration-id:i325468// c++-base-specifiers-id:i325469// type-id:i32)5470//5471// module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule,5472// MK_ExplicitModule or MK_ImplicitModule, then the module-name is the5473// module name. Otherwise, it is the module file name.5474auto Abbrev = std::make_shared<BitCodeAbbrev>();5475Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));5476Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));5477unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(std::move(Abbrev));5478SmallString<2048> Buffer;5479{5480llvm::raw_svector_ostream Out(Buffer);5481for (ModuleFile &M : Chain->ModuleMgr) {5482using namespace llvm::support;54835484endian::Writer LE(Out, llvm::endianness::little);5485LE.write<uint8_t>(static_cast<uint8_t>(M.Kind));5486StringRef Name = M.isModule() ? M.ModuleName : M.FileName;5487LE.write<uint16_t>(Name.size());5488Out.write(Name.data(), Name.size());54895490// Note: if a base ID was uint max, it would not be possible to load5491// another module after it or have more than one entity inside it.5492uint32_t None = std::numeric_limits<uint32_t>::max();54935494auto writeBaseIDOrNone = [&](auto BaseID, bool ShouldWrite) {5495assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high");5496if (ShouldWrite)5497LE.write<uint32_t>(BaseID);5498else5499LE.write<uint32_t>(None);5500};55015502// These values should be unique within a chain, since they will be read5503// as keys into ContinuousRangeMaps.5504writeBaseIDOrNone(M.BaseMacroID, M.LocalNumMacros);5505writeBaseIDOrNone(M.BasePreprocessedEntityID,5506M.NumPreprocessedEntities);5507writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules);5508writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors);5509}5510}5511RecordData::value_type Record[] = {MODULE_OFFSET_MAP};5512Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,5513Buffer.data(), Buffer.size());5514}55155516WriteDeclAndTypes(Context);55175518WriteFileDeclIDsMap();5519WriteSourceManagerBlock(Context.getSourceManager(), PP);5520WriteComments();5521WritePreprocessor(PP, isModule);5522WriteHeaderSearch(PP.getHeaderSearchInfo());5523WriteSelectors(SemaRef);5524WriteReferencedSelectorsPool(SemaRef);5525WriteLateParsedTemplates(SemaRef);5526WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);5527WriteFPPragmaOptions(SemaRef.CurFPFeatureOverrides());5528WriteOpenCLExtensions(SemaRef);5529WriteCUDAPragmas(SemaRef);55305531// If we're emitting a module, write out the submodule information.5532if (WritingModule)5533WriteSubmodules(WritingModule);55345535Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);55365537WriteSpecialDeclRecords(SemaRef);55385539// Write the record containing weak undeclared identifiers.5540if (!WeakUndeclaredIdentifiers.empty())5541Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,5542WeakUndeclaredIdentifiers);55435544if (!WritingModule) {5545// Write the submodules that were imported, if any.5546struct ModuleInfo {5547uint64_t ID;5548Module *M;5549ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {}5550};5551llvm::SmallVector<ModuleInfo, 64> Imports;5552for (const auto *I : Context.local_imports()) {5553assert(SubmoduleIDs.contains(I->getImportedModule()));5554Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()],5555I->getImportedModule()));5556}55575558if (!Imports.empty()) {5559auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) {5560return A.ID < B.ID;5561};5562auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) {5563return A.ID == B.ID;5564};55655566// Sort and deduplicate module IDs.5567llvm::sort(Imports, Cmp);5568Imports.erase(std::unique(Imports.begin(), Imports.end(), Eq),5569Imports.end());55705571RecordData ImportedModules;5572for (const auto &Import : Imports) {5573ImportedModules.push_back(Import.ID);5574// FIXME: If the module has macros imported then later has declarations5575// imported, this location won't be the right one as a location for the5576// declaration imports.5577AddSourceLocation(PP.getModuleImportLoc(Import.M), ImportedModules);5578}55795580Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);5581}5582}55835584WriteObjCCategories();5585if(!WritingModule) {5586WriteOptimizePragmaOptions(SemaRef);5587WriteMSStructPragmaOptions(SemaRef);5588WriteMSPointersToMembersPragmaOptions(SemaRef);5589}5590WritePackPragmaOptions(SemaRef);5591WriteFloatControlPragmaOptions(SemaRef);55925593// Some simple statistics5594RecordData::value_type Record[] = {5595NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts};5596Stream.EmitRecord(STATISTICS, Record);5597Stream.ExitBlock();5598Stream.FlushToWord();5599ASTBlockRange.second = Stream.GetCurrentBitNo() >> 3;56005601// Write the module file extension blocks.5602for (const auto &ExtWriter : ModuleFileExtensionWriters)5603WriteModuleFileExtension(SemaRef, *ExtWriter);56045605return backpatchSignature();5606}56075608void ASTWriter::EnteringModulePurview() {5609// In C++20 named modules, all entities before entering the module purview5610// lives in the GMF.5611if (GeneratingReducedBMI)5612DeclUpdatesFromGMF.swap(DeclUpdates);5613}56145615// Add update records for all mangling numbers and static local numbers.5616// These aren't really update records, but this is a convenient way of5617// tagging this rare extra data onto the declarations.5618void ASTWriter::AddedManglingNumber(const Decl *D, unsigned Number) {5619if (D->isFromASTFile())5620return;56215622DeclUpdates[D].push_back(DeclUpdate(UPD_MANGLING_NUMBER, Number));5623}5624void ASTWriter::AddedStaticLocalNumbers(const Decl *D, unsigned Number) {5625if (D->isFromASTFile())5626return;56275628DeclUpdates[D].push_back(DeclUpdate(UPD_STATIC_LOCAL_NUMBER, Number));5629}56305631void ASTWriter::AddedAnonymousNamespace(const TranslationUnitDecl *TU,5632NamespaceDecl *AnonNamespace) {5633// If the translation unit has an anonymous namespace, and we don't already5634// have an update block for it, write it as an update block.5635// FIXME: Why do we not do this if there's already an update block?5636if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {5637ASTWriter::UpdateRecord &Record = DeclUpdates[TU];5638if (Record.empty())5639Record.push_back(DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, NS));5640}5641}56425643void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {5644// Keep writing types, declarations, and declaration update records5645// until we've emitted all of them.5646RecordData DeclUpdatesOffsetsRecord;5647Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/5);5648DeclTypesBlockStartOffset = Stream.GetCurrentBitNo();5649WriteTypeAbbrevs();5650WriteDeclAbbrevs();5651do {5652WriteDeclUpdatesBlocks(DeclUpdatesOffsetsRecord);5653while (!DeclTypesToEmit.empty()) {5654DeclOrType DOT = DeclTypesToEmit.front();5655DeclTypesToEmit.pop();5656if (DOT.isType())5657WriteType(DOT.getType());5658else5659WriteDecl(Context, DOT.getDecl());5660}5661} while (!DeclUpdates.empty());56625663DoneWritingDeclsAndTypes = true;56645665// DelayedNamespace is only meaningful in reduced BMI.5666// See the comments of DelayedNamespace for details.5667assert(DelayedNamespace.empty() || GeneratingReducedBMI);5668RecordData DelayedNamespaceRecord;5669for (NamespaceDecl *NS : DelayedNamespace) {5670uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS);5671uint64_t VisibleOffset = WriteDeclContextVisibleBlock(Context, NS);56725673// Write the offset relative to current block.5674if (LexicalOffset)5675LexicalOffset -= DeclTypesBlockStartOffset;56765677if (VisibleOffset)5678VisibleOffset -= DeclTypesBlockStartOffset;56795680AddDeclRef(NS, DelayedNamespaceRecord);5681DelayedNamespaceRecord.push_back(LexicalOffset);5682DelayedNamespaceRecord.push_back(VisibleOffset);5683}56845685// The process of writing lexical and visible block for delayed namespace5686// shouldn't introduce any new decls, types or update to emit.5687assert(DeclTypesToEmit.empty());5688assert(DeclUpdates.empty());56895690Stream.ExitBlock();56915692// These things can only be done once we've written out decls and types.5693WriteTypeDeclOffsets();5694if (!DeclUpdatesOffsetsRecord.empty())5695Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);56965697if (!DelayedNamespaceRecord.empty())5698Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,5699DelayedNamespaceRecord);57005701const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();5702// Create a lexical update block containing all of the declarations in the5703// translation unit that do not come from other AST files.5704SmallVector<DeclID, 128> NewGlobalKindDeclPairs;5705for (const auto *D : TU->noload_decls()) {5706if (D->isFromASTFile())5707continue;57085709// In reduced BMI, skip unreached declarations.5710if (!wasDeclEmitted(D))5711continue;57125713NewGlobalKindDeclPairs.push_back(D->getKind());5714NewGlobalKindDeclPairs.push_back(GetDeclRef(D).getRawValue());5715}57165717auto Abv = std::make_shared<llvm::BitCodeAbbrev>();5718Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));5719Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));5720unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));57215722RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};5723Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,5724bytes(NewGlobalKindDeclPairs));57255726Abv = std::make_shared<llvm::BitCodeAbbrev>();5727Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));5728Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));5729Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));5730UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));57315732// And a visible updates block for the translation unit.5733WriteDeclContextVisibleUpdate(TU);57345735// If we have any extern "C" names, write out a visible update for them.5736if (Context.ExternCContext)5737WriteDeclContextVisibleUpdate(Context.ExternCContext);57385739// Write the visible updates to DeclContexts.5740for (auto *DC : UpdatedDeclContexts)5741WriteDeclContextVisibleUpdate(DC);5742}57435744void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {5745if (DeclUpdates.empty())5746return;57475748DeclUpdateMap LocalUpdates;5749LocalUpdates.swap(DeclUpdates);57505751for (auto &DeclUpdate : LocalUpdates) {5752const Decl *D = DeclUpdate.first;57535754bool HasUpdatedBody = false;5755bool HasAddedVarDefinition = false;5756RecordData RecordData;5757ASTRecordWriter Record(*this, RecordData);5758for (auto &Update : DeclUpdate.second) {5759DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind();57605761// An updated body is emitted last, so that the reader doesn't need5762// to skip over the lazy body to reach statements for other records.5763if (Kind == UPD_CXX_ADDED_FUNCTION_DEFINITION)5764HasUpdatedBody = true;5765else if (Kind == UPD_CXX_ADDED_VAR_DEFINITION)5766HasAddedVarDefinition = true;5767else5768Record.push_back(Kind);57695770switch (Kind) {5771case UPD_CXX_ADDED_IMPLICIT_MEMBER:5772case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:5773case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE:5774assert(Update.getDecl() && "no decl to add?");5775Record.AddDeclRef(Update.getDecl());5776break;57775778case UPD_CXX_ADDED_FUNCTION_DEFINITION:5779case UPD_CXX_ADDED_VAR_DEFINITION:5780break;57815782case UPD_CXX_POINT_OF_INSTANTIATION:5783// FIXME: Do we need to also save the template specialization kind here?5784Record.AddSourceLocation(Update.getLoc());5785break;57865787case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT:5788Record.writeStmtRef(5789cast<ParmVarDecl>(Update.getDecl())->getDefaultArg());5790break;57915792case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER:5793Record.AddStmt(5794cast<FieldDecl>(Update.getDecl())->getInClassInitializer());5795break;57965797case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {5798auto *RD = cast<CXXRecordDecl>(D);5799UpdatedDeclContexts.insert(RD->getPrimaryContext());5800Record.push_back(RD->isParamDestroyedInCallee());5801Record.push_back(llvm::to_underlying(RD->getArgPassingRestrictions()));5802Record.AddCXXDefinitionData(RD);5803Record.AddOffset(WriteDeclContextLexicalBlock(*Context, RD));58045805// This state is sometimes updated by template instantiation, when we5806// switch from the specialization referring to the template declaration5807// to it referring to the template definition.5808if (auto *MSInfo = RD->getMemberSpecializationInfo()) {5809Record.push_back(MSInfo->getTemplateSpecializationKind());5810Record.AddSourceLocation(MSInfo->getPointOfInstantiation());5811} else {5812auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);5813Record.push_back(Spec->getTemplateSpecializationKind());5814Record.AddSourceLocation(Spec->getPointOfInstantiation());58155816// The instantiation might have been resolved to a partial5817// specialization. If so, record which one.5818auto From = Spec->getInstantiatedFrom();5819if (auto PartialSpec =5820From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) {5821Record.push_back(true);5822Record.AddDeclRef(PartialSpec);5823Record.AddTemplateArgumentList(5824&Spec->getTemplateInstantiationArgs());5825} else {5826Record.push_back(false);5827}5828}5829Record.push_back(llvm::to_underlying(RD->getTagKind()));5830Record.AddSourceLocation(RD->getLocation());5831Record.AddSourceLocation(RD->getBeginLoc());5832Record.AddSourceRange(RD->getBraceRange());58335834// Instantiation may change attributes; write them all out afresh.5835Record.push_back(D->hasAttrs());5836if (D->hasAttrs())5837Record.AddAttributes(D->getAttrs());58385839// FIXME: Ensure we don't get here for explicit instantiations.5840break;5841}58425843case UPD_CXX_RESOLVED_DTOR_DELETE:5844Record.AddDeclRef(Update.getDecl());5845Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg());5846break;58475848case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {5849auto prototype =5850cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>();5851Record.writeExceptionSpecInfo(prototype->getExceptionSpecInfo());5852break;5853}58545855case UPD_CXX_DEDUCED_RETURN_TYPE:5856Record.push_back(GetOrCreateTypeID(Update.getType()));5857break;58585859case UPD_DECL_MARKED_USED:5860break;58615862case UPD_MANGLING_NUMBER:5863case UPD_STATIC_LOCAL_NUMBER:5864Record.push_back(Update.getNumber());5865break;58665867case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:5868Record.AddSourceRange(5869D->getAttr<OMPThreadPrivateDeclAttr>()->getRange());5870break;58715872case UPD_DECL_MARKED_OPENMP_ALLOCATE: {5873auto *A = D->getAttr<OMPAllocateDeclAttr>();5874Record.push_back(A->getAllocatorType());5875Record.AddStmt(A->getAllocator());5876Record.AddStmt(A->getAlignment());5877Record.AddSourceRange(A->getRange());5878break;5879}58805881case UPD_DECL_MARKED_OPENMP_DECLARETARGET:5882Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType());5883Record.AddSourceRange(5884D->getAttr<OMPDeclareTargetDeclAttr>()->getRange());5885break;58865887case UPD_DECL_EXPORTED:5888Record.push_back(getSubmoduleID(Update.getModule()));5889break;58905891case UPD_ADDED_ATTR_TO_RECORD:5892Record.AddAttributes(llvm::ArrayRef(Update.getAttr()));5893break;5894}5895}58965897// Add a trailing update record, if any. These must go last because we5898// lazily load their attached statement.5899if (!GeneratingReducedBMI || !CanElideDeclDef(D)) {5900if (HasUpdatedBody) {5901const auto *Def = cast<FunctionDecl>(D);5902Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);5903Record.push_back(Def->isInlined());5904Record.AddSourceLocation(Def->getInnerLocStart());5905Record.AddFunctionDefinition(Def);5906} else if (HasAddedVarDefinition) {5907const auto *VD = cast<VarDecl>(D);5908Record.push_back(UPD_CXX_ADDED_VAR_DEFINITION);5909Record.push_back(VD->isInline());5910Record.push_back(VD->isInlineSpecified());5911Record.AddVarDeclInit(VD);5912}5913}59145915AddDeclRef(D, OffsetsRecord);5916OffsetsRecord.push_back(Record.Emit(DECL_UPDATES));5917}5918}59195920void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info,5921RecordDataImpl &Record) {5922uint32_t Raw = Sema::AlignPackInfo::getRawEncoding(Info);5923Record.push_back(Raw);5924}59255926FileID ASTWriter::getAdjustedFileID(FileID FID) const {5927if (FID.isInvalid() || PP->getSourceManager().isLoadedFileID(FID) ||5928NonAffectingFileIDs.empty())5929return FID;5930auto It = llvm::lower_bound(NonAffectingFileIDs, FID);5931unsigned Idx = std::distance(NonAffectingFileIDs.begin(), It);5932unsigned Offset = NonAffectingFileIDAdjustments[Idx];5933return FileID::get(FID.getOpaqueValue() - Offset);5934}59355936unsigned ASTWriter::getAdjustedNumCreatedFIDs(FileID FID) const {5937unsigned NumCreatedFIDs = PP->getSourceManager()5938.getLocalSLocEntry(FID.ID)5939.getFile()5940.NumCreatedFIDs;59415942unsigned AdjustedNumCreatedFIDs = 0;5943for (unsigned I = FID.ID, N = I + NumCreatedFIDs; I != N; ++I)5944if (IsSLocAffecting[I])5945++AdjustedNumCreatedFIDs;5946return AdjustedNumCreatedFIDs;5947}59485949SourceLocation ASTWriter::getAdjustedLocation(SourceLocation Loc) const {5950if (Loc.isInvalid())5951return Loc;5952return Loc.getLocWithOffset(-getAdjustment(Loc.getOffset()));5953}59545955SourceRange ASTWriter::getAdjustedRange(SourceRange Range) const {5956return SourceRange(getAdjustedLocation(Range.getBegin()),5957getAdjustedLocation(Range.getEnd()));5958}59595960SourceLocation::UIntTy5961ASTWriter::getAdjustedOffset(SourceLocation::UIntTy Offset) const {5962return Offset - getAdjustment(Offset);5963}59645965SourceLocation::UIntTy5966ASTWriter::getAdjustment(SourceLocation::UIntTy Offset) const {5967if (NonAffectingRanges.empty())5968return 0;59695970if (PP->getSourceManager().isLoadedOffset(Offset))5971return 0;59725973if (Offset > NonAffectingRanges.back().getEnd().getOffset())5974return NonAffectingOffsetAdjustments.back();59755976if (Offset < NonAffectingRanges.front().getBegin().getOffset())5977return 0;59785979auto Contains = [](const SourceRange &Range, SourceLocation::UIntTy Offset) {5980return Range.getEnd().getOffset() < Offset;5981};59825983auto It = llvm::lower_bound(NonAffectingRanges, Offset, Contains);5984unsigned Idx = std::distance(NonAffectingRanges.begin(), It);5985return NonAffectingOffsetAdjustments[Idx];5986}59875988void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) {5989Record.push_back(getAdjustedFileID(FID).getOpaqueValue());5990}59915992SourceLocationEncoding::RawLocEncoding5993ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq) {5994unsigned BaseOffset = 0;5995unsigned ModuleFileIndex = 0;59965997// See SourceLocationEncoding.h for the encoding details.5998if (Context->getSourceManager().isLoadedSourceLocation(Loc) &&5999Loc.isValid()) {6000assert(getChain());6001auto SLocMapI = getChain()->GlobalSLocOffsetMap.find(6002SourceManager::MaxLoadedOffset - Loc.getOffset() - 1);6003assert(SLocMapI != getChain()->GlobalSLocOffsetMap.end() &&6004"Corrupted global sloc offset map");6005ModuleFile *F = SLocMapI->second;6006BaseOffset = F->SLocEntryBaseOffset - 2;6007// 0 means the location is not loaded. So we need to add 1 to the index to6008// make it clear.6009ModuleFileIndex = F->Index + 1;6010assert(&getChain()->getModuleManager()[F->Index] == F);6011}60126013return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex, Seq);6014}60156016void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record,6017SourceLocationSequence *Seq) {6018Loc = getAdjustedLocation(Loc);6019Record.push_back(getRawSourceLocationEncoding(Loc, Seq));6020}60216022void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record,6023SourceLocationSequence *Seq) {6024AddSourceLocation(Range.getBegin(), Record, Seq);6025AddSourceLocation(Range.getEnd(), Record, Seq);6026}60276028void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) {6029AddAPInt(Value.bitcastToAPInt());6030}60316032void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {6033Record.push_back(getIdentifierRef(II));6034}60356036IdentifierID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {6037if (!II)6038return 0;60396040IdentifierID &ID = IdentifierIDs[II];6041if (ID == 0)6042ID = NextIdentID++;6043return ID;6044}60456046MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {6047// Don't emit builtin macros like __LINE__ to the AST file unless they6048// have been redefined by the header (in which case they are not6049// isBuiltinMacro).6050if (!MI || MI->isBuiltinMacro())6051return 0;60526053MacroID &ID = MacroIDs[MI];6054if (ID == 0) {6055ID = NextMacroID++;6056MacroInfoToEmitData Info = { Name, MI, ID };6057MacroInfosToEmit.push_back(Info);6058}6059return ID;6060}60616062MacroID ASTWriter::getMacroID(MacroInfo *MI) {6063if (!MI || MI->isBuiltinMacro())6064return 0;60656066assert(MacroIDs.contains(MI) && "Macro not emitted!");6067return MacroIDs[MI];6068}60696070uint32_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {6071return IdentMacroDirectivesOffsetMap.lookup(Name);6072}60736074void ASTRecordWriter::AddSelectorRef(const Selector SelRef) {6075Record->push_back(Writer->getSelectorRef(SelRef));6076}60776078SelectorID ASTWriter::getSelectorRef(Selector Sel) {6079if (Sel.getAsOpaquePtr() == nullptr) {6080return 0;6081}60826083SelectorID SID = SelectorIDs[Sel];6084if (SID == 0 && Chain) {6085// This might trigger a ReadSelector callback, which will set the ID for6086// this selector.6087Chain->LoadSelector(Sel);6088SID = SelectorIDs[Sel];6089}6090if (SID == 0) {6091SID = NextSelectorID++;6092SelectorIDs[Sel] = SID;6093}6094return SID;6095}60966097void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) {6098AddDeclRef(Temp->getDestructor());6099}61006101void ASTRecordWriter::AddTemplateArgumentLocInfo(6102TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg) {6103switch (Kind) {6104case TemplateArgument::Expression:6105AddStmt(Arg.getAsExpr());6106break;6107case TemplateArgument::Type:6108AddTypeSourceInfo(Arg.getAsTypeSourceInfo());6109break;6110case TemplateArgument::Template:6111AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());6112AddSourceLocation(Arg.getTemplateNameLoc());6113break;6114case TemplateArgument::TemplateExpansion:6115AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());6116AddSourceLocation(Arg.getTemplateNameLoc());6117AddSourceLocation(Arg.getTemplateEllipsisLoc());6118break;6119case TemplateArgument::Null:6120case TemplateArgument::Integral:6121case TemplateArgument::Declaration:6122case TemplateArgument::NullPtr:6123case TemplateArgument::StructuralValue:6124case TemplateArgument::Pack:6125// FIXME: Is this right?6126break;6127}6128}61296130void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) {6131AddTemplateArgument(Arg.getArgument());61326133if (Arg.getArgument().getKind() == TemplateArgument::Expression) {6134bool InfoHasSameExpr6135= Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr();6136Record->push_back(InfoHasSameExpr);6137if (InfoHasSameExpr)6138return; // Avoid storing the same expr twice.6139}6140AddTemplateArgumentLocInfo(Arg.getArgument().getKind(), Arg.getLocInfo());6141}61426143void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) {6144if (!TInfo) {6145AddTypeRef(QualType());6146return;6147}61486149AddTypeRef(TInfo->getType());6150AddTypeLoc(TInfo->getTypeLoc());6151}61526153void ASTRecordWriter::AddTypeLoc(TypeLoc TL, LocSeq *OuterSeq) {6154LocSeq::State Seq(OuterSeq);6155TypeLocWriter TLW(*this, Seq);6156for (; !TL.isNull(); TL = TL.getNextTypeLoc())6157TLW.Visit(TL);6158}61596160void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) {6161Record.push_back(GetOrCreateTypeID(T));6162}61636164template <typename IdxForTypeTy>6165static TypeID MakeTypeID(ASTContext &Context, QualType T,6166IdxForTypeTy IdxForType) {6167if (T.isNull())6168return PREDEF_TYPE_NULL_ID;61696170unsigned FastQuals = T.getLocalFastQualifiers();6171T.removeLocalFastQualifiers();61726173if (T.hasLocalNonFastQualifiers())6174return IdxForType(T).asTypeID(FastQuals);61756176assert(!T.hasLocalQualifiers());61776178if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))6179return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);61806181if (T == Context.AutoDeductTy)6182return TypeIdx(0, PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals);6183if (T == Context.AutoRRefDeductTy)6184return TypeIdx(0, PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals);61856186return IdxForType(T).asTypeID(FastQuals);6187}61886189TypeID ASTWriter::GetOrCreateTypeID(QualType T) {6190assert(Context);6191return MakeTypeID(*Context, T, [&](QualType T) -> TypeIdx {6192if (T.isNull())6193return TypeIdx();6194assert(!T.getLocalFastQualifiers());61956196TypeIdx &Idx = TypeIdxs[T];6197if (Idx.getValue() == 0) {6198if (DoneWritingDeclsAndTypes) {6199assert(0 && "New type seen after serializing all the types to emit!");6200return TypeIdx();6201}62026203// We haven't seen this type before. Assign it a new ID and put it6204// into the queue of types to emit.6205Idx = TypeIdx(0, NextTypeID++);6206DeclTypesToEmit.push(T);6207}6208return Idx;6209});6210}62116212void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) {6213if (!wasDeclEmitted(D))6214return;62156216AddDeclRef(D, Record);6217}62186219void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {6220Record.push_back(GetDeclRef(D).getRawValue());6221}62226223LocalDeclID ASTWriter::GetDeclRef(const Decl *D) {6224assert(WritingAST && "Cannot request a declaration ID before AST writing");62256226if (!D) {6227return LocalDeclID();6228}62296230// If the DeclUpdate from the GMF gets touched, emit it.6231if (auto *Iter = DeclUpdatesFromGMF.find(D);6232Iter != DeclUpdatesFromGMF.end()) {6233for (DeclUpdate &Update : Iter->second)6234DeclUpdates[D].push_back(Update);6235DeclUpdatesFromGMF.erase(Iter);6236}62376238// If D comes from an AST file, its declaration ID is already known and6239// fixed.6240if (D->isFromASTFile()) {6241if (isWritingStdCXXNamedModules() && D->getOwningModule())6242TouchedTopLevelModules.insert(D->getOwningModule()->getTopLevelModule());62436244return LocalDeclID(D->getGlobalID());6245}62466247assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");6248LocalDeclID &ID = DeclIDs[D];6249if (ID.isInvalid()) {6250if (DoneWritingDeclsAndTypes) {6251assert(0 && "New decl seen after serializing all the decls to emit!");6252return LocalDeclID();6253}62546255// We haven't seen this declaration before. Give it a new ID and6256// enqueue it in the list of declarations to emit.6257ID = NextDeclID++;6258DeclTypesToEmit.push(const_cast<Decl *>(D));6259}62606261return ID;6262}62636264LocalDeclID ASTWriter::getDeclID(const Decl *D) {6265if (!D)6266return LocalDeclID();62676268// If D comes from an AST file, its declaration ID is already known and6269// fixed.6270if (D->isFromASTFile())6271return LocalDeclID(D->getGlobalID());62726273assert(DeclIDs.contains(D) && "Declaration not emitted!");6274return DeclIDs[D];6275}62766277bool ASTWriter::wasDeclEmitted(const Decl *D) const {6278assert(D);62796280assert(DoneWritingDeclsAndTypes &&6281"wasDeclEmitted should only be called after writing declarations");62826283if (D->isFromASTFile())6284return true;62856286bool Emitted = DeclIDs.contains(D);6287assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) ||6288GeneratingReducedBMI) &&6289"The declaration within modules can only be omitted in reduced BMI.");6290return Emitted;6291}62926293void ASTWriter::associateDeclWithFile(const Decl *D, LocalDeclID ID) {6294assert(ID.isValid());6295assert(D);62966297SourceLocation Loc = D->getLocation();6298if (Loc.isInvalid())6299return;63006301// We only keep track of the file-level declarations of each file.6302if (!D->getLexicalDeclContext()->isFileContext())6303return;6304// FIXME: ParmVarDecls that are part of a function type of a parameter of6305// a function/objc method, should not have TU as lexical context.6306// TemplateTemplateParmDecls that are part of an alias template, should not6307// have TU as lexical context.6308if (isa<ParmVarDecl, TemplateTemplateParmDecl>(D))6309return;63106311SourceManager &SM = Context->getSourceManager();6312SourceLocation FileLoc = SM.getFileLoc(Loc);6313assert(SM.isLocalSourceLocation(FileLoc));6314FileID FID;6315unsigned Offset;6316std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc);6317if (FID.isInvalid())6318return;6319assert(SM.getSLocEntry(FID).isFile());6320assert(IsSLocAffecting[FID.ID]);63216322std::unique_ptr<DeclIDInFileInfo> &Info = FileDeclIDs[FID];6323if (!Info)6324Info = std::make_unique<DeclIDInFileInfo>();63256326std::pair<unsigned, LocalDeclID> LocDecl(Offset, ID);6327LocDeclIDsTy &Decls = Info->DeclIDs;6328Decls.push_back(LocDecl);6329}63306331unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {6332assert(needsAnonymousDeclarationNumber(D) &&6333"expected an anonymous declaration");63346335// Number the anonymous declarations within this context, if we've not6336// already done so.6337auto It = AnonymousDeclarationNumbers.find(D);6338if (It == AnonymousDeclarationNumbers.end()) {6339auto *DC = D->getLexicalDeclContext();6340numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) {6341AnonymousDeclarationNumbers[ND] = Number;6342});63436344It = AnonymousDeclarationNumbers.find(D);6345assert(It != AnonymousDeclarationNumbers.end() &&6346"declaration not found within its lexical context");6347}63486349return It->second;6350}63516352void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,6353DeclarationName Name) {6354switch (Name.getNameKind()) {6355case DeclarationName::CXXConstructorName:6356case DeclarationName::CXXDestructorName:6357case DeclarationName::CXXConversionFunctionName:6358AddTypeSourceInfo(DNLoc.getNamedTypeInfo());6359break;63606361case DeclarationName::CXXOperatorName:6362AddSourceRange(DNLoc.getCXXOperatorNameRange());6363break;63646365case DeclarationName::CXXLiteralOperatorName:6366AddSourceLocation(DNLoc.getCXXLiteralOperatorNameLoc());6367break;63686369case DeclarationName::Identifier:6370case DeclarationName::ObjCZeroArgSelector:6371case DeclarationName::ObjCOneArgSelector:6372case DeclarationName::ObjCMultiArgSelector:6373case DeclarationName::CXXUsingDirective:6374case DeclarationName::CXXDeductionGuideName:6375break;6376}6377}63786379void ASTRecordWriter::AddDeclarationNameInfo(6380const DeclarationNameInfo &NameInfo) {6381AddDeclarationName(NameInfo.getName());6382AddSourceLocation(NameInfo.getLoc());6383AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName());6384}63856386void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {6387AddNestedNameSpecifierLoc(Info.QualifierLoc);6388Record->push_back(Info.NumTemplParamLists);6389for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i)6390AddTemplateParameterList(Info.TemplParamLists[i]);6391}63926393void ASTRecordWriter::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {6394// Nested name specifiers usually aren't too long. I think that 8 would6395// typically accommodate the vast majority.6396SmallVector<NestedNameSpecifierLoc , 8> NestedNames;63976398// Push each of the nested-name-specifiers's onto a stack for6399// serialization in reverse order.6400while (NNS) {6401NestedNames.push_back(NNS);6402NNS = NNS.getPrefix();6403}64046405Record->push_back(NestedNames.size());6406while(!NestedNames.empty()) {6407NNS = NestedNames.pop_back_val();6408NestedNameSpecifier::SpecifierKind Kind6409= NNS.getNestedNameSpecifier()->getKind();6410Record->push_back(Kind);6411switch (Kind) {6412case NestedNameSpecifier::Identifier:6413AddIdentifierRef(NNS.getNestedNameSpecifier()->getAsIdentifier());6414AddSourceRange(NNS.getLocalSourceRange());6415break;64166417case NestedNameSpecifier::Namespace:6418AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespace());6419AddSourceRange(NNS.getLocalSourceRange());6420break;64216422case NestedNameSpecifier::NamespaceAlias:6423AddDeclRef(NNS.getNestedNameSpecifier()->getAsNamespaceAlias());6424AddSourceRange(NNS.getLocalSourceRange());6425break;64266427case NestedNameSpecifier::TypeSpec:6428case NestedNameSpecifier::TypeSpecWithTemplate:6429Record->push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);6430AddTypeRef(NNS.getTypeLoc().getType());6431AddTypeLoc(NNS.getTypeLoc());6432AddSourceLocation(NNS.getLocalSourceRange().getEnd());6433break;64346435case NestedNameSpecifier::Global:6436AddSourceLocation(NNS.getLocalSourceRange().getEnd());6437break;64386439case NestedNameSpecifier::Super:6440AddDeclRef(NNS.getNestedNameSpecifier()->getAsRecordDecl());6441AddSourceRange(NNS.getLocalSourceRange());6442break;6443}6444}6445}64466447void ASTRecordWriter::AddTemplateParameterList(6448const TemplateParameterList *TemplateParams) {6449assert(TemplateParams && "No TemplateParams!");6450AddSourceLocation(TemplateParams->getTemplateLoc());6451AddSourceLocation(TemplateParams->getLAngleLoc());6452AddSourceLocation(TemplateParams->getRAngleLoc());64536454Record->push_back(TemplateParams->size());6455for (const auto &P : *TemplateParams)6456AddDeclRef(P);6457if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) {6458Record->push_back(true);6459writeStmtRef(RequiresClause);6460} else {6461Record->push_back(false);6462}6463}64646465/// Emit a template argument list.6466void ASTRecordWriter::AddTemplateArgumentList(6467const TemplateArgumentList *TemplateArgs) {6468assert(TemplateArgs && "No TemplateArgs!");6469Record->push_back(TemplateArgs->size());6470for (int i = 0, e = TemplateArgs->size(); i != e; ++i)6471AddTemplateArgument(TemplateArgs->get(i));6472}64736474void ASTRecordWriter::AddASTTemplateArgumentListInfo(6475const ASTTemplateArgumentListInfo *ASTTemplArgList) {6476assert(ASTTemplArgList && "No ASTTemplArgList!");6477AddSourceLocation(ASTTemplArgList->LAngleLoc);6478AddSourceLocation(ASTTemplArgList->RAngleLoc);6479Record->push_back(ASTTemplArgList->NumTemplateArgs);6480const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs();6481for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)6482AddTemplateArgumentLoc(TemplArgs[i]);6483}64846485void ASTRecordWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set) {6486Record->push_back(Set.size());6487for (ASTUnresolvedSet::const_iterator6488I = Set.begin(), E = Set.end(); I != E; ++I) {6489AddDeclRef(I.getDecl());6490Record->push_back(I.getAccess());6491}6492}64936494// FIXME: Move this out of the main ASTRecordWriter interface.6495void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) {6496Record->push_back(Base.isVirtual());6497Record->push_back(Base.isBaseOfClass());6498Record->push_back(Base.getAccessSpecifierAsWritten());6499Record->push_back(Base.getInheritConstructors());6500AddTypeSourceInfo(Base.getTypeSourceInfo());6501AddSourceRange(Base.getSourceRange());6502AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()6503: SourceLocation());6504}65056506static uint64_t EmitCXXBaseSpecifiers(ASTWriter &W,6507ArrayRef<CXXBaseSpecifier> Bases) {6508ASTWriter::RecordData Record;6509ASTRecordWriter Writer(W, Record);6510Writer.push_back(Bases.size());65116512for (auto &Base : Bases)6513Writer.AddCXXBaseSpecifier(Base);65146515return Writer.Emit(serialization::DECL_CXX_BASE_SPECIFIERS);6516}65176518// FIXME: Move this out of the main ASTRecordWriter interface.6519void ASTRecordWriter::AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases) {6520AddOffset(EmitCXXBaseSpecifiers(*Writer, Bases));6521}65226523static uint64_t6524EmitCXXCtorInitializers(ASTWriter &W,6525ArrayRef<CXXCtorInitializer *> CtorInits) {6526ASTWriter::RecordData Record;6527ASTRecordWriter Writer(W, Record);6528Writer.push_back(CtorInits.size());65296530for (auto *Init : CtorInits) {6531if (Init->isBaseInitializer()) {6532Writer.push_back(CTOR_INITIALIZER_BASE);6533Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());6534Writer.push_back(Init->isBaseVirtual());6535} else if (Init->isDelegatingInitializer()) {6536Writer.push_back(CTOR_INITIALIZER_DELEGATING);6537Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());6538} else if (Init->isMemberInitializer()){6539Writer.push_back(CTOR_INITIALIZER_MEMBER);6540Writer.AddDeclRef(Init->getMember());6541} else {6542Writer.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER);6543Writer.AddDeclRef(Init->getIndirectMember());6544}65456546Writer.AddSourceLocation(Init->getMemberLocation());6547Writer.AddStmt(Init->getInit());6548Writer.AddSourceLocation(Init->getLParenLoc());6549Writer.AddSourceLocation(Init->getRParenLoc());6550Writer.push_back(Init->isWritten());6551if (Init->isWritten())6552Writer.push_back(Init->getSourceOrder());6553}65546555return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS);6556}65576558// FIXME: Move this out of the main ASTRecordWriter interface.6559void ASTRecordWriter::AddCXXCtorInitializers(6560ArrayRef<CXXCtorInitializer *> CtorInits) {6561AddOffset(EmitCXXCtorInitializers(*Writer, CtorInits));6562}65636564void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {6565auto &Data = D->data();65666567Record->push_back(Data.IsLambda);65686569BitsPacker DefinitionBits;65706571#define FIELD(Name, Width, Merge) \6572if (!DefinitionBits.canWriteNextNBits(Width)) { \6573Record->push_back(DefinitionBits); \6574DefinitionBits.reset(0); \6575} \6576DefinitionBits.addBits(Data.Name, Width);65776578#include "clang/AST/CXXRecordDeclDefinitionBits.def"6579#undef FIELD65806581Record->push_back(DefinitionBits);65826583// getODRHash will compute the ODRHash if it has not been previously6584// computed.6585Record->push_back(D->getODRHash());65866587bool ModulesCodegen =6588!D->isDependentType() &&6589(Writer->Context->getLangOpts().ModulesDebugInfo ||6590D->isInNamedModule());6591Record->push_back(ModulesCodegen);6592if (ModulesCodegen)6593Writer->AddDeclRef(D, Writer->ModularCodegenDecls);65946595// IsLambda bit is already saved.65966597AddUnresolvedSet(Data.Conversions.get(*Writer->Context));6598Record->push_back(Data.ComputedVisibleConversions);6599if (Data.ComputedVisibleConversions)6600AddUnresolvedSet(Data.VisibleConversions.get(*Writer->Context));6601// Data.Definition is the owning decl, no need to write it.66026603if (!Data.IsLambda) {6604Record->push_back(Data.NumBases);6605if (Data.NumBases > 0)6606AddCXXBaseSpecifiers(Data.bases());66076608// FIXME: Make VBases lazily computed when needed to avoid storing them.6609Record->push_back(Data.NumVBases);6610if (Data.NumVBases > 0)6611AddCXXBaseSpecifiers(Data.vbases());66126613AddDeclRef(D->getFirstFriend());6614} else {6615auto &Lambda = D->getLambdaData();66166617BitsPacker LambdaBits;6618LambdaBits.addBits(Lambda.DependencyKind, /*Width=*/2);6619LambdaBits.addBit(Lambda.IsGenericLambda);6620LambdaBits.addBits(Lambda.CaptureDefault, /*Width=*/2);6621LambdaBits.addBits(Lambda.NumCaptures, /*Width=*/15);6622LambdaBits.addBit(Lambda.HasKnownInternalLinkage);6623Record->push_back(LambdaBits);66246625Record->push_back(Lambda.NumExplicitCaptures);6626Record->push_back(Lambda.ManglingNumber);6627Record->push_back(D->getDeviceLambdaManglingNumber());6628// The lambda context declaration and index within the context are provided6629// separately, so that they can be used for merging.6630AddTypeSourceInfo(Lambda.MethodTyInfo);6631for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {6632const LambdaCapture &Capture = Lambda.Captures.front()[I];6633AddSourceLocation(Capture.getLocation());66346635BitsPacker CaptureBits;6636CaptureBits.addBit(Capture.isImplicit());6637CaptureBits.addBits(Capture.getCaptureKind(), /*Width=*/3);6638Record->push_back(CaptureBits);66396640switch (Capture.getCaptureKind()) {6641case LCK_StarThis:6642case LCK_This:6643case LCK_VLAType:6644break;6645case LCK_ByCopy:6646case LCK_ByRef:6647ValueDecl *Var =6648Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr;6649AddDeclRef(Var);6650AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()6651: SourceLocation());6652break;6653}6654}6655}6656}66576658void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) {6659const Expr *Init = VD->getInit();6660if (!Init) {6661push_back(0);6662return;6663}66646665uint64_t Val = 1;6666if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) {6667Val |= (ES->HasConstantInitialization ? 2 : 0);6668Val |= (ES->HasConstantDestruction ? 4 : 0);6669APValue *Evaluated = VD->getEvaluatedValue();6670// If the evaluated result is constant, emit it.6671if (Evaluated && (Evaluated->isInt() || Evaluated->isFloat()))6672Val |= 8;6673}6674push_back(Val);6675if (Val & 8) {6676AddAPValue(*VD->getEvaluatedValue());6677}66786679writeStmtRef(Init);6680}66816682void ASTWriter::ReaderInitialized(ASTReader *Reader) {6683assert(Reader && "Cannot remove chain");6684assert((!Chain || Chain == Reader) && "Cannot replace chain");6685assert(FirstDeclID == NextDeclID &&6686FirstTypeID == NextTypeID &&6687FirstIdentID == NextIdentID &&6688FirstMacroID == NextMacroID &&6689FirstSubmoduleID == NextSubmoduleID &&6690FirstSelectorID == NextSelectorID &&6691"Setting chain after writing has started.");66926693Chain = Reader;66946695// Note, this will get called multiple times, once one the reader starts up6696// and again each time it's done reading a PCH or module.6697FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacros();6698FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules();6699FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors();6700NextMacroID = FirstMacroID;6701NextSelectorID = FirstSelectorID;6702NextSubmoduleID = FirstSubmoduleID;6703}67046705void ASTWriter::IdentifierRead(IdentifierID ID, IdentifierInfo *II) {6706// Don't reuse Type ID from external modules for named modules. See the6707// comments in WriteASTCore for details.6708if (isWritingStdCXXNamedModules())6709return;67106711IdentifierID &StoredID = IdentifierIDs[II];6712unsigned OriginalModuleFileIndex = StoredID >> 32;67136714// Always keep the local identifier ID. See \p TypeRead() for more6715// information.6716if (OriginalModuleFileIndex == 0 && StoredID)6717return;67186719// Otherwise, keep the highest ID since the module file comes later has6720// higher module file indexes.6721if (ID > StoredID)6722StoredID = ID;6723}67246725void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) {6726// Always keep the highest ID. See \p TypeRead() for more information.6727MacroID &StoredID = MacroIDs[MI];6728if (ID > StoredID)6729StoredID = ID;6730}67316732void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {6733// Don't reuse Type ID from external modules for named modules. See the6734// comments in WriteASTCore for details.6735if (isWritingStdCXXNamedModules())6736return;67376738// Always take the type index that comes in later module files.6739// This copes with an interesting6740// case for chained AST writing where we schedule writing the type and then,6741// later, deserialize the type from another AST. In this case, we want to6742// keep the entry from a later module so that we can properly write it out to6743// the AST file.6744TypeIdx &StoredIdx = TypeIdxs[T];67456746// Ignore it if the type comes from the current being written module file.6747// Since the current module file being written logically has the highest6748// index.6749unsigned ModuleFileIndex = StoredIdx.getModuleFileIndex();6750if (ModuleFileIndex == 0 && StoredIdx.getValue())6751return;67526753// Otherwise, keep the highest ID since the module file comes later has6754// higher module file indexes.6755if (Idx.getModuleFileIndex() >= StoredIdx.getModuleFileIndex())6756StoredIdx = Idx;6757}67586759void ASTWriter::PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {6760assert(D->isCanonicalDecl() && "predefined decl is not canonical");6761DeclIDs[D] = LocalDeclID(ID);6762PredefinedDecls.insert(D);6763}67646765void ASTWriter::SelectorRead(SelectorID ID, Selector S) {6766// Always keep the highest ID. See \p TypeRead() for more information.6767SelectorID &StoredID = SelectorIDs[S];6768if (ID > StoredID)6769StoredID = ID;6770}67716772void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID,6773MacroDefinitionRecord *MD) {6774assert(!MacroDefinitions.contains(MD));6775MacroDefinitions[MD] = ID;6776}67776778void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {6779assert(!SubmoduleIDs.contains(Mod));6780SubmoduleIDs[Mod] = ID;6781}67826783void ASTWriter::CompletedTagDefinition(const TagDecl *D) {6784if (Chain && Chain->isProcessingUpdateRecords()) return;6785assert(D->isCompleteDefinition());6786assert(!WritingAST && "Already writing the AST!");6787if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {6788// We are interested when a PCH decl is modified.6789if (RD->isFromASTFile()) {6790// A forward reference was mutated into a definition. Rewrite it.6791// FIXME: This happens during template instantiation, should we6792// have created a new definition decl instead ?6793assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) &&6794"completed a tag from another module but not by instantiation?");6795DeclUpdates[RD].push_back(6796DeclUpdate(UPD_CXX_INSTANTIATED_CLASS_DEFINITION));6797}6798}6799}68006801static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {6802if (D->isFromASTFile())6803return true;68046805// The predefined __va_list_tag struct is imported if we imported any decls.6806// FIXME: This is a gross hack.6807return D == D->getASTContext().getVaListTagDecl();6808}68096810void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {6811if (Chain && Chain->isProcessingUpdateRecords()) return;6812assert(DC->isLookupContext() &&6813"Should not add lookup results to non-lookup contexts!");68146815// TU is handled elsewhere.6816if (isa<TranslationUnitDecl>(DC))6817return;68186819// Namespaces are handled elsewhere, except for template instantiations of6820// FunctionTemplateDecls in namespaces. We are interested in cases where the6821// local instantiations are added to an imported context. Only happens when6822// adding ADL lookup candidates, for example templated friends.6823if (isa<NamespaceDecl>(DC) && D->getFriendObjectKind() == Decl::FOK_None &&6824!isa<FunctionTemplateDecl>(D))6825return;68266827// We're only interested in cases where a local declaration is added to an6828// imported context.6829if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC)))6830return;68316832assert(DC == DC->getPrimaryContext() && "added to non-primary context");6833assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");6834assert(!WritingAST && "Already writing the AST!");6835if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {6836// We're adding a visible declaration to a predefined decl context. Ensure6837// that we write out all of its lookup results so we don't get a nasty6838// surprise when we try to emit its lookup table.6839llvm::append_range(DeclsToEmitEvenIfUnreferenced, DC->decls());6840}6841DeclsToEmitEvenIfUnreferenced.push_back(D);6842}68436844void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {6845if (Chain && Chain->isProcessingUpdateRecords()) return;6846assert(D->isImplicit());68476848// We're only interested in cases where a local declaration is added to an6849// imported context.6850if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD))6851return;68526853if (!isa<CXXMethodDecl>(D))6854return;68556856// A decl coming from PCH was modified.6857assert(RD->isCompleteDefinition());6858assert(!WritingAST && "Already writing the AST!");6859DeclUpdates[RD].push_back(DeclUpdate(UPD_CXX_ADDED_IMPLICIT_MEMBER, D));6860}68616862void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {6863if (Chain && Chain->isProcessingUpdateRecords()) return;6864assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");6865if (!Chain) return;6866Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {6867// If we don't already know the exception specification for this redecl6868// chain, add an update record for it.6869if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)6870->getType()6871->castAs<FunctionProtoType>()6872->getExceptionSpecType()))6873DeclUpdates[D].push_back(UPD_CXX_RESOLVED_EXCEPTION_SPEC);6874});6875}68766877void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {6878if (Chain && Chain->isProcessingUpdateRecords()) return;6879assert(!WritingAST && "Already writing the AST!");6880if (!Chain) return;6881Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {6882DeclUpdates[D].push_back(6883DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType));6884});6885}68866887void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,6888const FunctionDecl *Delete,6889Expr *ThisArg) {6890if (Chain && Chain->isProcessingUpdateRecords()) return;6891assert(!WritingAST && "Already writing the AST!");6892assert(Delete && "Not given an operator delete");6893if (!Chain) return;6894Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {6895DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete));6896});6897}68986899void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {6900if (Chain && Chain->isProcessingUpdateRecords()) return;6901assert(!WritingAST && "Already writing the AST!");6902if (!D->isFromASTFile())6903return; // Declaration not imported from PCH.69046905// Implicit function decl from a PCH was defined.6906DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));6907}69086909void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {6910if (Chain && Chain->isProcessingUpdateRecords()) return;6911assert(!WritingAST && "Already writing the AST!");6912if (!D->isFromASTFile())6913return;69146915DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION));6916}69176918void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {6919if (Chain && Chain->isProcessingUpdateRecords()) return;6920assert(!WritingAST && "Already writing the AST!");6921if (!D->isFromASTFile())6922return;69236924DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));6925}69266927void ASTWriter::InstantiationRequested(const ValueDecl *D) {6928if (Chain && Chain->isProcessingUpdateRecords()) return;6929assert(!WritingAST && "Already writing the AST!");6930if (!D->isFromASTFile())6931return;69326933// Since the actual instantiation is delayed, this really means that we need6934// to update the instantiation location.6935SourceLocation POI;6936if (auto *VD = dyn_cast<VarDecl>(D))6937POI = VD->getPointOfInstantiation();6938else6939POI = cast<FunctionDecl>(D)->getPointOfInstantiation();6940DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI));6941}69426943void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {6944if (Chain && Chain->isProcessingUpdateRecords()) return;6945assert(!WritingAST && "Already writing the AST!");6946if (!D->isFromASTFile())6947return;69486949DeclUpdates[D].push_back(6950DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, D));6951}69526953void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {6954assert(!WritingAST && "Already writing the AST!");6955if (!D->isFromASTFile())6956return;69576958DeclUpdates[D].push_back(6959DeclUpdate(UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, D));6960}69616962void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,6963const ObjCInterfaceDecl *IFD) {6964if (Chain && Chain->isProcessingUpdateRecords()) return;6965assert(!WritingAST && "Already writing the AST!");6966if (!IFD->isFromASTFile())6967return; // Declaration not imported from PCH.69686969assert(IFD->getDefinition() && "Category on a class without a definition?");6970ObjCClassesWithCategories.insert(6971const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));6972}69736974void ASTWriter::DeclarationMarkedUsed(const Decl *D) {6975if (Chain && Chain->isProcessingUpdateRecords()) return;6976assert(!WritingAST && "Already writing the AST!");69776978// If there is *any* declaration of the entity that's not from an AST file,6979// we can skip writing the update record. We make sure that isUsed() triggers6980// completion of the redeclaration chain of the entity.6981for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl())6982if (IsLocalDecl(Prev))6983return;69846985DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_USED));6986}69876988void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {6989if (Chain && Chain->isProcessingUpdateRecords()) return;6990assert(!WritingAST && "Already writing the AST!");6991if (!D->isFromASTFile())6992return;69936994DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE));6995}69966997void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {6998if (Chain && Chain->isProcessingUpdateRecords()) return;6999assert(!WritingAST && "Already writing the AST!");7000if (!D->isFromASTFile())7001return;70027003DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_ALLOCATE, A));7004}70057006void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,7007const Attr *Attr) {7008if (Chain && Chain->isProcessingUpdateRecords()) return;7009assert(!WritingAST && "Already writing the AST!");7010if (!D->isFromASTFile())7011return;70127013DeclUpdates[D].push_back(7014DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARETARGET, Attr));7015}70167017void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {7018if (Chain && Chain->isProcessingUpdateRecords()) return;7019assert(!WritingAST && "Already writing the AST!");7020assert(!D->isUnconditionallyVisible() && "expected a hidden declaration");7021DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_EXPORTED, M));7022}70237024void ASTWriter::AddedAttributeToRecord(const Attr *Attr,7025const RecordDecl *Record) {7026if (Chain && Chain->isProcessingUpdateRecords()) return;7027assert(!WritingAST && "Already writing the AST!");7028if (!Record->isFromASTFile())7029return;7030DeclUpdates[Record].push_back(DeclUpdate(UPD_ADDED_ATTR_TO_RECORD, Attr));7031}70327033void ASTWriter::AddedCXXTemplateSpecialization(7034const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {7035assert(!WritingAST && "Already writing the AST!");70367037if (!TD->getFirstDecl()->isFromASTFile())7038return;7039if (Chain && Chain->isProcessingUpdateRecords())7040return;70417042DeclsToEmitEvenIfUnreferenced.push_back(D);7043}70447045void ASTWriter::AddedCXXTemplateSpecialization(7046const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {7047assert(!WritingAST && "Already writing the AST!");70487049if (!TD->getFirstDecl()->isFromASTFile())7050return;7051if (Chain && Chain->isProcessingUpdateRecords())7052return;70537054DeclsToEmitEvenIfUnreferenced.push_back(D);7055}70567057void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,7058const FunctionDecl *D) {7059assert(!WritingAST && "Already writing the AST!");70607061if (!TD->getFirstDecl()->isFromASTFile())7062return;7063if (Chain && Chain->isProcessingUpdateRecords())7064return;70657066DeclsToEmitEvenIfUnreferenced.push_back(D);7067}70687069//===----------------------------------------------------------------------===//7070//// OMPClause Serialization7071////===----------------------------------------------------------------------===//70727073namespace {70747075class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {7076ASTRecordWriter &Record;70777078public:7079OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {}7080#define GEN_CLANG_CLAUSE_CLASS7081#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);7082#include "llvm/Frontend/OpenMP/OMP.inc"7083void writeClause(OMPClause *C);7084void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);7085void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);7086};70877088}70897090void ASTRecordWriter::writeOMPClause(OMPClause *C) {7091OMPClauseWriter(*this).writeClause(C);7092}70937094void OMPClauseWriter::writeClause(OMPClause *C) {7095Record.push_back(unsigned(C->getClauseKind()));7096Visit(C);7097Record.AddSourceLocation(C->getBeginLoc());7098Record.AddSourceLocation(C->getEndLoc());7099}71007101void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {7102Record.push_back(uint64_t(C->getCaptureRegion()));7103Record.AddStmt(C->getPreInitStmt());7104}71057106void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {7107VisitOMPClauseWithPreInit(C);7108Record.AddStmt(C->getPostUpdateExpr());7109}71107111void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {7112VisitOMPClauseWithPreInit(C);7113Record.push_back(uint64_t(C->getNameModifier()));7114Record.AddSourceLocation(C->getNameModifierLoc());7115Record.AddSourceLocation(C->getColonLoc());7116Record.AddStmt(C->getCondition());7117Record.AddSourceLocation(C->getLParenLoc());7118}71197120void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {7121VisitOMPClauseWithPreInit(C);7122Record.AddStmt(C->getCondition());7123Record.AddSourceLocation(C->getLParenLoc());7124}71257126void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {7127VisitOMPClauseWithPreInit(C);7128Record.AddStmt(C->getNumThreads());7129Record.AddSourceLocation(C->getLParenLoc());7130}71317132void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {7133Record.AddStmt(C->getSafelen());7134Record.AddSourceLocation(C->getLParenLoc());7135}71367137void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {7138Record.AddStmt(C->getSimdlen());7139Record.AddSourceLocation(C->getLParenLoc());7140}71417142void OMPClauseWriter::VisitOMPSizesClause(OMPSizesClause *C) {7143Record.push_back(C->getNumSizes());7144for (Expr *Size : C->getSizesRefs())7145Record.AddStmt(Size);7146Record.AddSourceLocation(C->getLParenLoc());7147}71487149void OMPClauseWriter::VisitOMPFullClause(OMPFullClause *C) {}71507151void OMPClauseWriter::VisitOMPPartialClause(OMPPartialClause *C) {7152Record.AddStmt(C->getFactor());7153Record.AddSourceLocation(C->getLParenLoc());7154}71557156void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) {7157Record.AddStmt(C->getAllocator());7158Record.AddSourceLocation(C->getLParenLoc());7159}71607161void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {7162Record.AddStmt(C->getNumForLoops());7163Record.AddSourceLocation(C->getLParenLoc());7164}71657166void OMPClauseWriter::VisitOMPDetachClause(OMPDetachClause *C) {7167Record.AddStmt(C->getEventHandler());7168Record.AddSourceLocation(C->getLParenLoc());7169}71707171void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {7172Record.push_back(unsigned(C->getDefaultKind()));7173Record.AddSourceLocation(C->getLParenLoc());7174Record.AddSourceLocation(C->getDefaultKindKwLoc());7175}71767177void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {7178Record.push_back(unsigned(C->getProcBindKind()));7179Record.AddSourceLocation(C->getLParenLoc());7180Record.AddSourceLocation(C->getProcBindKindKwLoc());7181}71827183void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {7184VisitOMPClauseWithPreInit(C);7185Record.push_back(C->getScheduleKind());7186Record.push_back(C->getFirstScheduleModifier());7187Record.push_back(C->getSecondScheduleModifier());7188Record.AddStmt(C->getChunkSize());7189Record.AddSourceLocation(C->getLParenLoc());7190Record.AddSourceLocation(C->getFirstScheduleModifierLoc());7191Record.AddSourceLocation(C->getSecondScheduleModifierLoc());7192Record.AddSourceLocation(C->getScheduleKindLoc());7193Record.AddSourceLocation(C->getCommaLoc());7194}71957196void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {7197Record.push_back(C->getLoopNumIterations().size());7198Record.AddStmt(C->getNumForLoops());7199for (Expr *NumIter : C->getLoopNumIterations())7200Record.AddStmt(NumIter);7201for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)7202Record.AddStmt(C->getLoopCounter(I));7203Record.AddSourceLocation(C->getLParenLoc());7204}72057206void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *) {}72077208void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}72097210void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}72117212void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}72137214void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}72157216void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *C) {7217Record.push_back(C->isExtended() ? 1 : 0);7218if (C->isExtended()) {7219Record.AddSourceLocation(C->getLParenLoc());7220Record.AddSourceLocation(C->getArgumentLoc());7221Record.writeEnum(C->getDependencyKind());7222}7223}72247225void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}72267227void OMPClauseWriter::VisitOMPCompareClause(OMPCompareClause *) {}72287229// Save the parameter of fail clause.7230void OMPClauseWriter::VisitOMPFailClause(OMPFailClause *C) {7231Record.AddSourceLocation(C->getLParenLoc());7232Record.AddSourceLocation(C->getFailParameterLoc());7233Record.writeEnum(C->getFailParameter());7234}72357236void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}72377238void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}72397240void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}72417242void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}72437244void OMPClauseWriter::VisitOMPRelaxedClause(OMPRelaxedClause *) {}72457246void OMPClauseWriter::VisitOMPWeakClause(OMPWeakClause *) {}72477248void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}72497250void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}72517252void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}72537254void OMPClauseWriter::VisitOMPInitClause(OMPInitClause *C) {7255Record.push_back(C->varlist_size());7256for (Expr *VE : C->varlists())7257Record.AddStmt(VE);7258Record.writeBool(C->getIsTarget());7259Record.writeBool(C->getIsTargetSync());7260Record.AddSourceLocation(C->getLParenLoc());7261Record.AddSourceLocation(C->getVarLoc());7262}72637264void OMPClauseWriter::VisitOMPUseClause(OMPUseClause *C) {7265Record.AddStmt(C->getInteropVar());7266Record.AddSourceLocation(C->getLParenLoc());7267Record.AddSourceLocation(C->getVarLoc());7268}72697270void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *C) {7271Record.AddStmt(C->getInteropVar());7272Record.AddSourceLocation(C->getLParenLoc());7273Record.AddSourceLocation(C->getVarLoc());7274}72757276void OMPClauseWriter::VisitOMPNovariantsClause(OMPNovariantsClause *C) {7277VisitOMPClauseWithPreInit(C);7278Record.AddStmt(C->getCondition());7279Record.AddSourceLocation(C->getLParenLoc());7280}72817282void OMPClauseWriter::VisitOMPNocontextClause(OMPNocontextClause *C) {7283VisitOMPClauseWithPreInit(C);7284Record.AddStmt(C->getCondition());7285Record.AddSourceLocation(C->getLParenLoc());7286}72877288void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {7289VisitOMPClauseWithPreInit(C);7290Record.AddStmt(C->getThreadID());7291Record.AddSourceLocation(C->getLParenLoc());7292}72937294void OMPClauseWriter::VisitOMPAlignClause(OMPAlignClause *C) {7295Record.AddStmt(C->getAlignment());7296Record.AddSourceLocation(C->getLParenLoc());7297}72987299void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {7300Record.push_back(C->varlist_size());7301Record.AddSourceLocation(C->getLParenLoc());7302for (auto *VE : C->varlists()) {7303Record.AddStmt(VE);7304}7305for (auto *VE : C->private_copies()) {7306Record.AddStmt(VE);7307}7308}73097310void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {7311Record.push_back(C->varlist_size());7312VisitOMPClauseWithPreInit(C);7313Record.AddSourceLocation(C->getLParenLoc());7314for (auto *VE : C->varlists()) {7315Record.AddStmt(VE);7316}7317for (auto *VE : C->private_copies()) {7318Record.AddStmt(VE);7319}7320for (auto *VE : C->inits()) {7321Record.AddStmt(VE);7322}7323}73247325void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {7326Record.push_back(C->varlist_size());7327VisitOMPClauseWithPostUpdate(C);7328Record.AddSourceLocation(C->getLParenLoc());7329Record.writeEnum(C->getKind());7330Record.AddSourceLocation(C->getKindLoc());7331Record.AddSourceLocation(C->getColonLoc());7332for (auto *VE : C->varlists())7333Record.AddStmt(VE);7334for (auto *E : C->private_copies())7335Record.AddStmt(E);7336for (auto *E : C->source_exprs())7337Record.AddStmt(E);7338for (auto *E : C->destination_exprs())7339Record.AddStmt(E);7340for (auto *E : C->assignment_ops())7341Record.AddStmt(E);7342}73437344void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {7345Record.push_back(C->varlist_size());7346Record.AddSourceLocation(C->getLParenLoc());7347for (auto *VE : C->varlists())7348Record.AddStmt(VE);7349}73507351void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {7352Record.push_back(C->varlist_size());7353Record.writeEnum(C->getModifier());7354VisitOMPClauseWithPostUpdate(C);7355Record.AddSourceLocation(C->getLParenLoc());7356Record.AddSourceLocation(C->getModifierLoc());7357Record.AddSourceLocation(C->getColonLoc());7358Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());7359Record.AddDeclarationNameInfo(C->getNameInfo());7360for (auto *VE : C->varlists())7361Record.AddStmt(VE);7362for (auto *VE : C->privates())7363Record.AddStmt(VE);7364for (auto *E : C->lhs_exprs())7365Record.AddStmt(E);7366for (auto *E : C->rhs_exprs())7367Record.AddStmt(E);7368for (auto *E : C->reduction_ops())7369Record.AddStmt(E);7370if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {7371for (auto *E : C->copy_ops())7372Record.AddStmt(E);7373for (auto *E : C->copy_array_temps())7374Record.AddStmt(E);7375for (auto *E : C->copy_array_elems())7376Record.AddStmt(E);7377}7378}73797380void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {7381Record.push_back(C->varlist_size());7382VisitOMPClauseWithPostUpdate(C);7383Record.AddSourceLocation(C->getLParenLoc());7384Record.AddSourceLocation(C->getColonLoc());7385Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());7386Record.AddDeclarationNameInfo(C->getNameInfo());7387for (auto *VE : C->varlists())7388Record.AddStmt(VE);7389for (auto *VE : C->privates())7390Record.AddStmt(VE);7391for (auto *E : C->lhs_exprs())7392Record.AddStmt(E);7393for (auto *E : C->rhs_exprs())7394Record.AddStmt(E);7395for (auto *E : C->reduction_ops())7396Record.AddStmt(E);7397}73987399void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {7400Record.push_back(C->varlist_size());7401VisitOMPClauseWithPostUpdate(C);7402Record.AddSourceLocation(C->getLParenLoc());7403Record.AddSourceLocation(C->getColonLoc());7404Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());7405Record.AddDeclarationNameInfo(C->getNameInfo());7406for (auto *VE : C->varlists())7407Record.AddStmt(VE);7408for (auto *VE : C->privates())7409Record.AddStmt(VE);7410for (auto *E : C->lhs_exprs())7411Record.AddStmt(E);7412for (auto *E : C->rhs_exprs())7413Record.AddStmt(E);7414for (auto *E : C->reduction_ops())7415Record.AddStmt(E);7416for (auto *E : C->taskgroup_descriptors())7417Record.AddStmt(E);7418}74197420void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {7421Record.push_back(C->varlist_size());7422VisitOMPClauseWithPostUpdate(C);7423Record.AddSourceLocation(C->getLParenLoc());7424Record.AddSourceLocation(C->getColonLoc());7425Record.push_back(C->getModifier());7426Record.AddSourceLocation(C->getModifierLoc());7427for (auto *VE : C->varlists()) {7428Record.AddStmt(VE);7429}7430for (auto *VE : C->privates()) {7431Record.AddStmt(VE);7432}7433for (auto *VE : C->inits()) {7434Record.AddStmt(VE);7435}7436for (auto *VE : C->updates()) {7437Record.AddStmt(VE);7438}7439for (auto *VE : C->finals()) {7440Record.AddStmt(VE);7441}7442Record.AddStmt(C->getStep());7443Record.AddStmt(C->getCalcStep());7444for (auto *VE : C->used_expressions())7445Record.AddStmt(VE);7446}74477448void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {7449Record.push_back(C->varlist_size());7450Record.AddSourceLocation(C->getLParenLoc());7451Record.AddSourceLocation(C->getColonLoc());7452for (auto *VE : C->varlists())7453Record.AddStmt(VE);7454Record.AddStmt(C->getAlignment());7455}74567457void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {7458Record.push_back(C->varlist_size());7459Record.AddSourceLocation(C->getLParenLoc());7460for (auto *VE : C->varlists())7461Record.AddStmt(VE);7462for (auto *E : C->source_exprs())7463Record.AddStmt(E);7464for (auto *E : C->destination_exprs())7465Record.AddStmt(E);7466for (auto *E : C->assignment_ops())7467Record.AddStmt(E);7468}74697470void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {7471Record.push_back(C->varlist_size());7472Record.AddSourceLocation(C->getLParenLoc());7473for (auto *VE : C->varlists())7474Record.AddStmt(VE);7475for (auto *E : C->source_exprs())7476Record.AddStmt(E);7477for (auto *E : C->destination_exprs())7478Record.AddStmt(E);7479for (auto *E : C->assignment_ops())7480Record.AddStmt(E);7481}74827483void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {7484Record.push_back(C->varlist_size());7485Record.AddSourceLocation(C->getLParenLoc());7486for (auto *VE : C->varlists())7487Record.AddStmt(VE);7488}74897490void OMPClauseWriter::VisitOMPDepobjClause(OMPDepobjClause *C) {7491Record.AddStmt(C->getDepobj());7492Record.AddSourceLocation(C->getLParenLoc());7493}74947495void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {7496Record.push_back(C->varlist_size());7497Record.push_back(C->getNumLoops());7498Record.AddSourceLocation(C->getLParenLoc());7499Record.AddStmt(C->getModifier());7500Record.push_back(C->getDependencyKind());7501Record.AddSourceLocation(C->getDependencyLoc());7502Record.AddSourceLocation(C->getColonLoc());7503Record.AddSourceLocation(C->getOmpAllMemoryLoc());7504for (auto *VE : C->varlists())7505Record.AddStmt(VE);7506for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)7507Record.AddStmt(C->getLoopData(I));7508}75097510void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {7511VisitOMPClauseWithPreInit(C);7512Record.writeEnum(C->getModifier());7513Record.AddStmt(C->getDevice());7514Record.AddSourceLocation(C->getModifierLoc());7515Record.AddSourceLocation(C->getLParenLoc());7516}75177518void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {7519Record.push_back(C->varlist_size());7520Record.push_back(C->getUniqueDeclarationsNum());7521Record.push_back(C->getTotalComponentListNum());7522Record.push_back(C->getTotalComponentsNum());7523Record.AddSourceLocation(C->getLParenLoc());7524bool HasIteratorModifier = false;7525for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {7526Record.push_back(C->getMapTypeModifier(I));7527Record.AddSourceLocation(C->getMapTypeModifierLoc(I));7528if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator)7529HasIteratorModifier = true;7530}7531Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());7532Record.AddDeclarationNameInfo(C->getMapperIdInfo());7533Record.push_back(C->getMapType());7534Record.AddSourceLocation(C->getMapLoc());7535Record.AddSourceLocation(C->getColonLoc());7536for (auto *E : C->varlists())7537Record.AddStmt(E);7538for (auto *E : C->mapperlists())7539Record.AddStmt(E);7540if (HasIteratorModifier)7541Record.AddStmt(C->getIteratorModifier());7542for (auto *D : C->all_decls())7543Record.AddDeclRef(D);7544for (auto N : C->all_num_lists())7545Record.push_back(N);7546for (auto N : C->all_lists_sizes())7547Record.push_back(N);7548for (auto &M : C->all_components()) {7549Record.AddStmt(M.getAssociatedExpression());7550Record.AddDeclRef(M.getAssociatedDeclaration());7551}7552}75537554void OMPClauseWriter::VisitOMPAllocateClause(OMPAllocateClause *C) {7555Record.push_back(C->varlist_size());7556Record.AddSourceLocation(C->getLParenLoc());7557Record.AddSourceLocation(C->getColonLoc());7558Record.AddStmt(C->getAllocator());7559for (auto *VE : C->varlists())7560Record.AddStmt(VE);7561}75627563void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {7564VisitOMPClauseWithPreInit(C);7565Record.AddStmt(C->getNumTeams());7566Record.AddSourceLocation(C->getLParenLoc());7567}75687569void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {7570VisitOMPClauseWithPreInit(C);7571Record.AddStmt(C->getThreadLimit());7572Record.AddSourceLocation(C->getLParenLoc());7573}75747575void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {7576VisitOMPClauseWithPreInit(C);7577Record.AddStmt(C->getPriority());7578Record.AddSourceLocation(C->getLParenLoc());7579}75807581void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {7582VisitOMPClauseWithPreInit(C);7583Record.writeEnum(C->getModifier());7584Record.AddStmt(C->getGrainsize());7585Record.AddSourceLocation(C->getModifierLoc());7586Record.AddSourceLocation(C->getLParenLoc());7587}75887589void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {7590VisitOMPClauseWithPreInit(C);7591Record.writeEnum(C->getModifier());7592Record.AddStmt(C->getNumTasks());7593Record.AddSourceLocation(C->getModifierLoc());7594Record.AddSourceLocation(C->getLParenLoc());7595}75967597void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {7598Record.AddStmt(C->getHint());7599Record.AddSourceLocation(C->getLParenLoc());7600}76017602void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {7603VisitOMPClauseWithPreInit(C);7604Record.push_back(C->getDistScheduleKind());7605Record.AddStmt(C->getChunkSize());7606Record.AddSourceLocation(C->getLParenLoc());7607Record.AddSourceLocation(C->getDistScheduleKindLoc());7608Record.AddSourceLocation(C->getCommaLoc());7609}76107611void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {7612Record.push_back(C->getDefaultmapKind());7613Record.push_back(C->getDefaultmapModifier());7614Record.AddSourceLocation(C->getLParenLoc());7615Record.AddSourceLocation(C->getDefaultmapModifierLoc());7616Record.AddSourceLocation(C->getDefaultmapKindLoc());7617}76187619void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {7620Record.push_back(C->varlist_size());7621Record.push_back(C->getUniqueDeclarationsNum());7622Record.push_back(C->getTotalComponentListNum());7623Record.push_back(C->getTotalComponentsNum());7624Record.AddSourceLocation(C->getLParenLoc());7625for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {7626Record.push_back(C->getMotionModifier(I));7627Record.AddSourceLocation(C->getMotionModifierLoc(I));7628}7629Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());7630Record.AddDeclarationNameInfo(C->getMapperIdInfo());7631Record.AddSourceLocation(C->getColonLoc());7632for (auto *E : C->varlists())7633Record.AddStmt(E);7634for (auto *E : C->mapperlists())7635Record.AddStmt(E);7636for (auto *D : C->all_decls())7637Record.AddDeclRef(D);7638for (auto N : C->all_num_lists())7639Record.push_back(N);7640for (auto N : C->all_lists_sizes())7641Record.push_back(N);7642for (auto &M : C->all_components()) {7643Record.AddStmt(M.getAssociatedExpression());7644Record.writeBool(M.isNonContiguous());7645Record.AddDeclRef(M.getAssociatedDeclaration());7646}7647}76487649void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {7650Record.push_back(C->varlist_size());7651Record.push_back(C->getUniqueDeclarationsNum());7652Record.push_back(C->getTotalComponentListNum());7653Record.push_back(C->getTotalComponentsNum());7654Record.AddSourceLocation(C->getLParenLoc());7655for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {7656Record.push_back(C->getMotionModifier(I));7657Record.AddSourceLocation(C->getMotionModifierLoc(I));7658}7659Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());7660Record.AddDeclarationNameInfo(C->getMapperIdInfo());7661Record.AddSourceLocation(C->getColonLoc());7662for (auto *E : C->varlists())7663Record.AddStmt(E);7664for (auto *E : C->mapperlists())7665Record.AddStmt(E);7666for (auto *D : C->all_decls())7667Record.AddDeclRef(D);7668for (auto N : C->all_num_lists())7669Record.push_back(N);7670for (auto N : C->all_lists_sizes())7671Record.push_back(N);7672for (auto &M : C->all_components()) {7673Record.AddStmt(M.getAssociatedExpression());7674Record.writeBool(M.isNonContiguous());7675Record.AddDeclRef(M.getAssociatedDeclaration());7676}7677}76787679void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {7680Record.push_back(C->varlist_size());7681Record.push_back(C->getUniqueDeclarationsNum());7682Record.push_back(C->getTotalComponentListNum());7683Record.push_back(C->getTotalComponentsNum());7684Record.AddSourceLocation(C->getLParenLoc());7685for (auto *E : C->varlists())7686Record.AddStmt(E);7687for (auto *VE : C->private_copies())7688Record.AddStmt(VE);7689for (auto *VE : C->inits())7690Record.AddStmt(VE);7691for (auto *D : C->all_decls())7692Record.AddDeclRef(D);7693for (auto N : C->all_num_lists())7694Record.push_back(N);7695for (auto N : C->all_lists_sizes())7696Record.push_back(N);7697for (auto &M : C->all_components()) {7698Record.AddStmt(M.getAssociatedExpression());7699Record.AddDeclRef(M.getAssociatedDeclaration());7700}7701}77027703void OMPClauseWriter::VisitOMPUseDeviceAddrClause(OMPUseDeviceAddrClause *C) {7704Record.push_back(C->varlist_size());7705Record.push_back(C->getUniqueDeclarationsNum());7706Record.push_back(C->getTotalComponentListNum());7707Record.push_back(C->getTotalComponentsNum());7708Record.AddSourceLocation(C->getLParenLoc());7709for (auto *E : C->varlists())7710Record.AddStmt(E);7711for (auto *D : C->all_decls())7712Record.AddDeclRef(D);7713for (auto N : C->all_num_lists())7714Record.push_back(N);7715for (auto N : C->all_lists_sizes())7716Record.push_back(N);7717for (auto &M : C->all_components()) {7718Record.AddStmt(M.getAssociatedExpression());7719Record.AddDeclRef(M.getAssociatedDeclaration());7720}7721}77227723void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {7724Record.push_back(C->varlist_size());7725Record.push_back(C->getUniqueDeclarationsNum());7726Record.push_back(C->getTotalComponentListNum());7727Record.push_back(C->getTotalComponentsNum());7728Record.AddSourceLocation(C->getLParenLoc());7729for (auto *E : C->varlists())7730Record.AddStmt(E);7731for (auto *D : C->all_decls())7732Record.AddDeclRef(D);7733for (auto N : C->all_num_lists())7734Record.push_back(N);7735for (auto N : C->all_lists_sizes())7736Record.push_back(N);7737for (auto &M : C->all_components()) {7738Record.AddStmt(M.getAssociatedExpression());7739Record.AddDeclRef(M.getAssociatedDeclaration());7740}7741}77427743void OMPClauseWriter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *C) {7744Record.push_back(C->varlist_size());7745Record.push_back(C->getUniqueDeclarationsNum());7746Record.push_back(C->getTotalComponentListNum());7747Record.push_back(C->getTotalComponentsNum());7748Record.AddSourceLocation(C->getLParenLoc());7749for (auto *E : C->varlists())7750Record.AddStmt(E);7751for (auto *D : C->all_decls())7752Record.AddDeclRef(D);7753for (auto N : C->all_num_lists())7754Record.push_back(N);7755for (auto N : C->all_lists_sizes())7756Record.push_back(N);7757for (auto &M : C->all_components()) {7758Record.AddStmt(M.getAssociatedExpression());7759Record.AddDeclRef(M.getAssociatedDeclaration());7760}7761}77627763void OMPClauseWriter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}77647765void OMPClauseWriter::VisitOMPUnifiedSharedMemoryClause(7766OMPUnifiedSharedMemoryClause *) {}77677768void OMPClauseWriter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {}77697770void7771OMPClauseWriter::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) {7772}77737774void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause(7775OMPAtomicDefaultMemOrderClause *C) {7776Record.push_back(C->getAtomicDefaultMemOrderKind());7777Record.AddSourceLocation(C->getLParenLoc());7778Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());7779}77807781void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) {7782Record.push_back(C->getAtKind());7783Record.AddSourceLocation(C->getLParenLoc());7784Record.AddSourceLocation(C->getAtKindKwLoc());7785}77867787void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) {7788Record.push_back(C->getSeverityKind());7789Record.AddSourceLocation(C->getLParenLoc());7790Record.AddSourceLocation(C->getSeverityKindKwLoc());7791}77927793void OMPClauseWriter::VisitOMPMessageClause(OMPMessageClause *C) {7794Record.AddStmt(C->getMessageString());7795Record.AddSourceLocation(C->getLParenLoc());7796}77977798void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) {7799Record.push_back(C->varlist_size());7800Record.AddSourceLocation(C->getLParenLoc());7801for (auto *VE : C->varlists())7802Record.AddStmt(VE);7803for (auto *E : C->private_refs())7804Record.AddStmt(E);7805}78067807void OMPClauseWriter::VisitOMPInclusiveClause(OMPInclusiveClause *C) {7808Record.push_back(C->varlist_size());7809Record.AddSourceLocation(C->getLParenLoc());7810for (auto *VE : C->varlists())7811Record.AddStmt(VE);7812}78137814void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) {7815Record.push_back(C->varlist_size());7816Record.AddSourceLocation(C->getLParenLoc());7817for (auto *VE : C->varlists())7818Record.AddStmt(VE);7819}78207821void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) {7822Record.writeEnum(C->getKind());7823Record.writeEnum(C->getModifier());7824Record.AddSourceLocation(C->getLParenLoc());7825Record.AddSourceLocation(C->getKindKwLoc());7826Record.AddSourceLocation(C->getModifierKwLoc());7827}78287829void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {7830Record.push_back(C->getNumberOfAllocators());7831Record.AddSourceLocation(C->getLParenLoc());7832for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {7833OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);7834Record.AddStmt(Data.Allocator);7835Record.AddStmt(Data.AllocatorTraits);7836Record.AddSourceLocation(Data.LParenLoc);7837Record.AddSourceLocation(Data.RParenLoc);7838}7839}78407841void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) {7842Record.push_back(C->varlist_size());7843Record.AddSourceLocation(C->getLParenLoc());7844Record.AddStmt(C->getModifier());7845Record.AddSourceLocation(C->getColonLoc());7846for (Expr *E : C->varlists())7847Record.AddStmt(E);7848}78497850void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) {7851Record.writeEnum(C->getBindKind());7852Record.AddSourceLocation(C->getLParenLoc());7853Record.AddSourceLocation(C->getBindKindLoc());7854}78557856void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {7857VisitOMPClauseWithPreInit(C);7858Record.AddStmt(C->getSize());7859Record.AddSourceLocation(C->getLParenLoc());7860}78617862void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) {7863Record.push_back(C->varlist_size());7864Record.push_back(C->getNumLoops());7865Record.AddSourceLocation(C->getLParenLoc());7866Record.push_back(C->getDependenceType());7867Record.AddSourceLocation(C->getDependenceLoc());7868Record.AddSourceLocation(C->getColonLoc());7869for (auto *VE : C->varlists())7870Record.AddStmt(VE);7871for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)7872Record.AddStmt(C->getLoopData(I));7873}78747875void OMPClauseWriter::VisitOMPXAttributeClause(OMPXAttributeClause *C) {7876Record.AddAttributes(C->getAttrs());7877Record.AddSourceLocation(C->getBeginLoc());7878Record.AddSourceLocation(C->getLParenLoc());7879Record.AddSourceLocation(C->getEndLoc());7880}78817882void OMPClauseWriter::VisitOMPXBareClause(OMPXBareClause *C) {}78837884void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {7885writeUInt32(TI->Sets.size());7886for (const auto &Set : TI->Sets) {7887writeEnum(Set.Kind);7888writeUInt32(Set.Selectors.size());7889for (const auto &Selector : Set.Selectors) {7890writeEnum(Selector.Kind);7891writeBool(Selector.ScoreOrCondition);7892if (Selector.ScoreOrCondition)7893writeExprRef(Selector.ScoreOrCondition);7894writeUInt32(Selector.Properties.size());7895for (const auto &Property : Selector.Properties)7896writeEnum(Property.Kind);7897}7898}7899}79007901void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) {7902if (!Data)7903return;7904writeUInt32(Data->getNumClauses());7905writeUInt32(Data->getNumChildren());7906writeBool(Data->hasAssociatedStmt());7907for (unsigned I = 0, E = Data->getNumClauses(); I < E; ++I)7908writeOMPClause(Data->getClauses()[I]);7909if (Data->hasAssociatedStmt())7910AddStmt(Data->getAssociatedStmt());7911for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)7912AddStmt(Data->getChildren()[I]);7913}79147915void ASTRecordWriter::writeOpenACCVarList(const OpenACCClauseWithVarList *C) {7916writeUInt32(C->getVarList().size());7917for (Expr *E : C->getVarList())7918AddStmt(E);7919}79207921void ASTRecordWriter::writeOpenACCIntExprList(ArrayRef<Expr *> Exprs) {7922writeUInt32(Exprs.size());7923for (Expr *E : Exprs)7924AddStmt(E);7925}79267927void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {7928writeEnum(C->getClauseKind());7929writeSourceLocation(C->getBeginLoc());7930writeSourceLocation(C->getEndLoc());79317932switch (C->getClauseKind()) {7933case OpenACCClauseKind::Default: {7934const auto *DC = cast<OpenACCDefaultClause>(C);7935writeSourceLocation(DC->getLParenLoc());7936writeEnum(DC->getDefaultClauseKind());7937return;7938}7939case OpenACCClauseKind::If: {7940const auto *IC = cast<OpenACCIfClause>(C);7941writeSourceLocation(IC->getLParenLoc());7942AddStmt(const_cast<Expr*>(IC->getConditionExpr()));7943return;7944}7945case OpenACCClauseKind::Self: {7946const auto *SC = cast<OpenACCSelfClause>(C);7947writeSourceLocation(SC->getLParenLoc());7948writeBool(SC->hasConditionExpr());7949if (SC->hasConditionExpr())7950AddStmt(const_cast<Expr*>(SC->getConditionExpr()));7951return;7952}7953case OpenACCClauseKind::NumGangs: {7954const auto *NGC = cast<OpenACCNumGangsClause>(C);7955writeSourceLocation(NGC->getLParenLoc());7956writeUInt32(NGC->getIntExprs().size());7957for (Expr *E : NGC->getIntExprs())7958AddStmt(E);7959return;7960}7961case OpenACCClauseKind::NumWorkers: {7962const auto *NWC = cast<OpenACCNumWorkersClause>(C);7963writeSourceLocation(NWC->getLParenLoc());7964AddStmt(const_cast<Expr*>(NWC->getIntExpr()));7965return;7966}7967case OpenACCClauseKind::VectorLength: {7968const auto *NWC = cast<OpenACCVectorLengthClause>(C);7969writeSourceLocation(NWC->getLParenLoc());7970AddStmt(const_cast<Expr*>(NWC->getIntExpr()));7971return;7972}7973case OpenACCClauseKind::Private: {7974const auto *PC = cast<OpenACCPrivateClause>(C);7975writeSourceLocation(PC->getLParenLoc());7976writeOpenACCVarList(PC);7977return;7978}7979case OpenACCClauseKind::FirstPrivate: {7980const auto *FPC = cast<OpenACCFirstPrivateClause>(C);7981writeSourceLocation(FPC->getLParenLoc());7982writeOpenACCVarList(FPC);7983return;7984}7985case OpenACCClauseKind::Attach: {7986const auto *AC = cast<OpenACCAttachClause>(C);7987writeSourceLocation(AC->getLParenLoc());7988writeOpenACCVarList(AC);7989return;7990}7991case OpenACCClauseKind::DevicePtr: {7992const auto *DPC = cast<OpenACCDevicePtrClause>(C);7993writeSourceLocation(DPC->getLParenLoc());7994writeOpenACCVarList(DPC);7995return;7996}7997case OpenACCClauseKind::NoCreate: {7998const auto *NCC = cast<OpenACCNoCreateClause>(C);7999writeSourceLocation(NCC->getLParenLoc());8000writeOpenACCVarList(NCC);8001return;8002}8003case OpenACCClauseKind::Present: {8004const auto *PC = cast<OpenACCPresentClause>(C);8005writeSourceLocation(PC->getLParenLoc());8006writeOpenACCVarList(PC);8007return;8008}8009case OpenACCClauseKind::Copy:8010case OpenACCClauseKind::PCopy:8011case OpenACCClauseKind::PresentOrCopy: {8012const auto *CC = cast<OpenACCCopyClause>(C);8013writeSourceLocation(CC->getLParenLoc());8014writeOpenACCVarList(CC);8015return;8016}8017case OpenACCClauseKind::CopyIn:8018case OpenACCClauseKind::PCopyIn:8019case OpenACCClauseKind::PresentOrCopyIn: {8020const auto *CIC = cast<OpenACCCopyInClause>(C);8021writeSourceLocation(CIC->getLParenLoc());8022writeBool(CIC->isReadOnly());8023writeOpenACCVarList(CIC);8024return;8025}8026case OpenACCClauseKind::CopyOut:8027case OpenACCClauseKind::PCopyOut:8028case OpenACCClauseKind::PresentOrCopyOut: {8029const auto *COC = cast<OpenACCCopyOutClause>(C);8030writeSourceLocation(COC->getLParenLoc());8031writeBool(COC->isZero());8032writeOpenACCVarList(COC);8033return;8034}8035case OpenACCClauseKind::Create:8036case OpenACCClauseKind::PCreate:8037case OpenACCClauseKind::PresentOrCreate: {8038const auto *CC = cast<OpenACCCreateClause>(C);8039writeSourceLocation(CC->getLParenLoc());8040writeBool(CC->isZero());8041writeOpenACCVarList(CC);8042return;8043}8044case OpenACCClauseKind::Async: {8045const auto *AC = cast<OpenACCAsyncClause>(C);8046writeSourceLocation(AC->getLParenLoc());8047writeBool(AC->hasIntExpr());8048if (AC->hasIntExpr())8049AddStmt(const_cast<Expr*>(AC->getIntExpr()));8050return;8051}8052case OpenACCClauseKind::Wait: {8053const auto *WC = cast<OpenACCWaitClause>(C);8054writeSourceLocation(WC->getLParenLoc());8055writeBool(WC->getDevNumExpr());8056if (Expr *DNE = WC->getDevNumExpr())8057AddStmt(DNE);8058writeSourceLocation(WC->getQueuesLoc());80598060writeOpenACCIntExprList(WC->getQueueIdExprs());8061return;8062}8063case OpenACCClauseKind::DeviceType:8064case OpenACCClauseKind::DType: {8065const auto *DTC = cast<OpenACCDeviceTypeClause>(C);8066writeSourceLocation(DTC->getLParenLoc());8067writeUInt32(DTC->getArchitectures().size());8068for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) {8069writeBool(Arg.first);8070if (Arg.first)8071AddIdentifierRef(Arg.first);8072writeSourceLocation(Arg.second);8073}8074return;8075}8076case OpenACCClauseKind::Reduction: {8077const auto *RC = cast<OpenACCReductionClause>(C);8078writeSourceLocation(RC->getLParenLoc());8079writeEnum(RC->getReductionOp());8080writeOpenACCVarList(RC);8081return;8082}8083case OpenACCClauseKind::Seq:8084case OpenACCClauseKind::Independent:8085case OpenACCClauseKind::Auto:8086// Nothing to do here, there is no additional information beyond the8087// begin/end loc and clause kind.8088return;80898090case OpenACCClauseKind::Finalize:8091case OpenACCClauseKind::IfPresent:8092case OpenACCClauseKind::Worker:8093case OpenACCClauseKind::Vector:8094case OpenACCClauseKind::NoHost:8095case OpenACCClauseKind::UseDevice:8096case OpenACCClauseKind::Delete:8097case OpenACCClauseKind::Detach:8098case OpenACCClauseKind::Device:8099case OpenACCClauseKind::DeviceResident:8100case OpenACCClauseKind::Host:8101case OpenACCClauseKind::Link:8102case OpenACCClauseKind::Collapse:8103case OpenACCClauseKind::Bind:8104case OpenACCClauseKind::DeviceNum:8105case OpenACCClauseKind::DefaultAsync:8106case OpenACCClauseKind::Tile:8107case OpenACCClauseKind::Gang:8108case OpenACCClauseKind::Invalid:8109llvm_unreachable("Clause serialization not yet implemented");8110}8111llvm_unreachable("Invalid Clause Kind");8112}81138114void ASTRecordWriter::writeOpenACCClauseList(8115ArrayRef<const OpenACCClause *> Clauses) {8116for (const OpenACCClause *Clause : Clauses)8117writeOpenACCClause(Clause);8118}811981208121