aboutsummaryrefslogtreecommitdiff
path: root/lib/Serialization/ASTWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r--lib/Serialization/ASTWriter.cpp229
1 files changed, 186 insertions, 43 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index b8ada04e5d8a..405488c35716 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -108,6 +108,11 @@ void ASTTypeWriter::VisitPointerType(const PointerType *T) {
Code = TYPE_POINTER;
}
+void ASTTypeWriter::VisitDecayedType(const DecayedType *T) {
+ Writer.AddTypeRef(T->getOriginalType(), Record);
+ Code = TYPE_DECAYED;
+}
+
void ASTTypeWriter::VisitBlockPointerType(const BlockPointerType *T) {
Writer.AddTypeRef(T->getPointeeType(), Record);
Code = TYPE_BLOCK_POINTER;
@@ -447,6 +452,9 @@ void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getStarLoc(), Record);
}
+void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
+ // nothing to do
+}
void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
Writer.AddSourceLocation(TL.getCaretLoc(), Record);
}
@@ -735,6 +743,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
RECORD(EXPR_CXX_CONST_CAST);
RECORD(EXPR_CXX_FUNCTIONAL_CAST);
RECORD(EXPR_USER_DEFINED_LITERAL);
+ RECORD(EXPR_CXX_STD_INITIALIZER_LIST);
RECORD(EXPR_CXX_BOOL_LITERAL);
RECORD(EXPR_CXX_NULL_PTR_LITERAL);
RECORD(EXPR_CXX_TYPEID_EXPR);
@@ -839,6 +848,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(OBJC_CATEGORIES);
RECORD(MACRO_OFFSET);
RECORD(MACRO_TABLE);
+ RECORD(LATE_PARSED_TEMPLATE);
// SourceManager Block.
BLOCK(SOURCE_MANAGER_BLOCK);
@@ -937,6 +947,9 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_CLASS_TEMPLATE);
RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);
RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);
+ RECORD(DECL_VAR_TEMPLATE);
+ RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION);
+ RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION);
RECORD(DECL_FUNCTION_TEMPLATE);
RECORD(DECL_TEMPLATE_TYPE_PARM);
RECORD(DECL_NON_TYPE_TEMPLATE_PARM);
@@ -1224,7 +1237,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
WriteInputFiles(Context.SourceMgr,
PP.getHeaderSearchInfo().getHeaderSearchOpts(),
- isysroot);
+ isysroot,
+ PP.getLangOpts().Modules);
Stream.ExitBlock();
}
@@ -1239,7 +1253,8 @@ namespace {
void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
HeaderSearchOptions &HSOpts,
- StringRef isysroot) {
+ StringRef isysroot,
+ bool Modules) {
using namespace llvm;
Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);
RecordData Record;
@@ -1293,6 +1308,19 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
}
}
+ // Add the compiler's own module.map in the set of (non-system) input files.
+ // This is a simple heuristic for detecting whether the compiler's headers
+ // have changed, because we don't want to stat() all of them.
+ if (Modules && !Chain) {
+ SmallString<128> P = StringRef(HSOpts.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ llvm::sys::path::append(P, "module.map");
+ if (const FileEntry *ModuleMapFile = FileMgr.getFile(P)) {
+ InputFileEntry Entry = { ModuleMapFile, false, false };
+ SortedFiles.push_front(Entry);
+ }
+ }
+
unsigned UserFilesNum = 0;
// Write out all of the input files.
std::vector<uint32_t> InputFileOffsets;
@@ -1475,7 +1503,8 @@ namespace {
using namespace clang::io;
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.isImport << 5)
+ unsigned char Flags = (Data.HeaderRole << 6)
+ | (Data.isImport << 5)
| (Data.isPragmaOnce << 4)
| (Data.DirInfo << 2)
| (Data.Resolved << 1)
@@ -1506,7 +1535,7 @@ namespace {
Emit32(Out, Offset);
if (Data.isModuleHeader) {
- Module *Mod = HS.findModuleForHeader(key.FE);
+ Module *Mod = HS.findModuleForHeader(key.FE).getModule();
Emit32(Out, Writer.getExistingSubmoduleID(Mod));
}
@@ -1542,6 +1571,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot) {
const HeaderFileInfo &HFI = HS.getFileInfo(File);
if (HFI.External && Chain)
continue;
+ if (HFI.isModuleHeader && !HFI.isCompilingModuleHeader)
+ continue;
// Turn the file name into an absolute path, if it isn't already.
const char *Filename = File->getName();
@@ -1830,12 +1861,10 @@ public:
};
} // end anonymous namespace
-static int compareMacroDirectives(const void *XPtr, const void *YPtr) {
- const std::pair<const IdentifierInfo *, MacroDirective *> &X =
- *(const std::pair<const IdentifierInfo *, MacroDirective *>*)XPtr;
- const std::pair<const IdentifierInfo *, MacroDirective *> &Y =
- *(const std::pair<const IdentifierInfo *, MacroDirective *>*)YPtr;
- return X.first->getName().compare(Y.first->getName());
+static int compareMacroDirectives(
+ const std::pair<const IdentifierInfo *, MacroDirective *> *X,
+ const std::pair<const IdentifierInfo *, MacroDirective *> *Y) {
+ return X->first->getName().compare(Y->first->getName());
}
static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
@@ -2249,7 +2278,8 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev);
Abbrev = new BitCodeAbbrev();
@@ -2258,6 +2288,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
@@ -2308,12 +2343,12 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
// Emit the requirements.
- for (unsigned I = 0, N = Mod->Requires.size(); I != N; ++I) {
+ for (unsigned I = 0, N = Mod->Requirements.size(); I != N; ++I) {
Record.clear();
Record.push_back(SUBMODULE_REQUIRES);
+ Record.push_back(Mod->Requirements[I].second);
Stream.EmitRecordWithBlob(RequiresAbbrev, Record,
- Mod->Requires[I].data(),
- Mod->Requires[I].size());
+ Mod->Requirements[I].first);
}
// Emit the umbrella header, if there is one.
@@ -2330,11 +2365,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
}
// Emit the headers.
- for (unsigned I = 0, N = Mod->Headers.size(); I != N; ++I) {
+ for (unsigned I = 0, N = Mod->NormalHeaders.size(); I != N; ++I) {
Record.clear();
Record.push_back(SUBMODULE_HEADER);
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
- Mod->Headers[I]->getName());
+ Mod->NormalHeaders[I]->getName());
}
// Emit the excluded headers.
for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
@@ -2343,6 +2378,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
Mod->ExcludedHeaders[I]->getName());
}
+ // Emit the private headers.
+ for (unsigned I = 0, N = Mod->PrivateHeaders.size(); I != N; ++I) {
+ Record.clear();
+ Record.push_back(SUBMODULE_PRIVATE_HEADER);
+ Stream.EmitRecordWithBlob(PrivateHeaderAbbrev, Record,
+ Mod->PrivateHeaders[I]->getName());
+ }
ArrayRef<const FileEntry *>
TopHeaders = Mod->getTopHeaders(PP->getFileManager());
for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {
@@ -2380,6 +2422,10 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecord(SUBMODULE_EXPORTS, Record);
}
+ //FIXME: How do we emit the 'use'd modules? They may not be submodules.
+ // Might be unnecessary as use declarations are only used to build the
+ // module itself.
+
// Emit the link libraries.
for (unsigned I = 0, N = Mod->LinkLibraries.size(); I != N; ++I) {
Record.clear();
@@ -3096,7 +3142,7 @@ public:
// Only emit declarations that aren't from a chained PCH, though.
SmallVector<Decl *, 16> Decls(IdResolver.begin(II),
IdResolver.end());
- for (SmallVector<Decl *, 16>::reverse_iterator D = Decls.rbegin(),
+ for (SmallVectorImpl<Decl *>::reverse_iterator D = Decls.rbegin(),
DEnd = Decls.rend();
D != DEnd; ++D)
clang::io::Emit32(Out, Writer.getDeclID(getMostRecentLocalDecl(*D)));
@@ -3486,7 +3532,7 @@ void ASTWriter::WriteRedeclarations() {
for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) {
Decl *First = Redeclarations[I];
- assert(First->getPreviousDecl() == 0 && "Not the first declaration?");
+ assert(First->isFirstDecl() && "Not the first declaration?");
Decl *MostRecent = First->getMostRecentDecl();
@@ -3631,6 +3677,30 @@ void ASTWriter::WriteMergedDecls() {
Stream.EmitRecord(MERGED_DECLARATIONS, Record);
}
+void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
+ Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap;
+
+ if (LPTMap.empty())
+ return;
+
+ RecordData Record;
+ for (Sema::LateParsedTemplateMapT::iterator It = LPTMap.begin(),
+ ItEnd = LPTMap.end();
+ It != ItEnd; ++It) {
+ LateParsedTemplate *LPT = It->second;
+ AddDeclRef(It->first, Record);
+ AddDeclRef(LPT->D, Record);
+ Record.push_back(LPT->Toks.size());
+
+ for (CachedTokens::iterator TokIt = LPT->Toks.begin(),
+ TokEnd = LPT->Toks.end();
+ TokIt != TokEnd; ++TokIt) {
+ AddToken(*TokIt, Record);
+ }
+ }
+ Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
+}
+
//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//
@@ -3812,8 +3882,9 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// FIXME: Modules won't like this at all.
IdentifierTable &Table = PP.getIdentifierTable();
SmallVector<const char *, 32> BuiltinNames;
- Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
- Context.getLangOpts().NoBuiltin);
+ if (!Context.getLangOpts().NoBuiltin) {
+ Context.BuiltinInfo.GetBuiltinNames(BuiltinNames);
+ }
for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
getIdentifierRef(&Table.get(BuiltinNames[I]));
}
@@ -3998,12 +4069,27 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
// Make sure visible decls, added to DeclContexts previously loaded from
// an AST file, are registered for serialization.
- for (SmallVector<const Decl *, 16>::iterator
+ for (SmallVectorImpl<const Decl *>::iterator
I = UpdatingVisibleDecls.begin(),
E = UpdatingVisibleDecls.end(); I != E; ++I) {
GetDeclRef(*I);
}
+ // Make sure all decls associated with an identifier are registered for
+ // serialization.
+ for (IdentifierTable::iterator ID = PP.getIdentifierTable().begin(),
+ IDEnd = PP.getIdentifierTable().end();
+ ID != IDEnd; ++ID) {
+ const IdentifierInfo *II = ID->second;
+ if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) {
+ for (IdentifierResolver::iterator D = SemaRef.IdResolver.begin(II),
+ DEnd = SemaRef.IdResolver.end();
+ D != DEnd; ++D) {
+ GetDeclRef(*D);
+ }
+ }
+ }
+
// Resolve any declaration pointers within the declaration updates block.
ResolveDeclUpdatesBlocks();
@@ -4197,7 +4283,8 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
WriteRedeclarations();
WriteMergedDecls();
WriteObjCCategories();
-
+ WriteLateParsedTemplates(SemaRef);
+
// Some simple statistics
Record.clear();
Record.push_back(NumStatements);
@@ -4228,8 +4315,15 @@ void ASTWriter::ResolveDeclUpdatesBlocks() {
URec[Idx] = GetDeclRef(reinterpret_cast<Decl *>(URec[Idx]));
++Idx;
break;
-
+
case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+ case UPD_DECL_MARKED_USED:
+ ++Idx;
+ break;
+
+ case UPD_CXX_DEDUCED_RETURN_TYPE:
+ URec[Idx] = GetOrCreateTypeID(
+ QualType::getFromOpaquePtr(reinterpret_cast<void *>(URec[Idx])));
++Idx;
break;
}
@@ -4266,8 +4360,8 @@ void ASTWriter::WriteDeclReplacementsBlock() {
return;
RecordData Record;
- for (SmallVector<ReplacedDeclInfo, 16>::iterator
- I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
+ for (SmallVectorImpl<ReplacedDeclInfo>::iterator
+ I = ReplacedDecls.begin(), E = ReplacedDecls.end(); I != E; ++I) {
Record.push_back(I->ID);
Record.push_back(I->Offset);
Record.push_back(I->Loc);
@@ -4446,11 +4540,13 @@ void ASTWriter::AddTypeRef(QualType T, RecordDataImpl &Record) {
}
TypeID ASTWriter::GetOrCreateTypeID( QualType T) {
+ assert(Context);
return MakeTypeID(*Context, T,
std::bind1st(std::mem_fun(&ASTWriter::GetOrCreateTypeIdx), this));
}
TypeID ASTWriter::getTypeID(QualType T) const {
+ assert(Context);
return MakeTypeID(*Context, T,
std::bind1st(std::mem_fun(&ASTWriter::getTypeIdx), this));
}
@@ -4531,11 +4627,6 @@ DeclID ASTWriter::getDeclID(const Decl *D) {
return DeclIDs[D];
}
-static inline bool compLocDecl(std::pair<unsigned, serialization::DeclID> L,
- std::pair<unsigned, serialization::DeclID> R) {
- return L.first < R.first;
-}
-
void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) {
assert(ID);
assert(D);
@@ -4574,8 +4665,8 @@ void ASTWriter::associateDeclWithFile(const Decl *D, DeclID ID) {
return;
}
- LocDeclIDsTy::iterator
- I = std::upper_bound(Decls.begin(), Decls.end(), LocDecl, compLocDecl);
+ LocDeclIDsTy::iterator I =
+ std::upper_bound(Decls.begin(), Decls.end(), LocDecl, llvm::less_first());
Decls.insert(I, LocDecl);
}
@@ -4874,6 +4965,17 @@ ASTWriter::AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs,
AddTemplateArgument(TemplateArgs->get(i), Record);
}
+void
+ASTWriter::AddASTTemplateArgumentListInfo
+(const ASTTemplateArgumentListInfo *ASTTemplArgList, RecordDataImpl &Record) {
+ assert(ASTTemplArgList && "No ASTTemplArgList!");
+ AddSourceLocation(ASTTemplArgList->LAngleLoc, Record);
+ AddSourceLocation(ASTTemplArgList->RAngleLoc, Record);
+ Record.push_back(ASTTemplArgList->NumTemplateArgs);
+ const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs();
+ for (int i=0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)
+ AddTemplateArgumentLoc(TemplArgs[i], Record);
+}
void
ASTWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set, RecordDataImpl &Record) {
@@ -5004,8 +5106,6 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
Record.push_back(Data.ImplicitCopyAssignmentHasConstParam);
Record.push_back(Data.HasDeclaredCopyConstructorWithConstParam);
Record.push_back(Data.HasDeclaredCopyAssignmentWithConstParam);
- Record.push_back(Data.FailedImplicitMoveConstructor);
- Record.push_back(Data.FailedImplicitMoveAssignment);
// IsLambda bit is already saved.
Record.push_back(Data.NumBases);
@@ -5019,15 +5119,17 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
AddCXXBaseSpecifiersRef(Data.getVBases(), Data.getVBases() + Data.NumVBases,
Record);
- AddUnresolvedSet(Data.Conversions, Record);
- AddUnresolvedSet(Data.VisibleConversions, Record);
+ AddUnresolvedSet(Data.Conversions.get(*Context), Record);
+ AddUnresolvedSet(Data.VisibleConversions.get(*Context), Record);
// Data.Definition is the owning decl, no need to write it.
- AddDeclRef(Data.FirstFriend, Record);
+ AddDeclRef(D->getFirstFriend(), Record);
// Add lambda-specific data.
if (Data.IsLambda) {
CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData();
Record.push_back(Lambda.Dependent);
+ Record.push_back(Lambda.IsGenericLambda);
+ Record.push_back(Lambda.CaptureDefault);
Record.push_back(Lambda.NumCaptures);
Record.push_back(Lambda.NumExplicitCaptures);
Record.push_back(Lambda.ManglingNumber);
@@ -5037,12 +5139,20 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
LambdaExpr::Capture &Capture = Lambda.Captures[I];
AddSourceLocation(Capture.getLocation(), Record);
Record.push_back(Capture.isImplicit());
- Record.push_back(Capture.getCaptureKind()); // FIXME: stable!
- VarDecl *Var = Capture.capturesVariable()? Capture.getCapturedVar() : 0;
- AddDeclRef(Var, Record);
- AddSourceLocation(Capture.isPackExpansion()? Capture.getEllipsisLoc()
- : SourceLocation(),
- Record);
+ Record.push_back(Capture.getCaptureKind());
+ switch (Capture.getCaptureKind()) {
+ case LCK_This:
+ break;
+ case LCK_ByCopy:
+ case LCK_ByRef:
+ VarDecl *Var =
+ Capture.capturesVariable() ? Capture.getCapturedVar() : 0;
+ AddDeclRef(Var, Record);
+ AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
+ break;
+ }
}
}
}
@@ -5174,6 +5284,19 @@ void ASTWriter::AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD,
Record.push_back(reinterpret_cast<uint64_t>(D));
}
+void ASTWriter::AddedCXXTemplateSpecialization(
+ const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
+ // The specializations set is kept in the canonical template.
+ assert(!WritingAST && "Already writing the AST!");
+ TD = TD->getCanonicalDecl();
+ if (!(!D->isFromASTFile() && TD->isFromASTFile()))
+ return; // Not a source specialization added to a template from PCH.
+
+ UpdateRecord &Record = DeclUpdates[TD];
+ Record.push_back(UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION);
+ Record.push_back(reinterpret_cast<uint64_t>(D));
+}
+
void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
const FunctionDecl *D) {
// The specializations set is kept in the canonical template.
@@ -5187,6 +5310,17 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
Record.push_back(reinterpret_cast<uint64_t>(D));
}
+void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
+ assert(!WritingAST && "Already writing the AST!");
+ FD = FD->getCanonicalDecl();
+ if (!FD->isFromASTFile())
+ return; // Not a function declared in PCH and defined outside.
+
+ UpdateRecord &Record = DeclUpdates[FD];
+ Record.push_back(UPD_CXX_DEDUCED_RETURN_TYPE);
+ Record.push_back(reinterpret_cast<uint64_t>(ReturnType.getAsOpaquePtr()));
+}
+
void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
assert(!WritingAST && "Already writing the AST!");
if (!D->isFromASTFile())
@@ -5235,3 +5369,12 @@ void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,
RewriteDecl(D);
}
+
+void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
+ assert(!WritingAST && "Already writing the AST!");
+ if (!D->isFromASTFile())
+ return;
+
+ UpdateRecord &Record = DeclUpdates[D];
+ Record.push_back(UPD_DECL_MARKED_USED);
+}