diff options
Diffstat (limited to 'lib/Serialization')
-rw-r--r-- | lib/Serialization/ASTCommon.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTCommon.h | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 293 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 772 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderStmt.cpp | 145 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 229 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 170 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterStmt.cpp | 110 | ||||
-rw-r--r-- | lib/Serialization/GeneratePCH.cpp | 17 | ||||
-rw-r--r-- | lib/Serialization/GlobalModuleIndex.cpp | 8 | ||||
-rw-r--r-- | lib/Serialization/ModuleManager.cpp | 13 |
11 files changed, 1412 insertions, 354 deletions
diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index 24b268f..a817687 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -158,14 +158,18 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::CXXRecord: case Decl::ClassTemplateSpecialization: case Decl::ClassTemplatePartialSpecialization: + case Decl::VarTemplateSpecialization: + case Decl::VarTemplatePartialSpecialization: case Decl::Function: case Decl::CXXMethod: case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXConversion: + case Decl::UsingShadow: case Decl::Var: case Decl::FunctionTemplate: case Decl::ClassTemplate: + case Decl::VarTemplate: case Decl::TypeAliasTemplate: case Decl::ObjCProtocol: case Decl::ObjCInterface: @@ -189,7 +193,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::NonTypeTemplateParm: case Decl::TemplateTemplateParm: case Decl::Using: - case Decl::UsingShadow: case Decl::ObjCMethod: case Decl::ObjCCategory: case Decl::ObjCCategoryImpl: diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index 76ef904..ef81e69 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -25,7 +25,9 @@ enum DeclUpdateKind { UPD_CXX_ADDED_IMPLICIT_MEMBER, UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, - UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER + UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, + UPD_CXX_DEDUCED_RETURN_TYPE, + UPD_DECL_MARKED_USED }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 22caeb8..4d1b4b9 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -210,6 +210,8 @@ bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts, namespace { typedef llvm::StringMap<std::pair<StringRef, bool /*IsUndef*/> > MacroDefinitionsMap; + typedef llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > + DeclsMap; } /// \brief Collect the macro definitions provided by the given preprocessor @@ -377,12 +379,6 @@ bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, PP.getLangOpts()); } -void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI, - unsigned ID) { - PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID); - ++NumHeaderInfos; -} - void PCHValidator::ReadCounter(const ModuleFile &M, unsigned Value) { PP.setCounterValue(Value); } @@ -765,6 +761,10 @@ bool ASTReader::ReadDeclContextStorage(ModuleFile &M, void ASTReader::Error(StringRef Msg) { Error(diag::err_fe_pch_malformed, Msg); + if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) { + Diag(diag::note_module_cache_path) + << PP.getHeaderSearchInfo().getModuleCachePath(); + } } void ASTReader::Error(unsigned DiagID, @@ -1103,7 +1103,7 @@ bool ASTReader::ReadBlockAbbrevs(BitstreamCursor &Cursor, unsigned BlockID) { } } -Token ASTReader::ReadToken(ModuleFile &F, const RecordData &Record, +Token ASTReader::ReadToken(ModuleFile &F, const RecordDataImpl &Record, unsigned &Idx) { Token Tok; Tok.startToken(); @@ -1283,6 +1283,8 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, using namespace clang::io; HeaderFileInfo HFI; unsigned Flags = *d++; + HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole> + ((Flags >> 6) & 0x03); HFI.isImport = (Flags >> 5) & 0x01; HFI.isPragmaOnce = (Flags >> 4) & 0x01; HFI.DirInfo = (Flags >> 2) & 0x03; @@ -1309,7 +1311,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d, FileManager &FileMgr = Reader.getFileManager(); ModuleMap &ModMap = Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap(); - ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), /*Excluded=*/false); + ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), HFI.getHeaderRole()); } } @@ -1587,18 +1589,21 @@ void ASTReader::installPCHMacroDirectives(IdentifierInfo *II, /// \brief For the given macro definitions, check if they are both in system /// modules. static bool areDefinedInSystemModules(MacroInfo *PrevMI, MacroInfo *NewMI, - Module *NewOwner, ASTReader &Reader) { + Module *NewOwner, ASTReader &Reader) { assert(PrevMI && NewMI); - if (!NewOwner) - return false; Module *PrevOwner = 0; if (SubmoduleID PrevModID = PrevMI->getOwningModuleID()) PrevOwner = Reader.getSubmodule(PrevModID); - if (!PrevOwner) - return false; - if (PrevOwner == NewOwner) + SourceManager &SrcMgr = Reader.getSourceManager(); + bool PrevInSystem + = PrevOwner? PrevOwner->IsSystem + : SrcMgr.isInSystemHeader(PrevMI->getDefinitionLoc()); + bool NewInSystem + = NewOwner? NewOwner->IsSystem + : SrcMgr.isInSystemHeader(NewMI->getDefinitionLoc()); + if (PrevOwner && PrevOwner == NewOwner) return false; - return PrevOwner->IsSystem && NewOwner->IsSystem; + return PrevInSystem && NewInSystem; } void ASTReader::installImportedMacro(IdentifierInfo *II, MacroDirective *MD, @@ -1721,6 +1726,10 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) { )) { if (Complain) { Error(diag::err_fe_pch_file_modified, Filename, F.FileName); + if (Context.getLangOpts().Modules && !Diags.isDiagnosticInFlight()) { + Diag(diag::note_module_cache_path) + << PP.getHeaderSearchInfo().getModuleCachePath(); + } } IsOutOfDate = true; @@ -2515,9 +2524,10 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case SEMA_DECL_REFS: - // Later tables overwrite earlier ones. - // FIXME: Modules will have some trouble with this. - SemaDeclRefs.clear(); + if (Record.size() != 2) { + Error("Invalid SEMA_DECL_REFS block"); + return true; + } for (unsigned I = 0, N = Record.size(); I != N; ++I) SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); break; @@ -2742,6 +2752,11 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { // FIXME: Not used yet. break; } + + case LATE_PARSED_TEMPLATE: { + LateParsedTemplates.append(Record.begin(), Record.end()); + break; + } } } } @@ -2805,13 +2820,12 @@ void ASTReader::makeModuleVisible(Module *Mod, bool Complain) { llvm::SmallPtrSet<Module *, 4> Visited; SmallVector<Module *, 4> Stack; - Stack.push_back(Mod); + Stack.push_back(Mod); while (!Stack.empty()) { - Mod = Stack.back(); - Stack.pop_back(); + Mod = Stack.pop_back_val(); if (NameVisibility <= Mod->NameVisibility) { - // This module already has this level of visibility (or greater), so + // This module already has this level of visibility (or greater), so // there is nothing more to do. continue; } @@ -2831,16 +2845,7 @@ void ASTReader::makeModuleVisible(Module *Mod, makeNamesVisible(Hidden->second, Hidden->first); HiddenNamesMap.erase(Hidden); } - - // Push any non-explicit submodules onto the stack to be marked as - // visible. - for (Module::submodule_iterator Sub = Mod->submodule_begin(), - SubEnd = Mod->submodule_end(); - Sub != SubEnd; ++Sub) { - if (!(*Sub)->IsExplicit && Visited.insert(*Sub)) - Stack.push_back(*Sub); - } - + // Push any exported modules onto the stack to be marked as visible. SmallVector<Module *, 16> Exports; Mod->getExportedModules(Exports); @@ -2898,6 +2903,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ModuleKind Type, SourceLocation ImportLoc, unsigned ClientLoadCapabilities) { + llvm::SaveAndRestore<SourceLocation> + SetCurImportLocRAII(CurrentImportLoc, ImportLoc); + // Bump the generation number. unsigned PreviousGeneration = CurrentGeneration++; @@ -3012,9 +3020,16 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, } } UnresolvedModuleRefs.clear(); + + // FIXME: How do we load the 'use'd modules? They may not be submodules. + // Might be unnecessary as use declarations are only used to build the + // module itself. InitializeContext(); + if (SemaObj) + UpdateSema(); + if (DeserializationListener) DeserializationListener->ReaderInitialized(this); @@ -3759,6 +3774,21 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { break; } + case SUBMODULE_PRIVATE_HEADER: { + if (First) { + Error("missing submodule metadata record at beginning of block"); + return true; + } + + if (!CurrentModule) + break; + + // We lazily associate headers with their modules via the HeaderInfoTable. + // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead + // of complete filenames or remove it entirely. + break; + } + case SUBMODULE_TOPHEADER: { if (First) { Error("missing submodule metadata record at beginning of block"); @@ -3873,7 +3903,7 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) { if (!CurrentModule) break; - CurrentModule->addRequirement(Blob, Context.getLangOpts(), + CurrentModule->addRequirement(Blob, Record[0], Context.getLangOpts(), Context.getTargetInfo()); break; } @@ -4394,11 +4424,8 @@ namespace { HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { HeaderFileInfoVisitor Visitor(FE); ModuleMgr.visit(&HeaderFileInfoVisitor::visit, &Visitor); - if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) { - if (Listener) - Listener->ReadHeaderFileInfo(*HFI, FE->getUID()); + if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo()) return *HFI; - } return HeaderFileInfo(); } @@ -4509,6 +4536,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) { return Context.getPointerType(PointeeType); } + case TYPE_DECAYED: { + if (Record.size() != 1) { + Error("Incorrect encoding of decayed type"); + return QualType(); + } + QualType OriginalType = readType(*Loc.F, Record, Idx); + QualType DT = Context.getAdjustedParameterType(OriginalType); + if (!isa<DecayedType>(DT)) + Error("Decayed type does not decay"); + return DT; + } + case TYPE_BLOCK_POINTER: { if (Record.size() != 1) { Error("Incorrect encoding of block pointer type"); @@ -4955,6 +4994,9 @@ void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { TL.setStarLoc(ReadSourceLocation(Record, Idx)); } +void TypeLocReader::VisitDecayedTypeLoc(DecayedTypeLoc TL) { + // nothing to do +} void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { TL.setCaretLoc(ReadSourceLocation(Record, Idx)); } @@ -5315,6 +5357,19 @@ ASTReader::ReadTemplateArgumentLoc(ModuleFile &F, Record, Index)); } +const ASTTemplateArgumentListInfo* +ASTReader::ReadASTTemplateArgumentListInfo(ModuleFile &F, + const RecordData &Record, + unsigned &Index) { + SourceLocation LAngleLoc = ReadSourceLocation(F, Record, Index); + SourceLocation RAngleLoc = ReadSourceLocation(F, Record, Index); + unsigned NumArgsAsWritten = Record[Index++]; + TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); + for (unsigned i = 0; i != NumArgsAsWritten; ++i) + TemplArgsInfo.addArgument(ReadTemplateArgumentLoc(F, Record, Index)); + return ASTTemplateArgumentListInfo::Create(getContext(), TemplArgsInfo); +} + Decl *ASTReader::GetExternalDecl(uint32_t ID) { return GetDecl(ID); } @@ -5775,15 +5830,13 @@ namespace { class DeclContextAllNamesVisitor { ASTReader &Reader; SmallVectorImpl<const DeclContext *> &Contexts; - llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > &Decls; + DeclsMap &Decls; bool VisitAll; public: DeclContextAllNamesVisitor(ASTReader &Reader, SmallVectorImpl<const DeclContext *> &Contexts, - llvm::DenseMap<DeclarationName, - SmallVector<NamedDecl *, 8> > &Decls, - bool VisitAll) + DeclsMap &Decls, bool VisitAll) : Reader(Reader), Contexts(Contexts), Decls(Decls), VisitAll(VisitAll) { } static bool visit(ModuleFile &M, void *UserData) { @@ -5834,7 +5887,7 @@ namespace { void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { if (!DC->hasExternalVisibleStorage()) return; - llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8> > Decls; + DeclsMap Decls; // Compute the declaration contexts we need to look into. Multiple such // declaration contexts occur when two declaration contexts from disjoint @@ -5857,9 +5910,7 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { ModuleMgr.visit(&DeclContextAllNamesVisitor::visit, &Visitor); ++NumVisibleDeclContextsRead; - for (llvm::DenseMap<DeclarationName, - SmallVector<NamedDecl *, 8> >::iterator - I = Decls.begin(), E = Decls.end(); I != E; ++I) { + for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { SetExternalVisibleDeclsForName(DC, I->first, I->second); } const_cast<DeclContext *>(DC)->setHasExternalVisibleStorage(false); @@ -6080,21 +6131,13 @@ void ASTReader::InitializeSema(Sema &S) { } PreloadedDecls.clear(); - // Load the offsets of the declarations that Sema references. - // They will be lazily deserialized when needed. - if (!SemaDeclRefs.empty()) { - assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!"); - if (!SemaObj->StdNamespace) - SemaObj->StdNamespace = SemaDeclRefs[0]; - if (!SemaObj->StdBadAlloc) - SemaObj->StdBadAlloc = SemaDeclRefs[1]; - } - + // FIXME: What happens if these are changed by a module import? if (!FPPragmaOptions.empty()) { assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS"); SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0]; } + // FIXME: What happens if these are changed by a module import? if (!OpenCLExtensions.empty()) { unsigned I = 0; #define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++]; @@ -6102,6 +6145,25 @@ void ASTReader::InitializeSema(Sema &S) { assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS"); } + + UpdateSema(); +} + +void ASTReader::UpdateSema() { + assert(SemaObj && "no Sema to update"); + + // Load the offsets of the declarations that Sema references. + // They will be lazily deserialized when needed. + if (!SemaDeclRefs.empty()) { + assert(SemaDeclRefs.size() % 2 == 0); + for (unsigned I = 0; I != SemaDeclRefs.size(); I += 2) { + if (!SemaObj->StdNamespace) + SemaObj->StdNamespace = SemaDeclRefs[I]; + if (!SemaObj->StdBadAlloc) + SemaObj->StdBadAlloc = SemaDeclRefs[I+1]; + } + SemaDeclRefs.clear(); + } } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { @@ -6440,6 +6502,29 @@ void ASTReader::ReadPendingInstantiations( PendingInstantiations.clear(); } +void ASTReader::ReadLateParsedTemplates( + llvm::DenseMap<const FunctionDecl *, LateParsedTemplate *> &LPTMap) { + for (unsigned Idx = 0, N = LateParsedTemplates.size(); Idx < N; + /* In loop */) { + FunctionDecl *FD = cast<FunctionDecl>(GetDecl(LateParsedTemplates[Idx++])); + + LateParsedTemplate *LT = new LateParsedTemplate; + LT->D = GetDecl(LateParsedTemplates[Idx++]); + + ModuleFile *F = getOwningModuleFile(LT->D); + assert(F && "No module"); + + unsigned TokN = LateParsedTemplates[Idx++]; + LT->Toks.reserve(TokN); + for (unsigned T = 0; T < TokN; ++T) + LT->Toks.push_back(ReadToken(*F, LateParsedTemplates, Idx)); + + LPTMap[FD] = LT; + } + + LateParsedTemplates.clear(); +} + void ASTReader::LoadSelector(Selector Sel) { // It would be complicated to avoid reading the methods anyway. So don't. ReadMethodPool(Sel); @@ -6887,7 +6972,7 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F, void ASTReader:: -ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, +ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, ModuleFile &F, const RecordData &Record, unsigned &Idx) { unsigned NumTemplateArgs = Record[Idx++]; @@ -6897,14 +6982,14 @@ ReadTemplateArgumentList(SmallVector<TemplateArgument, 8> &TemplArgs, } /// \brief Read a UnresolvedSet structure. -void ASTReader::ReadUnresolvedSet(ModuleFile &F, ASTUnresolvedSet &Set, +void ASTReader::ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx) { unsigned NumDecls = Record[Idx++]; Set.reserve(Context, NumDecls); while (NumDecls--) { - NamedDecl *D = ReadDeclAs<NamedDecl>(F, Record, Idx); + DeclID ID = ReadDeclID(F, Record, Idx); AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addDecl(Context, D, AS); + Set.addLazyDecl(Context, ID, AS); } } @@ -6991,9 +7076,16 @@ ASTReader::ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); } else { - BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, - LParenLoc, Init, RParenLoc, - Indices.data(), Indices.size()); + if (IndirectMember) { + assert(Indices.empty() && "Indirect field improperly initialized"); + BOMInit = new (Context) CXXCtorInitializer(Context, IndirectMember, + MemberOrEllipsisLoc, LParenLoc, + Init, RParenLoc); + } else { + BOMInit = CXXCtorInitializer::Create(Context, Member, MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc, + Indices.data(), Indices.size()); + } } if (IsWritten) @@ -7168,7 +7260,7 @@ CXXTemporary *ASTReader::ReadCXXTemporary(ModuleFile &F, } DiagnosticBuilder ASTReader::Diag(unsigned DiagID) { - return Diag(SourceLocation(), DiagID); + return Diag(CurrentImportLoc, DiagID); } DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) { @@ -7251,10 +7343,14 @@ void ASTReader::ReadComments() { void ASTReader::finishPendingActions() { while (!PendingIdentifierInfos.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty()) { + !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || + !PendingOdrMergeChecks.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. - llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > TopLevelDecls; + typedef llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> > + TopLevelDeclsMap; + TopLevelDeclsMap TopLevelDecls; + while (!PendingIdentifierInfos.empty()) { // FIXME: std::move IdentifierInfo *II = PendingIdentifierInfos.back().first; @@ -7272,9 +7368,8 @@ void ASTReader::finishPendingActions() { PendingDeclChains.clear(); // Make the most recent of the top-level declarations visible. - for (llvm::DenseMap<IdentifierInfo *, SmallVector<Decl *, 2> >::iterator - TLD = TopLevelDecls.begin(), TLDEnd = TopLevelDecls.end(); - TLD != TLDEnd; ++TLD) { + for (TopLevelDeclsMap::iterator TLD = TopLevelDecls.begin(), + TLDEnd = TopLevelDecls.end(); TLD != TLDEnd; ++TLD) { IdentifierInfo *II = TLD->first; for (unsigned I = 0, N = TLD->second.size(); I != N; ++I) { pushExternalDeclIntoScope(cast<NamedDecl>(TLD->second[I]), II); @@ -7312,6 +7407,64 @@ void ASTReader::finishPendingActions() { DeclContext *LexicalDC = cast<DeclContext>(GetDecl(Info.LexicalDC)); Info.D->setDeclContextsImpl(SemaDC, LexicalDC, getContext()); } + + // For each declaration from a merged context, check that the canonical + // definition of that context also contains a declaration of the same + // entity. + while (!PendingOdrMergeChecks.empty()) { + NamedDecl *D = PendingOdrMergeChecks.pop_back_val(); + + // FIXME: Skip over implicit declarations for now. This matters for things + // like implicitly-declared special member functions. This isn't entirely + // correct; we can end up with multiple unmerged declarations of the same + // implicit entity. + if (D->isImplicit()) + continue; + + DeclContext *CanonDef = D->getDeclContext(); + DeclContext::lookup_result R = CanonDef->lookup(D->getDeclName()); + + bool Found = false; + const Decl *DCanon = D->getCanonicalDecl(); + + llvm::SmallVector<const NamedDecl*, 4> Candidates; + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); + !Found && I != E; ++I) { + for (Decl::redecl_iterator RI = (*I)->redecls_begin(), + RE = (*I)->redecls_end(); + RI != RE; ++RI) { + if ((*RI)->getLexicalDeclContext() == CanonDef) { + // This declaration is present in the canonical definition. If it's + // in the same redecl chain, it's the one we're looking for. + if ((*RI)->getCanonicalDecl() == DCanon) + Found = true; + else + Candidates.push_back(cast<NamedDecl>(*RI)); + break; + } + } + } + + if (!Found) { + D->setInvalidDecl(); + + Module *CanonDefModule = cast<Decl>(CanonDef)->getOwningModule(); + Diag(D->getLocation(), diag::err_module_odr_violation_missing_decl) + << D << D->getOwningModule()->getFullModuleName() + << CanonDef << !CanonDefModule + << (CanonDefModule ? CanonDefModule->getFullModuleName() : ""); + + if (Candidates.empty()) + Diag(cast<Decl>(CanonDef)->getLocation(), + diag::note_module_odr_violation_no_possible_decls) << D; + else { + for (unsigned I = 0, N = Candidates.size(); I != N; ++I) + Diag(Candidates[I]->getLocation(), + diag::note_module_odr_violation_possible_decl) + << Candidates[I]; + } + } + } } // If we deserialized any C++ or Objective-C class definitions, any @@ -7418,7 +7571,7 @@ void ASTReader::FinishedDeserializing() { } void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { - D = cast<NamedDecl>(D->getMostRecentDecl()); + D = D->getMostRecentDecl(); if (SemaObj->IdResolver.tryAddTopLevelDecl(D, Name) && SemaObj->TUScope) { SemaObj->TUScope->AddDecl(D); @@ -7454,7 +7607,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, NumVisibleDeclContextsRead(0), TotalVisibleDeclContexts(0), TotalModulesSizeInBits(0), NumCurrentElementsDeserializing(0), PassingDeclsToConsumer(false), - NumCXXBaseSpecifiersLoaded(0) + NumCXXBaseSpecifiersLoaded(0), ReadingKind(Read_None) { SourceMgr.setExternalSLocEntrySource(this); } diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index f7fa818..b8102d8 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -223,16 +223,29 @@ namespace clang { void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - void VisitTagDecl(TagDecl *TD); + RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); - void VisitRecordDecl(RecordDecl *RD); - void VisitCXXRecordDecl(CXXRecordDecl *D); - void VisitClassTemplateSpecializationDecl( + RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); + void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } + RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); + void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } + RedeclarableResult VisitClassTemplateSpecializationDeclImpl( ClassTemplateSpecializationDecl *D); + void VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + VisitClassTemplateSpecializationDeclImpl(D); + } void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D); + RedeclarableResult + VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D); + void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) { + VisitVarTemplateSpecializationDeclImpl(D); + } + void VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); void VisitValueDecl(ValueDecl *VD); void VisitEnumConstantDecl(EnumConstantDecl *ECD); @@ -246,13 +259,15 @@ namespace clang { void VisitFieldDecl(FieldDecl *FD); void VisitMSPropertyDecl(MSPropertyDecl *FD); void VisitIndirectFieldDecl(IndirectFieldDecl *FD); - void VisitVarDecl(VarDecl *VD); + RedeclarableResult VisitVarDeclImpl(VarDecl *D); + void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); } void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitVarTemplateDecl(VarTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); @@ -276,7 +291,14 @@ namespace clang { template<typename T> void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); - + + template<typename T> + void mergeRedeclarable(Redeclarable<T> *D, T *Existing, + RedeclarableResult &Redecl); + + template<typename T> + void mergeMergeable(Mergeable<T> *D); + // FIXME: Reorder according to DeclNodes.td? void VisitObjCMethodDecl(ObjCMethodDecl *D); void VisitObjCContainerDecl(ObjCContainerDecl *D); @@ -348,9 +370,11 @@ void ASTDeclReader::VisitDecl(Decl *D) { } else { DeclContext *SemaDC = ReadDeclAs<DeclContext>(Record, Idx); DeclContext *LexicalDC = ReadDeclAs<DeclContext>(Record, Idx); + DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); // Avoid calling setLexicalDeclContext() directly because it uses // Decl::getASTContext() internally which is unsafe during derialization. - D->setDeclContextsImpl(SemaDC, LexicalDC, Reader.getContext()); + D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC, + Reader.getContext()); } D->setLocation(Reader.ReadSourceLocation(F, RawLocation)); D->setInvalidDecl(Record[Idx++]); @@ -362,7 +386,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setAttrsImpl(Attrs, Reader.getContext()); } D->setImplicit(Record[Idx++]); - D->setUsed(Record[Idx++]); + D->Used = Record[Idx++]; D->setReferenced(Record[Idx++]); D->setTopLevelDeclInObjCContainer(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); @@ -411,8 +435,12 @@ void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) { void ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); - - TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); + TypeSourceInfo *TInfo = GetTypeSourceInfo(Record, Idx); + if (Record[Idx++]) { // isModed + QualType modedT = Reader.readType(F, Record, Idx); + TD->setModedTypeSourceInfo(TInfo, modedT); + } else + TD->setTypeSourceInfo(TInfo); mergeRedeclarable(TD, Redecl); } @@ -424,7 +452,7 @@ void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { VisitTypedefNameDecl(TD); } -void ASTDeclReader::VisitTagDecl(TagDecl *TD) { +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { RedeclarableResult Redecl = VisitRedeclarable(TD); VisitTypeDecl(TD); @@ -433,16 +461,18 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) { TD->setCompleteDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); TD->setFreeStanding(Record[Idx++]); + TD->setCompleteDefinitionRequired(Record[Idx++]); TD->setRBraceLoc(ReadSourceLocation(Record, Idx)); if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); - TD->TypedefNameDeclOrQualifier = Info; + TD->NamedDeclOrQualifier = Info; } else - TD->setTypedefNameForAnonDecl(ReadDeclAs<TypedefNameDecl>(Record, Idx)); + TD->NamedDeclOrQualifier = ReadDeclAs<NamedDecl>(Record, Idx); - mergeRedeclarable(TD, Redecl); + mergeRedeclarable(TD, Redecl); + return Redecl; } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -458,6 +488,19 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ED->IsScopedUsingClassTag = Record[Idx++]; ED->IsFixed = Record[Idx++]; + // If this is a definition subject to the ODR, and we already have a + // definition, merge this one into it. + if (ED->IsCompleteDefinition && + Reader.getContext().getLangOpts().Modules && + Reader.getContext().getLangOpts().CPlusPlus) { + if (EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()]) { + Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); + ED->IsCompleteDefinition = false; + } else { + OldDef = ED; + } + } + if (EnumDecl *InstED = ReadDeclAs<EnumDecl>(Record, Idx)) { TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); @@ -466,12 +509,14 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { } } -void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { - VisitTagDecl(RD); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { + RedeclarableResult Redecl = VisitTagDecl(RD); RD->setHasFlexibleArrayMember(Record[Idx++]); RD->setAnonymousStructOrUnion(Record[Idx++]); RD->setHasObjectMember(Record[Idx++]); RD->setHasVolatileMember(Record[Idx++]); + return Redecl; } void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { @@ -484,6 +529,7 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { if (Record[Idx++]) ECD->setInitExpr(Reader.ReadExpr(F)); ECD->setInitVal(Reader.ReadAPSInt(Record, Idx)); + mergeMergeable(ECD); } void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { @@ -521,8 +567,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FD->HasImplicitReturnZero = Record[Idx++]; FD->IsConstexpr = Record[Idx++]; FD->HasSkippedBody = Record[Idx++]; - FD->HasCachedLinkage = true; - FD->CachedLinkage = Record[Idx++]; + FD->IsLateTemplateParsed = Record[Idx++]; + FD->setCachedLinkage(Linkage(Record[Idx++])); FD->EndRangeLoc = ReadSourceLocation(Record, Idx); switch ((FunctionDecl::TemplatedKind)Record[Idx++]) { @@ -594,11 +640,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(), TemplArgs.size(), C); void *InsertPos = 0; - CanonTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr(); + CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos); if (InsertPos) - CanonTemplate->getSpecializations().InsertNode(FTInfo, InsertPos); - else - assert(0 && "Another specialization already inserted!"); + CommonPtr->Specializations.InsertNode(FTInfo, InsertPos); + else { + assert(Reader.getContext().getLangOpts().Modules && + "already deserialized this template specialization"); + // FIXME: This specialization is a redeclaration of one from another + // module. Merge it. + } } break; } @@ -747,6 +798,8 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setNextIvar(0); bool synth = Record[Idx++]; IVD->setSynthesize(synth); + bool backingIvarReferencedInAccessor = Record[Idx++]; + IVD->setBackingIvarReferencedInAccessor(backingIvarReferencedInAccessor); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { @@ -880,6 +933,7 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { if (FieldDecl *Tmpl = ReadDeclAs<FieldDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl); } + mergeMergeable(FD); } void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) { @@ -899,7 +953,7 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) { FD->Chaining[I] = ReadDeclAs<NamedDecl>(Record, Idx); } -void ASTDeclReader::VisitVarDecl(VarDecl *VD) { +ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { RedeclarableResult Redecl = VisitRedeclarable(VD); VisitDeclaratorDecl(VD); @@ -911,11 +965,18 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VD->VarDeclBits.CXXForRangeDecl = Record[Idx++]; VD->VarDeclBits.ARCPseudoStrong = Record[Idx++]; VD->VarDeclBits.IsConstexpr = Record[Idx++]; - VD->HasCachedLinkage = true; - VD->CachedLinkage = Record[Idx++]; - + VD->VarDeclBits.IsInitCapture = Record[Idx++]; + VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++]; + Linkage VarLinkage = Linkage(Record[Idx++]); + VD->setCachedLinkage(VarLinkage); + + // Reconstruct the one piece of the IdentifierNamespace that we need. + if (VarLinkage != NoLinkage && + VD->getLexicalDeclContext()->isFunctionOrMethod()) + VD->setLocalExternDecl(); + // Only true variables (not parameters or implicit parameters) can be merged. - if (VD->getKind() == Decl::Var) + if (VD->getKind() != Decl::ParmVar && VD->getKind() != Decl::ImplicitParam) mergeRedeclarable(VD, Redecl); if (uint64_t Val = Record[Idx++]) { @@ -927,12 +988,25 @@ void ASTDeclReader::VisitVarDecl(VarDecl *VD) { } } - if (Record[Idx++]) { // HasMemberSpecializationInfo. + enum VarKind { + VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization + }; + switch ((VarKind)Record[Idx++]) { + case VarNotTemplate: + break; + case VarTemplate: + VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>(Record, Idx)); + break; + case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo. VarDecl *Tmpl = ReadDeclAs<VarDecl>(Record, Idx); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = ReadSourceLocation(Record, Idx); Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI); + break; } + } + + return Redecl; } void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { @@ -956,6 +1030,9 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++]; if (Record[Idx++]) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F)); + + // FIXME: If this is a redeclaration of a function from another module, handle + // inheritance of default arguments. } void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { @@ -1022,6 +1099,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { D->setInline(Record[Idx++]); D->LocStart = ReadSourceLocation(Record, Idx); D->RBraceLoc = ReadSourceLocation(Record, Idx); + // FIXME: At the point of this call, D->getCanonicalDecl() returns 0. mergeRedeclarable(D, Redecl); if (Redecl.getFirstID() == ThisDeclID) { @@ -1034,7 +1112,7 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } else { // Link this namespace back to the first declaration, which has already // been deserialized. - D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDeclaration()); + D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); } } @@ -1048,22 +1126,24 @@ void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); - D->setUsingLocation(ReadSourceLocation(Record, Idx)); + D->setUsingLoc(ReadSourceLocation(Record, Idx)); D->QualifierLoc = Reader.ReadNestedNameSpecifierLoc(F, Record, Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record, Idx); D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>(Record, Idx)); - D->setTypeName(Record[Idx++]); + D->setTypename(Record[Idx++]); if (NamedDecl *Pattern = ReadDeclAs<NamedDecl>(Record, Idx)) Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern); } void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx)); D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx); UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx); if (Pattern) Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); + mergeRedeclarable(D, Redecl); } void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { @@ -1128,8 +1208,6 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.ImplicitCopyAssignmentHasConstParam = Record[Idx++]; Data.HasDeclaredCopyConstructorWithConstParam = Record[Idx++]; Data.HasDeclaredCopyAssignmentWithConstParam = Record[Idx++]; - Data.FailedImplicitMoveConstructor = Record[Idx++]; - Data.FailedImplicitMoveAssignment = Record[Idx++]; Data.NumBases = Record[Idx++]; if (Data.NumBases) @@ -1141,13 +1219,15 @@ void ASTDeclReader::ReadCXXDefinitionData( Reader.ReadUnresolvedSet(F, Data.Conversions, Record, Idx); Reader.ReadUnresolvedSet(F, Data.VisibleConversions, Record, Idx); assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend = ReadDeclAs<FriendDecl>(Record, Idx); - + Data.FirstFriend = ReadDeclID(Record, Idx); + if (Data.IsLambda) { typedef LambdaExpr::Capture Capture; CXXRecordDecl::LambdaDefinitionData &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); Lambda.Dependent = Record[Idx++]; + Lambda.IsGenericLambda = Record[Idx++]; + Lambda.CaptureDefault = Record[Idx++]; Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; Lambda.ManglingNumber = Record[Idx++]; @@ -1160,41 +1240,65 @@ void ASTDeclReader::ReadCXXDefinitionData( SourceLocation Loc = ReadSourceLocation(Record, Idx); bool IsImplicit = Record[Idx++]; LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]); - VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); - SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); - *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + switch (Kind) { + case LCK_This: + *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation()); + break; + case LCK_ByCopy: + case LCK_ByRef: + VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx); + SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx); + *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + break; + } } } } -void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { - VisitRecordDecl(D); +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { + RedeclarableResult Redecl = VisitRecordDeclImpl(D); ASTContext &C = Reader.getContext(); - if (Record[Idx++]) { + bool WasDefinition = Record[Idx++]; + if (WasDefinition) { // Determine whether this is a lambda closure type, so that we can // allocate the appropriate DefinitionData structure. bool IsLambda = Record[Idx++]; if (IsLambda) D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0, - false); + false, + false, LCD_None); else D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); - + + ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); + // Propagate the DefinitionData pointer to the canonical declaration, so // that all other deserialized declarations will see it. - // FIXME: Complain if there already is a DefinitionData! - D->getCanonicalDecl()->DefinitionData = D->DefinitionData; - - ReadCXXDefinitionData(*D->DefinitionData, Record, Idx); - - // Note that we have deserialized a definition. Any declarations - // deserialized before this one will be be given the DefinitionData pointer - // at the end. - Reader.PendingDefinitions.insert(D); + CXXRecordDecl *Canon = D->getCanonicalDecl(); + if (Canon == D) { + // Nothing to do. + } else if (!Canon->DefinitionData) { + Canon->DefinitionData = D->DefinitionData; + + // Note that we have deserialized a definition. Any declarations + // deserialized before this one will be be given the DefinitionData + // pointer at the end. + Reader.PendingDefinitions.insert(D); + } else { + // We have already deserialized a definition of this record. This + // definition is no longer really a definition. Note that the pre-existing + // definition is the *real* definition. + // FIXME: Check DefinitionData for consistency with prior definition. + Reader.MergedDeclContexts.insert( + std::make_pair(D, D->getCanonicalDecl()->DefinitionData->Definition)); + D->IsCompleteDefinition = false; + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; + } } else { // Propagate DefinitionData pointer from the canonical declaration. - D->DefinitionData = D->getCanonicalDecl()->DefinitionData; + D->DefinitionData = D->getCanonicalDecl()->DefinitionData; } enum CXXRecKind { @@ -1217,12 +1321,15 @@ void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { } } - // Load the key function to avoid deserializing every method so we can + // Lazily load the key function to avoid deserializing every method so we can // compute it. - if (D->IsCompleteDefinition) { - if (CXXMethodDecl *Key = ReadDeclAs<CXXMethodDecl>(Record, Idx)) - C.KeyFunctions[D] = Key; + if (WasDefinition) { + DeclID KeyFn = ReadDeclID(Record, Idx); + if (KeyFn && D->IsCompleteDefinition) + C.KeyFunctions[D] = KeyFn; } + + return Redecl; } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { @@ -1240,7 +1347,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); D->IsExplicitSpecified = Record[Idx++]; - D->ImplicitlyDefined = Record[Idx++]; llvm::tie(D->CtorInitializers, D->NumCtorInitializers) = Reader.ReadCXXCtorInitializers(F, Record, Idx); } @@ -1248,7 +1354,6 @@ void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) { void ASTDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); - D->ImplicitlyDefined = Record[Idx++]; D->OperatorDelete = ReadDeclAs<FunctionDecl>(Record, Idx); } @@ -1280,7 +1385,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { D->Friend = GetTypeSourceInfo(Record, Idx); for (unsigned i = 0; i != D->NumTPLists; ++i) D->getTPLists()[i] = Reader.ReadTemplateParameterList(F, Record, Idx); - D->NextFriend = Record[Idx++]; + D->NextFriend = ReadDeclID(Record, Idx); D->UnsupportedFriend = (Record[Idx++] != 0); D->FriendLoc = ReadSourceLocation(Record, Idx); } @@ -1306,6 +1411,9 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { TemplateParameterList* TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); D->init(TemplatedDecl, TemplateParams); + + // FIXME: If this is a redeclaration of a template from another module, handle + // inheritance of default template arguments. } ASTDeclReader::RedeclarableResult @@ -1339,6 +1447,11 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { mergeRedeclarable(D, Redecl); + // If we merged the template with a prior declaration chain, merge the common + // pointer. + // FIXME: Actually merge here, don't just overwrite. + D->Common = D->getCanonicalDecl()->Common; + return Redecl; } @@ -1378,9 +1491,47 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { } } -void ASTDeclReader::VisitClassTemplateSpecializationDecl( - ClassTemplateSpecializationDecl *D) { - VisitCXXRecordDecl(D); +/// TODO: Unify with ClassTemplateDecl version? +/// May require unifying ClassTemplateDecl and +/// VarTemplateDecl beyond TemplateDecl... +void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + + if (ThisDeclID == Redecl.getFirstID()) { + // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of + // the specializations. + SmallVector<serialization::DeclID, 2> SpecIDs; + SpecIDs.push_back(0); + + // Specializations. + unsigned Size = Record[Idx++]; + SpecIDs[0] += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); + + // Partial specializations. + Size = Record[Idx++]; + SpecIDs[0] += Size; + for (unsigned I = 0; I != Size; ++I) + SpecIDs.push_back(ReadDeclID(Record, Idx)); + + VarTemplateDecl::Common *CommonPtr = D->getCommonPtr(); + if (SpecIDs[0]) { + typedef serialization::DeclID DeclID; + + // FIXME: Append specializations! + CommonPtr->LazySpecializations = + new (Reader.getContext()) DeclID[SpecIDs.size()]; + memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), + SpecIDs.size() * sizeof(DeclID)); + } + } +} + +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( + ClassTemplateSpecializationDecl *D) { + RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D); ASTContext &C = Reader.getContext(); if (Decl *InstD = ReadDecl(Record, Idx)) { @@ -1402,16 +1553,6 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { - ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo - = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); - ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); - D->ExplicitInfo = ExplicitInfo; - } - SmallVector<TemplateArgument, 8> TemplArgs; Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs.data(), @@ -1423,35 +1564,60 @@ void ASTDeclReader::VisitClassTemplateSpecializationDecl( if (writtenAsCanonicalDecl) { ClassTemplateDecl *CanonPattern = ReadDeclAs<ClassTemplateDecl>(Record,Idx); if (D->isCanonicalDecl()) { // It's kept in the folding set. - if (ClassTemplatePartialSpecializationDecl *Partial - = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getCommonPtr()->PartialSpecializations.GetOrInsertNode(Partial); + // Set this as, or find, the canonical declaration for this specialization + ClassTemplateSpecializationDecl *CanonSpec; + if (ClassTemplatePartialSpecializationDecl *Partial = + dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) { + CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations + .GetOrInsertNode(Partial); } else { - CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + CanonSpec = + CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + } + // If there was already a canonical specialization, merge into it. + if (CanonSpec != D) { + mergeRedeclarable<TagDecl>(D, CanonSpec, Redecl); + + // This declaration might be a definition. Merge with any existing + // definition. + if (D->DefinitionData) { + if (!CanonSpec->DefinitionData) { + CanonSpec->DefinitionData = D->DefinitionData; + } else { + // FIXME: Check DefinitionData for consistency with prior definition + Reader.PendingDefinitions.erase(D); + Reader.MergedDeclContexts.insert( + std::make_pair(D, CanonSpec->DefinitionData->Definition)); + D->IsCompleteDefinition = false; + D->DefinitionData = CanonSpec->DefinitionData; + } + } } } } + + // Explicit info. + if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { + ClassTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo + = new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); + ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); + D->ExplicitInfo = ExplicitInfo; + } + + return Redecl; } void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { - VisitClassTemplateSpecializationDecl(D); + RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); - ASTContext &C = Reader.getContext(); D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); - - unsigned NumArgs = Record[Idx++]; - if (NumArgs) { - D->NumArgsAsWritten = NumArgs; - D->ArgsAsWritten = new (C) TemplateArgumentLoc[NumArgs]; - for (unsigned i=0; i != NumArgs; ++i) - D->ArgsAsWritten[i] = Reader.ReadTemplateArgumentLoc(F, Record, Idx); - } - - D->SequenceNumber = Record[Idx++]; + D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx); // These are read/set from/to the first declaration. - if (D->getPreviousDecl() == 0) { + if (ThisDeclID == Redecl.getFirstID()) { D->InstantiatedFromMember.setPointer( ReadDeclAs<ClassTemplatePartialSpecializationDecl>(Record, Idx)); D->InstantiatedFromMember.setInt(Record[Idx++]); @@ -1470,12 +1636,100 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. - // Read the function specialization declarations. - // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled - // when reading the specialized FunctionDecl. - unsigned NumSpecs = Record[Idx++]; - while (NumSpecs--) - (void)ReadDecl(Record, Idx); + // Read the function specialization declaration IDs. The specializations + // themselves will be loaded if they're needed. + if (unsigned NumSpecs = Record[Idx++]) { + // FIXME: Append specializations! + FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr(); + CommonPtr->LazySpecializations = new (Reader.getContext()) + serialization::DeclID[NumSpecs + 1]; + CommonPtr->LazySpecializations[0] = NumSpecs; + for (unsigned I = 0; I != NumSpecs; ++I) + CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx); + } + } +} + +/// TODO: Unify with ClassTemplateSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +ASTDeclReader::RedeclarableResult +ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( + VarTemplateSpecializationDecl *D) { + RedeclarableResult Redecl = VisitVarDeclImpl(D); + + ASTContext &C = Reader.getContext(); + if (Decl *InstD = ReadDecl(Record, Idx)) { + if (VarTemplateDecl *VTD = dyn_cast<VarTemplateDecl>(InstD)) { + D->SpecializedTemplate = VTD; + } else { + SmallVector<TemplateArgument, 8> TemplArgs; + Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); + TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy( + C, TemplArgs.data(), TemplArgs.size()); + VarTemplateSpecializationDecl::SpecializedPartialSpecialization *PS = + new (C) + VarTemplateSpecializationDecl::SpecializedPartialSpecialization(); + PS->PartialSpecialization = + cast<VarTemplatePartialSpecializationDecl>(InstD); + PS->TemplateArgs = ArgList; + D->SpecializedTemplate = PS; + } + } + + // Explicit info. + if (TypeSourceInfo *TyInfo = GetTypeSourceInfo(Record, Idx)) { + VarTemplateSpecializationDecl::ExplicitSpecializationInfo *ExplicitInfo = + new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = TyInfo; + ExplicitInfo->ExternLoc = ReadSourceLocation(Record, Idx); + ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation(Record, Idx); + D->ExplicitInfo = ExplicitInfo; + } + + SmallVector<TemplateArgument, 8> TemplArgs; + Reader.ReadTemplateArgumentList(TemplArgs, F, Record, Idx); + D->TemplateArgs = + TemplateArgumentList::CreateCopy(C, TemplArgs.data(), TemplArgs.size()); + D->PointOfInstantiation = ReadSourceLocation(Record, Idx); + D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++]; + + bool writtenAsCanonicalDecl = Record[Idx++]; + if (writtenAsCanonicalDecl) { + VarTemplateDecl *CanonPattern = ReadDeclAs<VarTemplateDecl>(Record, Idx); + if (D->isCanonicalDecl()) { // It's kept in the folding set. + if (VarTemplatePartialSpecializationDecl *Partial = + dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { + CanonPattern->getCommonPtr()->PartialSpecializations + .GetOrInsertNode(Partial); + } else { + CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + } + } + } + + return Redecl; +} + +/// TODO: Unify with ClassTemplatePartialSpecializationDecl version? +/// May require unifying ClassTemplate(Partial)SpecializationDecl and +/// VarTemplate(Partial)SpecializationDecl with a new data +/// structure Template(Partial)SpecializationDecl, and +/// using Template(Partial)SpecializationDecl as input type. +void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D) { + RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); + + D->TemplateParams = Reader.ReadTemplateParameterList(F, Record, Idx); + D->ArgsAsWritten = Reader.ReadASTTemplateArgumentListInfo(F, Record, Idx); + + // These are read/set from/to the first declaration. + if (ThisDeclID == Redecl.getFirstID()) { + D->InstantiatedFromMember.setPointer( + ReadDeclAs<VarTemplatePartialSpecializationDecl>(Record, Idx)); + D->InstantiatedFromMember.setInt(Record[Idx++]); } } @@ -1584,70 +1838,98 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { /// \brief Attempts to merge the given declaration (D) with another declaration /// of the same entity. template<typename T> -void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl) { // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; - - if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) { - if (T *Existing = ExistingRes) { - T *ExistingCanon = Existing->getCanonicalDecl(); - T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); - if (ExistingCanon != DCanon) { - // Have our redeclaration link point back at the canonical declaration - // of the existing declaration, so that this declaration has the - // appropriate canonical declaration. - D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon); - - // When we merge a namespace, update its pointer to the first namespace. - if (NamespaceDecl *Namespace - = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) { - Namespace->AnonOrFirstNamespaceAndInline.setPointer( - static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon))); - } - - // Don't introduce DCanon into the set of pending declaration chains. - Redecl.suppress(); - - // Introduce ExistingCanon into the set of pending declaration chains, - // if in fact it came from a module file. - if (ExistingCanon->isFromASTFile()) { - GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID(); - assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); - if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) - Reader.PendingDeclChains.push_back(ExistingCanonID); - } - - // If this declaration was the canonical declaration, make a note of - // that. We accept the linear algorithm here because the number of - // unique canonical declarations of an entity should always be tiny. - if (DCanon == static_cast<T*>(D)) { - SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; - if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) - == Merged.end()) - Merged.push_back(Redecl.getFirstID()); - - // If ExistingCanon did not come from a module file, introduce the - // first declaration that *does* come from a module file to the - // set of pending declaration chains, so that we merge this - // declaration. - if (!ExistingCanon->isFromASTFile() && - Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) - Reader.PendingDeclChains.push_back(Merged[0]); - } - } + + if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) + if (T *Existing = ExistingRes) + mergeRedeclarable(D, Existing, Redecl); +} + +/// \brief Attempts to merge the given declaration (D) with another declaration +/// of the same entity. +template<typename T> +void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *D, T *Existing, + RedeclarableResult &Redecl) { + T *ExistingCanon = Existing->getCanonicalDecl(); + T *DCanon = static_cast<T*>(D)->getCanonicalDecl(); + if (ExistingCanon != DCanon) { + // Have our redeclaration link point back at the canonical declaration + // of the existing declaration, so that this declaration has the + // appropriate canonical declaration. + D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon); + + // When we merge a namespace, update its pointer to the first namespace. + if (NamespaceDecl *Namespace + = dyn_cast<NamespaceDecl>(static_cast<T*>(D))) { + Namespace->AnonOrFirstNamespaceAndInline.setPointer( + static_cast<NamespaceDecl *>(static_cast<void*>(ExistingCanon))); + } + + // Don't introduce DCanon into the set of pending declaration chains. + Redecl.suppress(); + + // Introduce ExistingCanon into the set of pending declaration chains, + // if in fact it came from a module file. + if (ExistingCanon->isFromASTFile()) { + GlobalDeclID ExistingCanonID = ExistingCanon->getGlobalID(); + assert(ExistingCanonID && "Unrecorded canonical declaration ID?"); + if (Reader.PendingDeclChainsKnown.insert(ExistingCanonID)) + Reader.PendingDeclChains.push_back(ExistingCanonID); + } + + // If this declaration was the canonical declaration, make a note of + // that. We accept the linear algorithm here because the number of + // unique canonical declarations of an entity should always be tiny. + if (DCanon == static_cast<T*>(D)) { + SmallVectorImpl<DeclID> &Merged = Reader.MergedDecls[ExistingCanon]; + if (std::find(Merged.begin(), Merged.end(), Redecl.getFirstID()) + == Merged.end()) + Merged.push_back(Redecl.getFirstID()); + + // If ExistingCanon did not come from a module file, introduce the + // first declaration that *does* come from a module file to the + // set of pending declaration chains, so that we merge this + // declaration. + if (!ExistingCanon->isFromASTFile() && + Reader.PendingDeclChainsKnown.insert(Redecl.getFirstID())) + Reader.PendingDeclChains.push_back(Merged[0]); } } } +/// \brief Attempts to merge the given declaration (D) with another declaration +/// of the same entity, for the case where the entity is not actually +/// redeclarable. This happens, for instance, when merging the fields of +/// identical class definitions from two different modules. +template<typename T> +void ASTDeclReader::mergeMergeable(Mergeable<T> *D) { + // If modules are not available, there is no reason to perform this merge. + if (!Reader.getContext().getLangOpts().Modules) + return; + + // ODR-based merging is only performed in C++. In C, identically-named things + // in different translation units are not redeclarations (but may still have + // compatible types). + if (!Reader.getContext().getLangOpts().CPlusPlus) + return; + + if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D))) + if (T *Existing = ExistingRes) + Reader.Context.setPrimaryMergedDecl(static_cast<T*>(D), + Existing->getCanonicalDecl()); +} + void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { VisitDecl(D); unsigned NumVars = D->varlist_size(); - SmallVector<DeclRefExpr *, 16> Vars; + SmallVector<Expr *, 16> Vars; Vars.reserve(NumVars); for (unsigned i = 0; i != NumVars; ++i) { - Vars.push_back(cast<DeclRefExpr>(Reader.ReadExpr(F))); + Vars.push_back(Reader.ReadExpr(F)); } D->setVars(Vars); } @@ -1741,6 +2023,48 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } +static bool isSameTemplateParameterList(const TemplateParameterList *X, + const TemplateParameterList *Y); + +/// \brief Determine whether two template parameters are similar enough +/// that they may be used in declarations of the same template. +static bool isSameTemplateParameter(const NamedDecl *X, + const NamedDecl *Y) { + if (X->getKind() != Y->getKind()) + return false; + + if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) { + const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack(); + } + + if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { + const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack() && + TX->getASTContext().hasSameType(TX->getType(), TY->getType()); + } + + const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X); + const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y); + return TX->isParameterPack() == TY->isParameterPack() && + isSameTemplateParameterList(TX->getTemplateParameters(), + TY->getTemplateParameters()); +} + +/// \brief Determine whether two template parameter lists are similar enough +/// that they may be used in declarations of the same template. +static bool isSameTemplateParameterList(const TemplateParameterList *X, + const TemplateParameterList *Y) { + if (X->size() != Y->size()) + return false; + + for (unsigned I = 0, N = X->size(); I != N; ++I) + if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I))) + return false; + + return true; +} + /// \brief Determine whether the two declarations refer to the same entity. static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); @@ -1767,7 +2091,13 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // Objective-C classes and protocols with the same name always match. if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) return true; - + + if (isa<ClassTemplateSpecializationDecl>(X)) { + // No need to handle these here: we merge them when adding them to the + // template. + return false; + } + // Compatible tags match. if (TagDecl *TagX = dyn_cast<TagDecl>(X)) { TagDecl *TagY = cast<TagDecl>(Y); @@ -1777,48 +2107,90 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class || TagY->getTagKind() == TTK_Interface)); } - + // Functions with the same type and linkage match. - // FIXME: This needs to cope with function templates, merging of - //prototyped/non-prototyped functions, etc. + // FIXME: This needs to cope with function template specializations, + // merging of prototyped/non-prototyped functions, etc. if (FunctionDecl *FuncX = dyn_cast<FunctionDecl>(X)) { FunctionDecl *FuncY = cast<FunctionDecl>(Y); - return (FuncX->getLinkage() == FuncY->getLinkage()) && + return (FuncX->getLinkageInternal() == FuncY->getLinkageInternal()) && FuncX->getASTContext().hasSameType(FuncX->getType(), FuncY->getType()); } // Variables with the same type and linkage match. if (VarDecl *VarX = dyn_cast<VarDecl>(X)) { VarDecl *VarY = cast<VarDecl>(Y); - return (VarX->getLinkage() == VarY->getLinkage()) && + return (VarX->getLinkageInternal() == VarY->getLinkageInternal()) && VarX->getASTContext().hasSameType(VarX->getType(), VarY->getType()); } - + // Namespaces with the same name and inlinedness match. if (NamespaceDecl *NamespaceX = dyn_cast<NamespaceDecl>(X)) { NamespaceDecl *NamespaceY = cast<NamespaceDecl>(Y); return NamespaceX->isInline() == NamespaceY->isInline(); } - // Identical template names and kinds match. - if (isa<TemplateDecl>(X)) + // Identical template names and kinds match if their template parameter lists + // and patterns match. + if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) { + TemplateDecl *TemplateY = cast<TemplateDecl>(Y); + return isSameEntity(TemplateX->getTemplatedDecl(), + TemplateY->getTemplatedDecl()) && + isSameTemplateParameterList(TemplateX->getTemplateParameters(), + TemplateY->getTemplateParameters()); + } + + // Fields with the same name and the same type match. + if (FieldDecl *FDX = dyn_cast<FieldDecl>(X)) { + FieldDecl *FDY = cast<FieldDecl>(Y); + // FIXME: Diagnose if the types don't match. More generally, diagnose if we + // get a declaration in a class definition that isn't in the canonical class + // definition. + // FIXME: Also check the bitwidth is odr-equivalent, if any. + return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); + } + + // Enumerators with the same name match. + if (isa<EnumConstantDecl>(X)) + // FIXME: Also check the value is odr-equivalent. return true; + // Using shadow declarations with the same target match. + if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) { + UsingShadowDecl *USY = cast<UsingShadowDecl>(Y); + return USX->getTargetDecl() == USY->getTargetDecl(); + } + // FIXME: Many other cases to implement. return false; } +/// Find the context in which we should search for previous declarations when +/// looking for declarations to merge. +static DeclContext *getPrimaryContextForMerging(DeclContext *DC) { + if (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC)) + return ND->getOriginalNamespace(); + + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) + return RD->getDefinition(); + + if (EnumDecl *ED = dyn_cast<EnumDecl>(DC)) + return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() : 0; + + return 0; +} + ASTDeclReader::FindExistingResult::~FindExistingResult() { if (!AddResult || Existing) return; - - if (New->getDeclContext()->getRedeclContext()->isTranslationUnit() - && Reader.SemaObj) { + + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + if (DC->isTranslationUnit() && Reader.SemaObj) { Reader.SemaObj->IdResolver.tryAddTopLevelDecl(New, New->getDeclName()); - } else { - DeclContext *DC = New->getLexicalDeclContext(); - if (DC->isNamespace()) - DC->addDecl(New); + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + // Add the declaration to its redeclaration context so later merging + // lookups will find it. + MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true); } } @@ -1830,11 +2202,11 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { Result.suppress(); return Result; } - + + // FIXME: Bail out for non-canonical declarations. We will have performed any + // necessary merging already. + DeclContext *DC = D->getDeclContext()->getRedeclContext(); - if (!DC->isFileContext()) - return FindExistingResult(Reader); - if (DC->isTranslationUnit() && Reader.SemaObj) { IdentifierResolver &IdResolver = Reader.SemaObj->IdResolver; @@ -1867,17 +2239,22 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { if (isSameEntity(*I, D)) return FindExistingResult(Reader, D, *I); } - } - - if (DC->isNamespace()) { - DeclContext::lookup_result R = DC->lookup(Name); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) { + } else if (DeclContext *MergeDC = getPrimaryContextForMerging(DC)) { + DeclContext::lookup_result R = MergeDC->noload_lookup(Name); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { if (isSameEntity(*I, D)) return FindExistingResult(Reader, D, *I); } + } else { + // Not in a mergeable context. + return FindExistingResult(Reader); } - + + // If this declaration is from a merged context, make a note that we need to + // check that the canonical definition of that context contains the decl. + if (Reader.MergedDeclContexts.count(D->getLexicalDeclContext())) + Reader.PendingOdrMergeChecks.push_back(D); + return FindExistingResult(Reader, D, /*Existing=*/0); } @@ -1891,6 +2268,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { VD->RedeclLink.setNext(cast<VarDecl>(previous)); } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous)); + } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { + USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous)); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { @@ -1901,6 +2280,15 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); TD->RedeclLink.setNext(cast<RedeclarableTemplateDecl>(previous)); } + + // If the declaration was visible in one module, a redeclaration of it in + // another module remains visible even if it wouldn't be visible by itself. + // + // FIXME: In this case, the declaration should only be visible if a module + // that makes it visible has been imported. + D->IdentifierNamespace |= + previous->IdentifierNamespace & + (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); } void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { @@ -1909,7 +2297,7 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { TD->RedeclLink = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->RedeclLink + FD->RedeclLink = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { VD->RedeclLink @@ -1918,6 +2306,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { TD->RedeclLink = Redeclarable<TypedefNameDecl>::LatestDeclLink( cast<TypedefNameDecl>(Latest)); + } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { + USD->RedeclLink + = Redeclarable<UsingShadowDecl>::LatestDeclLink( + cast<UsingShadowDecl>(Latest)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { ID->RedeclLink = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( @@ -1961,11 +2353,6 @@ ASTReader::combineStoredMergedDecls(Decl *Canon, GlobalDeclID CanonID) { return Pos; } -void ASTReader::loadAndAttachPreviousDecl(Decl *D, serialization::DeclID ID) { - Decl *previous = GetDecl(ID); - ASTDeclReader::attachPreviousDecl(D, previous); -} - /// \brief Read the declaration at the given offset from the AST file. Decl *ASTReader::ReadDeclRecord(DeclID ID) { unsigned Index = ID - NUM_PREDEF_DECL_IDS; @@ -2070,6 +2457,15 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION: D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); break; + case DECL_VAR_TEMPLATE: + D = VarTemplateDecl::CreateDeserialized(Context, ID); + break; + case DECL_VAR_TEMPLATE_SPECIALIZATION: + D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID); + break; + case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION: + D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); + break; case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); break; @@ -2397,7 +2793,7 @@ void ASTReader::loadPendingDeclChain(serialization::GlobalDeclID ID) { for (unsigned I = 0, N = Chain.size(); I != N; ++I) { if (Chain[I] == CanonDecl) continue; - + ASTDeclReader::attachPreviousDecl(Chain[I], MostRecent); MostRecent = Chain[I]; } @@ -2582,6 +2978,20 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, cast<VarDecl>(D)->getMemberSpecializationInfo()->setPointOfInstantiation( Reader.ReadSourceLocation(ModuleFile, Record, Idx)); break; + + case UPD_CXX_DEDUCED_RETURN_TYPE: { + FunctionDecl *FD = cast<FunctionDecl>(D); + Reader.Context.adjustDeducedFunctionResultType( + FD, Reader.readType(ModuleFile, Record, Idx)); + break; + } + + case UPD_DECL_MARKED_USED: { + // FIXME: This doesn't send the right notifications if there are + // ASTMutationListeners other than an ASTWriter. + D->Used = true; + break; + } } } } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index e1357ba..1115e8f 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -25,6 +25,7 @@ using namespace clang::serialization; namespace clang { class ASTStmtReader : public StmtVisitor<ASTStmtReader> { + friend class OMPClauseReader; typedef ASTReader::RecordData RecordData; ASTReader &Reader; @@ -382,6 +383,7 @@ void ASTStmtReader::VisitMSAsmStmt(MSAsmStmt *S) { void ASTStmtReader::VisitCapturedStmt(CapturedStmt *S) { VisitStmt(S); + ++Idx; S->setCapturedDecl(ReadDeclAs<CapturedDecl>(Record, Idx)); S->setCapturedRegionKind(static_cast<CapturedRegionKind>(Record[Idx++])); S->setCapturedRecordDecl(ReadDeclAs<RecordDecl>(Record, Idx)); @@ -723,7 +725,6 @@ void ASTStmtReader::VisitInitListExpr(InitListExpr *E) { } else E->ArrayFillerOrUnionFieldInit = ReadDeclAs<FieldDecl>(Record, Idx); E->sawArrayRangeDesignator(Record[Idx++]); - E->setInitializesStdInitializerList(Record[Idx++]); unsigned NumInits = Record[Idx++]; E->reserveInits(Reader.getContext(), NumInits); if (isArrayFiller) { @@ -834,6 +835,7 @@ void ASTStmtReader::VisitChooseExpr(ChooseExpr *E) { E->setRHS(Reader.ReadSubExpr()); E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); + E->setIsConditionTrue(Record[Idx++]); } void ASTStmtReader::VisitGNUNullExpr(GNUNullExpr *E) { @@ -847,11 +849,19 @@ void ASTStmtReader::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { unsigned NumExprs = Record[Idx++]; while (NumExprs--) Exprs.push_back(Reader.ReadSubExpr()); - E->setExprs(Reader.getContext(), Exprs.data(), Exprs.size()); + E->setExprs(Reader.getContext(), Exprs); E->setBuiltinLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitConvertVectorExpr(ConvertVectorExpr *E) { + VisitExpr(E); + E->BuiltinLoc = ReadSourceLocation(Record, Idx); + E->RParenLoc = ReadSourceLocation(Record, Idx); + E->TInfo = GetTypeSourceInfo(Record, Idx); + E->SrcExpr = Reader.ReadSubExpr(); +} + void ASTStmtReader::VisitBlockExpr(BlockExpr *E) { VisitExpr(E); E->setBlockDecl(ReadDeclAs<BlockDecl>(Record, Idx)); @@ -1190,7 +1200,7 @@ void ASTStmtReader::VisitCXXConstructExpr(CXXConstructExpr *E) { E->setListInitialization(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); - E->ParenRange = ReadSourceRange(Record, Idx); + E->ParenOrBraceRange = ReadSourceRange(Record, Idx); } void ASTStmtReader::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E) { @@ -1205,6 +1215,7 @@ void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { unsigned NumArrayIndexVars = Record[Idx++]; E->IntroducerRange = ReadSourceRange(Record, Idx); E->CaptureDefault = static_cast<LambdaCaptureDefault>(Record[Idx++]); + E->CaptureDefaultLoc = ReadSourceLocation(Record, Idx); E->ExplicitParams = Record[Idx++]; E->ExplicitResultType = Record[Idx++]; E->ClosingBrace = ReadSourceLocation(Record, Idx); @@ -1227,6 +1238,12 @@ void ASTStmtReader::VisitLambdaExpr(LambdaExpr *E) { } } +void +ASTStmtReader::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { + VisitExpr(E); + E->SubExpr = Reader.ReadSubExpr(); +} + void ASTStmtReader::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { VisitExplicitCastExpr(E); SourceRange R = ReadSourceRange(Record, Idx); @@ -1254,7 +1271,7 @@ void ASTStmtReader::VisitCXXConstCastExpr(CXXConstCastExpr *E) { void ASTStmtReader::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { VisitExplicitCastExpr(E); - E->setTypeBeginLoc(ReadSourceLocation(Record, Idx)); + E->setLParenLoc(ReadSourceLocation(Record, Idx)); E->setRParenLoc(ReadSourceLocation(Record, Idx)); } @@ -1576,6 +1593,7 @@ void ASTStmtReader::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtReader::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); E->Temporary = Reader.ReadSubExpr(); + E->ExtendingDecl = ReadDeclAs<ValueDecl>(Record, Idx); } void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { @@ -1650,11 +1668,114 @@ void ASTStmtReader::VisitAsTypeExpr(AsTypeExpr *E) { } //===----------------------------------------------------------------------===// +// OpenMP Clauses. +//===----------------------------------------------------------------------===// + +namespace clang { +class OMPClauseReader : public OMPClauseVisitor<OMPClauseReader> { + ASTStmtReader *Reader; + ASTContext &Context; + const ASTReader::RecordData &Record; + unsigned &Idx; +public: + OMPClauseReader(ASTStmtReader *R, ASTContext &C, + const ASTReader::RecordData &Record, unsigned &Idx) + : Reader(R), Context(C), Record(Record), Idx(Idx) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + OMPClause *readClause(); +}; +} + +OMPClause *OMPClauseReader::readClause() { + OMPClause *C; + switch (Record[Idx++]) { + case OMPC_default: + C = new (Context) OMPDefaultClause(); + break; + case OMPC_private: + C = OMPPrivateClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_firstprivate: + C = OMPFirstprivateClause::CreateEmpty(Context, Record[Idx++]); + break; + case OMPC_shared: + C = OMPSharedClause::CreateEmpty(Context, Record[Idx++]); + break; + } + Visit(C); + C->setLocStart(Reader->ReadSourceLocation(Record, Idx)); + C->setLocEnd(Reader->ReadSourceLocation(Record, Idx)); + + return C; +} + +void OMPClauseReader::VisitOMPDefaultClause(OMPDefaultClause *C) { + C->setDefaultKind( + static_cast<OpenMPDefaultClauseKind>(Record[Idx++])); + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + C->setDefaultKindKwLoc(Reader->ReadSourceLocation(Record, Idx)); +} + +void OMPClauseReader::VisitOMPPrivateClause(OMPPrivateClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +void OMPClauseReader::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +void OMPClauseReader::VisitOMPSharedClause(OMPSharedClause *C) { + C->setLParenLoc(Reader->ReadSourceLocation(Record, Idx)); + unsigned NumVars = C->varlist_size(); + SmallVector<Expr *, 16> Vars; + Vars.reserve(NumVars); + for (unsigned i = 0; i != NumVars; ++i) + Vars.push_back(Reader->Reader.ReadSubExpr()); + C->setVarRefs(Vars); +} + +//===----------------------------------------------------------------------===// +// OpenMP Directives. +//===----------------------------------------------------------------------===// +void ASTStmtReader::VisitOMPExecutableDirective(OMPExecutableDirective *E) { + VisitStmt(E); + ++Idx; + E->setLocStart(ReadSourceLocation(Record, Idx)); + E->setLocEnd(ReadSourceLocation(Record, Idx)); + OMPClauseReader ClauseReader(this, Reader.getContext(), Record, Idx); + SmallVector<OMPClause *, 5> Clauses; + for (unsigned i = 0; i < E->getNumClauses(); ++i) + Clauses.push_back(ClauseReader.readClause()); + E->setClauses(Clauses); + E->setAssociatedStmt(Reader.ReadSubStmt()); +} + +void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitOMPExecutableDirective(D); +} + +//===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// Stmt *ASTReader::ReadStmt(ModuleFile &F) { switch (ReadingKind) { + case Read_None: + llvm_unreachable("should not call this when not reading anything"); case Read_Decl: case Read_Type: return ReadStmtFromStream(F); @@ -1815,7 +1936,7 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { case STMT_CAPTURED: S = CapturedStmt::CreateDeserialized(Context, - Record[ASTStmtReader::NumExprFields]); + Record[ASTStmtReader::NumStmtFields]); break; case EXPR_PREDEFINED: @@ -2004,6 +2125,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ShuffleVectorExpr(Empty); break; + case EXPR_CONVERT_VECTOR: + S = new (Context) ConvertVectorExpr(Empty); + break; + case EXPR_BLOCK: S = new (Context) BlockExpr(Empty); break; @@ -2115,6 +2240,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { DeclarationNameInfo(), 0); break; + case STMT_OMP_PARALLEL_DIRECTIVE: + S = + OMPParallelDirective::CreateEmpty(Context, + Record[ASTStmtReader::NumStmtFields], + Empty); + break; case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); @@ -2160,6 +2291,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) UserDefinedLiteral(Context, Empty); break; + case EXPR_CXX_STD_INITIALIZER_LIST: + S = new (Context) CXXStdInitializerListExpr(Empty); + break; + case EXPR_CXX_BOOL_LITERAL: S = new (Context) CXXBoolLiteralExpr(Empty); break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index b8ada04..405488c 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); +} diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 67349db..55f830a 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -68,6 +68,9 @@ namespace clang { ClassTemplateSpecializationDecl *D); void VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); + void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); + void VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *D); void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); @@ -90,6 +93,7 @@ namespace clang { void VisitTemplateDecl(TemplateDecl *D); void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitVarTemplateDecl(VarTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); @@ -184,7 +188,10 @@ void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { VisitRedeclarable(D); VisitTypeDecl(D); - Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + Record.push_back(D->isModed()); + if (D->isModed()) + Writer.AddTypeRef(D->getUnderlyingType(), Record); } void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { @@ -192,7 +199,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - D->getFirstDeclaration() == D->getMostRecentDecl() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -217,10 +224,13 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { Record.push_back(D->isCompleteDefinition()); Record.push_back(D->isEmbeddedInDeclarator()); Record.push_back(D->isFreeStanding()); + Record.push_back(D->isCompleteDefinitionRequired()); Writer.AddSourceLocation(D->getRBraceLoc(), Record); Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Writer.AddQualifierInfo(*D->getExtInfo(), Record); + else if (D->hasDeclaratorForAnonDecl()) + Writer.AddDeclRef(D->getDeclaratorForAnonDecl(), Record); else Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record); } @@ -248,7 +258,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->getFirstDeclaration() == D->getMostRecentDecl() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -274,7 +284,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - D->getFirstDeclaration() == D->getMostRecentDecl() && + D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -334,7 +344,8 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { Record.push_back(D->hasImplicitReturnZero()); Record.push_back(D->isConstexpr()); Record.push_back(D->HasSkippedBody); - Record.push_back(D->getLinkage()); + Record.push_back(D->isLateTemplateParsed()); + Record.push_back(D->getLinkageInternal()); Writer.AddSourceLocation(D->getLocEnd(), Record); Record.push_back(D->getTemplatedKind()); @@ -517,6 +528,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { // FIXME: stable encoding for @public/@private/@protected/@package Record.push_back(D->getAccessControl()); Record.push_back(D->getSynthesize()); + Record.push_back(D->getBackingIvarReferencedInAccessor()); if (!D->hasAttrs() && !D->isImplicit() && @@ -694,7 +706,9 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { Record.push_back(D->isCXXForRangeDecl()); Record.push_back(D->isARCPseudoStrong()); Record.push_back(D->isConstexpr()); - Record.push_back(D->getLinkage()); + Record.push_back(D->isInitCapture()); + Record.push_back(D->isPreviousDeclInSameBlockScope()); + Record.push_back(D->getLinkageInternal()); if (D->getInit()) { Record.push_back(!D->isInitKnownICE() ? 1 : (D->isInitICE() ? 3 : 2)); @@ -702,14 +716,21 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { } else { Record.push_back(0); } - - MemberSpecializationInfo *SpecInfo - = D->isStaticDataMember() ? D->getMemberSpecializationInfo() : 0; - Record.push_back(SpecInfo != 0); - if (SpecInfo) { + + enum { + VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization + }; + if (VarTemplateDecl *TemplD = D->getDescribedVarTemplate()) { + Record.push_back(VarTemplate); + Writer.AddDeclRef(TemplD, Record); + } else if (MemberSpecializationInfo *SpecInfo + = D->getMemberSpecializationInfo()) { + Record.push_back(StaticDataMemberSpecialization); Writer.AddDeclRef(SpecInfo->getInstantiatedFrom(), Record); Record.push_back(SpecInfo->getTemplateSpecializationKind()); Writer.AddSourceLocation(SpecInfo->getPointOfInstantiation(), Record); + } else { + Record.push_back(VarNotTemplate); } if (!D->hasAttrs() && @@ -722,12 +743,15 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && - D->getFirstDeclaration() == D->getMostRecentDecl() && + D->getFirstDecl() == D->getMostRecentDecl() && D->getInitStyle() == VarDecl::CInit && D->getInit() == 0 && !isa<ParmVarDecl>(D) && + !isa<VarTemplateSpecializationDecl>(D) && !D->isConstexpr() && - !SpecInfo) + !D->isInitCapture() && + !D->isPreviousDeclInSameBlockScope() && + !D->getMemberSpecializationInfo()) AbbrevToUse = Writer.getDeclVarAbbrev(); Code = serialization::DECL_VAR; @@ -905,16 +929,17 @@ void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { VisitNamedDecl(D); - Writer.AddSourceLocation(D->getUsingLocation(), Record); + Writer.AddSourceLocation(D->getUsingLoc(), Record); Writer.AddNestedNameSpecifierLoc(D->getQualifierLoc(), Record); Writer.AddDeclarationNameLoc(D->DNLoc, D->getDeclName(), Record); Writer.AddDeclRef(D->FirstUsingShadow.getPointer(), Record); - Record.push_back(D->isTypeName()); + Record.push_back(D->hasTypename()); Writer.AddDeclRef(Context.getInstantiatedFromUsingDecl(D), Record); Code = serialization::DECL_USING; } void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { + VisitRedeclarable(D); VisitNamedDecl(D); Writer.AddDeclRef(D->getTargetDecl(), Record); Writer.AddDeclRef(D->UsingOrNextShadow, Record); @@ -997,7 +1022,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { VisitCXXMethodDecl(D); Record.push_back(D->IsExplicitSpecified); - Record.push_back(D->ImplicitlyDefined); Writer.AddCXXCtorInitializers(D->CtorInitializers, D->NumCtorInitializers, Record); @@ -1007,7 +1031,6 @@ void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { VisitCXXMethodDecl(D); - Record.push_back(D->ImplicitlyDefined); Writer.AddDeclRef(D->OperatorDelete, Record); Code = serialization::DECL_CXX_DESTRUCTOR; @@ -1089,7 +1112,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that // getCommonPtr() can be used while this is still initializing. - if (D->isFirstDeclaration()) { + if (D->isFirstDecl()) { // This declaration owns the 'common' pointer, so serialize that data now. Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); if (D->getInstantiatedFromMemberTemplate()) @@ -1103,7 +1126,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDeclaration()) { + if (D->isFirstDecl()) { typedef llvm::FoldingSetVector<ClassTemplateSpecializationDecl> CTSDSetTy; CTSDSetTy &CTSDSet = D->getSpecializations(); Record.push_back(CTSDSet.size()); @@ -1141,13 +1164,6 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record); } - // Explicit info. - Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record); - if (D->getTypeAsWritten()) { - Writer.AddSourceLocation(D->getExternLoc(), Record); - Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record); - } - Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record); Writer.AddSourceLocation(D->getPointOfInstantiation(), Record); Record.push_back(D->getSpecializationKind()); @@ -1158,6 +1174,13 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record); } + // Explicit info. + Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record); + if (D->getTypeAsWritten()) { + Writer.AddSourceLocation(D->getExternLoc(), Record); + Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record); + } + Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; } @@ -1166,12 +1189,83 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( VisitClassTemplateSpecializationDecl(D); Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); + Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record); + + // These are read/set from/to the first declaration. + if (D->getPreviousDecl() == 0) { + Writer.AddDeclRef(D->getInstantiatedFromMember(), Record); + Record.push_back(D->isMemberSpecialization()); + } + + Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; +} + +void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) { + VisitRedeclarableTemplateDecl(D); + + if (D->isFirstDecl()) { + typedef llvm::FoldingSetVector<VarTemplateSpecializationDecl> VTSDSetTy; + VTSDSetTy &VTSDSet = D->getSpecializations(); + Record.push_back(VTSDSet.size()); + for (VTSDSetTy::iterator I = VTSDSet.begin(), E = VTSDSet.end(); I != E; + ++I) { + assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); + Writer.AddDeclRef(&*I, Record); + } - Record.push_back(D->getNumTemplateArgsAsWritten()); - for (int i = 0, e = D->getNumTemplateArgsAsWritten(); i != e; ++i) - Writer.AddTemplateArgumentLoc(D->getTemplateArgsAsWritten()[i], Record); + typedef llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> + VTPSDSetTy; + VTPSDSetTy &VTPSDSet = D->getPartialSpecializations(); + Record.push_back(VTPSDSet.size()); + for (VTPSDSetTy::iterator I = VTPSDSet.begin(), E = VTPSDSet.end(); I != E; + ++I) { + assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); + Writer.AddDeclRef(&*I, Record); + } + } + Code = serialization::DECL_VAR_TEMPLATE; +} - Record.push_back(D->getSequenceNumber()); +void ASTDeclWriter::VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *D) { + VisitVarDecl(D); + + llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> + InstFrom = D->getSpecializedTemplateOrPartial(); + if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { + Writer.AddDeclRef(InstFromD, Record); + } else { + Writer.AddDeclRef(InstFrom.get<VarTemplatePartialSpecializationDecl *>(), + Record); + Writer.AddTemplateArgumentList(&D->getTemplateInstantiationArgs(), Record); + } + + // Explicit info. + Writer.AddTypeSourceInfo(D->getTypeAsWritten(), Record); + if (D->getTypeAsWritten()) { + Writer.AddSourceLocation(D->getExternLoc(), Record); + Writer.AddSourceLocation(D->getTemplateKeywordLoc(), Record); + } + + Writer.AddTemplateArgumentList(&D->getTemplateArgs(), Record); + Writer.AddSourceLocation(D->getPointOfInstantiation(), Record); + Record.push_back(D->getSpecializationKind()); + Record.push_back(D->isCanonicalDecl()); + + if (D->isCanonicalDecl()) { + // When reading, we'll add it to the folding set of the following template. + Writer.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl(), Record); + } + + Code = serialization::DECL_VAR_TEMPLATE_SPECIALIZATION; +} + +void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( + VarTemplatePartialSpecializationDecl *D) { + VisitVarTemplateSpecializationDecl(D); + + Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); + Writer.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten(), Record); // These are read/set from/to the first declaration. if (D->getPreviousDecl() == 0) { @@ -1179,7 +1273,7 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( Record.push_back(D->isMemberSpecialization()); } - Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; + Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION; } void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( @@ -1193,7 +1287,7 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDeclaration()) { + if (D->isFirstDecl()) { // This FunctionTemplateDecl owns the CommonPtr; write it. // Write the function specialization declarations. @@ -1310,7 +1404,7 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, template <typename T> void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { - T *First = D->getFirstDeclaration(); + T *First = D->getFirstDecl(); if (First->getMostRecentDecl() != First) { assert(isRedeclarableDeclKind(static_cast<T *>(D)->getKind()) && "Not considered redeclarable?"); @@ -1412,6 +1506,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { // ObjC Ivar Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize + // getBackingIvarReferencedInAccessor + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); @@ -1447,6 +1543,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl @@ -1494,6 +1591,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypedefNameAnonDecl @@ -1541,6 +1639,8 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(0)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(0)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr + Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture + Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope Abv->Add(BitCodeAbbrevOp(0)); // Linkage Abv->Add(BitCodeAbbrevOp(0)); // HasInit Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo @@ -1620,7 +1720,9 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Linkage + Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture + Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasMemberSpecInfo // Type Source Info diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 5f7ac01..072fc98 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file implements serialization for Statements and Expressions. -// +/// +/// \file +/// \brief Implements serialization for Statements and Expressions. +/// //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTWriter.h" @@ -26,7 +27,9 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace clang { + class ASTStmtWriter : public StmtVisitor<ASTStmtWriter, void> { + friend class OMPClauseWriter; ASTWriter &Writer; ASTWriter::RecordData &Record; @@ -683,7 +686,6 @@ void ASTStmtWriter::VisitInitListExpr(InitListExpr *E) { else Writer.AddDeclRef(E->getInitializedFieldInUnion(), Record); Record.push_back(E->hadArrayRangeDesignator()); - Record.push_back(E->initializesStdInitializerList()); Record.push_back(E->getNumInits()); if (isArrayFiller) { // ArrayFiller may have filled "holes" due to designated initializer. @@ -772,6 +774,7 @@ void ASTStmtWriter::VisitChooseExpr(ChooseExpr *E) { Writer.AddStmt(E->getRHS()); Writer.AddSourceLocation(E->getBuiltinLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); + Record.push_back(E->isConditionDependent() ? false : E->isConditionTrue()); Code = serialization::EXPR_CHOOSE; } @@ -791,6 +794,15 @@ void ASTStmtWriter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { Code = serialization::EXPR_SHUFFLE_VECTOR; } +void ASTStmtWriter::VisitConvertVectorExpr(ConvertVectorExpr *E) { + VisitExpr(E); + Writer.AddSourceLocation(E->getBuiltinLoc(), Record); + Writer.AddSourceLocation(E->getRParenLoc(), Record); + Writer.AddTypeSourceInfo(E->getTypeSourceInfo(), Record); + Writer.AddStmt(E->getSrcExpr()); + Code = serialization::EXPR_CONVERT_VECTOR; +} + void ASTStmtWriter::VisitBlockExpr(BlockExpr *E) { VisitExpr(E); Writer.AddDeclRef(E->getBlockDecl(), Record); @@ -1145,7 +1157,7 @@ void ASTStmtWriter::VisitCXXConstructExpr(CXXConstructExpr *E) { Record.push_back(E->isListInitialization()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding - Writer.AddSourceRange(E->getParenRange(), Record); + Writer.AddSourceRange(E->getParenOrBraceRange(), Record); Code = serialization::EXPR_CXX_CONSTRUCT; } @@ -1164,6 +1176,7 @@ void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { Record.push_back(NumArrayIndexVars); Writer.AddSourceRange(E->IntroducerRange, Record); Record.push_back(E->CaptureDefault); // FIXME: stable encoding + Writer.AddSourceLocation(E->CaptureDefaultLoc, Record); Record.push_back(E->ExplicitParams); Record.push_back(E->ExplicitResultType); Writer.AddSourceLocation(E->ClosingBrace, Record); @@ -1187,6 +1200,12 @@ void ASTStmtWriter::VisitLambdaExpr(LambdaExpr *E) { Code = serialization::EXPR_LAMBDA; } +void ASTStmtWriter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getSubExpr()); + Code = serialization::EXPR_CXX_STD_INITIALIZER_LIST; +} + void ASTStmtWriter::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { VisitExplicitCastExpr(E); Writer.AddSourceRange(SourceRange(E->getOperatorLoc(), E->getRParenLoc()), @@ -1216,7 +1235,7 @@ void ASTStmtWriter::VisitCXXConstCastExpr(CXXConstCastExpr *E) { void ASTStmtWriter::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E) { VisitExplicitCastExpr(E); - Writer.AddSourceLocation(E->getTypeBeginLoc(), Record); + Writer.AddSourceLocation(E->getLParenLoc(), Record); Writer.AddSourceLocation(E->getRParenLoc(), Record); Code = serialization::EXPR_CXX_FUNCTIONAL_CAST; } @@ -1572,6 +1591,7 @@ void ASTStmtWriter::VisitFunctionParmPackExpr(FunctionParmPackExpr *E) { void ASTStmtWriter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { VisitExpr(E); Writer.AddStmt(E->Temporary); + Writer.AddDeclRef(E->ExtendingDecl, Record); Code = serialization::EXPR_MATERIALIZE_TEMPORARY; } @@ -1653,6 +1673,84 @@ void ASTStmtWriter::VisitSEHTryStmt(SEHTryStmt *S) { } //===----------------------------------------------------------------------===// +// OpenMP Clauses. +//===----------------------------------------------------------------------===// + +namespace clang { +class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> { + ASTStmtWriter *Writer; + ASTWriter::RecordData &Record; +public: + OMPClauseWriter(ASTStmtWriter *W, ASTWriter::RecordData &Record) + : Writer(W), Record(Record) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(Class *S); +#include "clang/Basic/OpenMPKinds.def" + void writeClause(OMPClause *C); +}; +} + +void OMPClauseWriter::writeClause(OMPClause *C) { + Record.push_back(C->getClauseKind()); + Visit(C); + Writer->Writer.AddSourceLocation(C->getLocStart(), Record); + Writer->Writer.AddSourceLocation(C->getLocEnd(), Record); +} + +void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) { + Record.push_back(C->getDefaultKind()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + Writer->Writer.AddSourceLocation(C->getDefaultKindKwLoc(), Record); +} + +void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (OMPPrivateClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) + Writer->Writer.AddStmt(*I); +} + +void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (OMPFirstprivateClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) + Writer->Writer.AddStmt(*I); +} + +void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) { + Record.push_back(C->varlist_size()); + Writer->Writer.AddSourceLocation(C->getLParenLoc(), Record); + for (OMPSharedClause::varlist_iterator I = C->varlist_begin(), + E = C->varlist_end(); + I != E; ++I) + Writer->Writer.AddStmt(*I); +} + +//===----------------------------------------------------------------------===// +// OpenMP Directives. +//===----------------------------------------------------------------------===// +void ASTStmtWriter::VisitOMPExecutableDirective(OMPExecutableDirective *E) { + VisitStmt(E); + Record.push_back(E->getNumClauses()); + Writer.AddSourceLocation(E->getLocStart(), Record); + Writer.AddSourceLocation(E->getLocEnd(), Record); + OMPClauseWriter ClauseWriter(this, Record); + for (unsigned i = 0; i < E->getNumClauses(); ++i) { + ClauseWriter.writeClause(E->getClause(i)); + } + Writer.AddStmt(E->getAssociatedStmt()); +} + +void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) { + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_DIRECTIVE; +} + +//===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Serialization/GeneratePCH.cpp b/lib/Serialization/GeneratePCH.cpp index 32c2df3..7e8baa2 100644 --- a/lib/Serialization/GeneratePCH.cpp +++ b/lib/Serialization/GeneratePCH.cpp @@ -28,22 +28,29 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile, clang::Module *Module, StringRef isysroot, - raw_ostream *OS) + raw_ostream *OS, bool AllowASTWithErrors) : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()), Out(OS), - SemaPtr(0), Stream(Buffer), Writer(Stream) { + SemaPtr(0), Stream(Buffer), Writer(Stream), + AllowASTWithErrors(AllowASTWithErrors), + HasEmittedPCH(false) { } PCHGenerator::~PCHGenerator() { } void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { - if (PP.getDiagnostics().hasErrorOccurred()) + // Don't create a PCH if there were fatal failures during module loading. + if (PP.getModuleLoader().HadFatalFailure) + return; + + bool hasErrors = PP.getDiagnostics().hasErrorOccurred(); + if (hasErrors && !AllowASTWithErrors) return; // Emit the PCH file assert(SemaPtr && "No Sema?"); - Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot); + Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors); // Write the generated bitstream to "Out". Out->write((char *)&Buffer.front(), Buffer.size()); @@ -53,6 +60,8 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { // Free up some memory, in case the process is kept alive. Buffer.clear(); + + HasEmittedPCH = true; } ASTMutationListener *PCHGenerator::GetASTMutationListener() { diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp index b6693e4..fb647b0 100644 --- a/lib/Serialization/GlobalModuleIndex.cpp +++ b/lib/Serialization/GlobalModuleIndex.cpp @@ -26,7 +26,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/LockFileManager.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PathV2.h" +#include "llvm/Support/Path.h" #include <cstdio> using namespace clang; using namespace serialization; @@ -229,7 +229,8 @@ GlobalModuleIndex::readIndex(StringRef Path) { llvm::sys::path::append(IndexPath, IndexFileName); llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - if (llvm::MemoryBuffer::getFile(IndexPath, Buffer) != llvm::errc::success) + if (llvm::MemoryBuffer::getFile(IndexPath.c_str(), Buffer) != + llvm::errc::success) return std::make_pair((GlobalModuleIndex *)0, EC_NotFound); /// \brief The bitstream reader from which we'll read the AST file. @@ -790,7 +791,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { // Write the global index file to a temporary file. llvm::SmallString<128> IndexTmpPath; int TmpFD; - if (llvm::sys::fs::unique_file(IndexPath + "-%%%%%%%%", TmpFD, IndexTmpPath)) + if (llvm::sys::fs::createUniqueFile(IndexPath + "-%%%%%%%%", TmpFD, + IndexTmpPath)) return EC_IOError; // Open the temporary global index file for output. diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp index f3d53ad..9c4b3d9 100644 --- a/lib/Serialization/ModuleManager.cpp +++ b/lib/Serialization/ModuleManager.cpp @@ -12,10 +12,10 @@ // //===----------------------------------------------------------------------===// #include "clang/Lex/ModuleMap.h" -#include "clang/Serialization/ModuleManager.h" #include "clang/Serialization/GlobalModuleIndex.h" +#include "clang/Serialization/ModuleManager.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PathV2.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" @@ -62,11 +62,13 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, // Look for the file entry. This only fails if the expected size or // modification time differ. const FileEntry *Entry; - if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) + if (lookupModuleFile(FileName, ExpectedSize, ExpectedModTime, Entry)) { + ErrorStr = "module file out of date"; return OutOfDate; + } if (!Entry && FileName != "-") { - ErrorStr = "file not found"; + ErrorStr = "module file not found"; return Missing; } @@ -332,8 +334,7 @@ ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), break; // Pop the next module off the stack. - NextModule = State->Stack.back(); - State->Stack.pop_back(); + NextModule = State->Stack.pop_back_val(); } while (true); } |