diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp | 146 |
1 files changed, 108 insertions, 38 deletions
diff --git a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp index 0d15b17..8b68638 100644 --- a/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp +++ b/contrib/llvm/tools/clang/lib/Serialization/ASTWriter.cpp @@ -421,9 +421,13 @@ void ASTTypeWriter::VisitObjCInterfaceType(const ObjCInterfaceType *T) { void ASTTypeWriter::VisitObjCObjectType(const ObjCObjectType *T) { Writer.AddTypeRef(T->getBaseType(), Record); + Record.push_back(T->getTypeArgsAsWritten().size()); + for (auto TypeArg : T->getTypeArgsAsWritten()) + Writer.AddTypeRef(TypeArg, Record); Record.push_back(T->getNumProtocols()); for (const auto *I : T->quals()) Writer.AddDeclRef(I, Record); + Record.push_back(T->isKindOfTypeAsWritten()); Code = TYPE_OBJC_OBJECT; } @@ -648,8 +652,12 @@ void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { } void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { Record.push_back(TL.hasBaseTypeAsWritten()); - Writer.AddSourceLocation(TL.getLAngleLoc(), Record); - Writer.AddSourceLocation(TL.getRAngleLoc(), Record); + Writer.AddSourceLocation(TL.getTypeArgsLAngleLoc(), Record); + Writer.AddSourceLocation(TL.getTypeArgsRAngleLoc(), Record); + for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i) + Writer.AddTypeSourceInfo(TL.getTypeArgTInfo(i), Record); + Writer.AddSourceLocation(TL.getProtocolLAngleLoc(), Record); + Writer.AddSourceLocation(TL.getProtocolRAngleLoc(), Record); for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) Writer.AddSourceLocation(TL.getProtocolLoc(i), Record); } @@ -3626,6 +3634,55 @@ ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC, /// bitstream, or 0 if no block was written. uint64_t ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC) { + // If we imported a key declaration of this namespace, write the visible + // lookup results as an update record for it rather than including them + // on this declaration. We will only look at key declarations on reload. + if (isa<NamespaceDecl>(DC) && Chain && + Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) { + // Only do this once, for the first local declaration of the namespace. + for (NamespaceDecl *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev; + Prev = Prev->getPreviousDecl()) + if (!Prev->isFromASTFile()) + return 0; + + // Note that we need to emit an update record for the primary context. + UpdatedDeclContexts.insert(DC->getPrimaryContext()); + + // Make sure all visible decls are written. They will be recorded later. We + // do this using a side data structure so we can sort the names into + // a deterministic order. + StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup(); + SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16> + LookupResults; + if (Map) { + LookupResults.reserve(Map->size()); + for (auto &Entry : *Map) + LookupResults.push_back( + std::make_pair(Entry.first, Entry.second.getLookupResult())); + } + + std::sort(LookupResults.begin(), LookupResults.end(), llvm::less_first()); + for (auto &NameAndResult : LookupResults) { + DeclarationName Name = NameAndResult.first; + DeclContext::lookup_result Result = NameAndResult.second; + if (Name.getNameKind() == DeclarationName::CXXConstructorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + // We have to work around a name lookup bug here where negative lookup + // results for these names get cached in namespace lookup tables (these + // names should never be looked up in a namespace). + assert(Result.empty() && "Cannot have a constructor or conversion " + "function name in a namespace!"); + continue; + } + + for (NamedDecl *ND : Result) + if (!ND->isFromASTFile()) + GetDeclRef(ND); + } + + return 0; + } + if (DC->getPrimaryContext() != DC) return 0; @@ -3677,6 +3734,11 @@ void ASTWriter::WriteDeclContextVisibleUpdate(const DeclContext *DC) { SmallString<4096> LookupTable; uint32_t BucketOffset = GenerateNameLookupTable(DC, LookupTable); + // If we're updating a namespace, select a key declaration as the key for the + // update record; those are the only ones that will be checked on reload. + if (isa<NamespaceDecl>(DC)) + DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC))); + // Write the lookup table RecordData Record; Record.push_back(UPDATE_VISIBLE); @@ -3709,11 +3771,17 @@ void ASTWriter::WriteRedeclarations() { SmallVector<serialization::LocalRedeclarationsInfo, 2> LocalRedeclsMap; for (unsigned I = 0, N = Redeclarations.size(); I != N; ++I) { - Decl *First = Redeclarations[I]; - assert(First->isFirstDecl() && "Not the first declaration?"); - - Decl *MostRecent = First->getMostRecentDecl(); - + const Decl *Key = Redeclarations[I]; + assert((Chain ? Chain->getKeyDeclaration(Key) == Key + : Key->isFirstDecl()) && + "not the key declaration"); + + const Decl *First = Key->getCanonicalDecl(); + const Decl *MostRecent = First->getMostRecentDecl(); + + assert((getDeclID(First) >= NUM_PREDEF_DECL_IDS || First == Key) && + "should not have imported key decls for predefined decl"); + // If we only have a single declaration, there is no point in storing // a redeclaration chain. if (First == MostRecent) @@ -3722,34 +3790,34 @@ void ASTWriter::WriteRedeclarations() { unsigned Offset = LocalRedeclChains.size(); unsigned Size = 0; LocalRedeclChains.push_back(0); // Placeholder for the size. - + // Collect the set of local redeclarations of this declaration. - for (Decl *Prev = MostRecent; Prev != First; + for (const Decl *Prev = MostRecent; Prev; Prev = Prev->getPreviousDecl()) { - if (!Prev->isFromASTFile()) { + if (!Prev->isFromASTFile() && Prev != Key) { AddDeclRef(Prev, LocalRedeclChains); ++Size; } } LocalRedeclChains[Offset] = Size; - + // Reverse the set of local redeclarations, so that we store them in // order (since we found them in reverse order). std::reverse(LocalRedeclChains.end() - Size, LocalRedeclChains.end()); - + // Add the mapping from the first ID from the AST to the set of local // declarations. - LocalRedeclarationsInfo Info = { getDeclID(First), Offset }; + LocalRedeclarationsInfo Info = { getDeclID(Key), Offset }; LocalRedeclsMap.push_back(Info); - + assert(N == Redeclarations.size() && "Deserialized a declaration we shouldn't have"); } - + if (LocalRedeclChains.empty()) return; - + // Sort the local redeclarations map by the first declaration ID, // since the reader will be performing binary searches on this information. llvm::array_pod_sort(LocalRedeclsMap.begin(), LocalRedeclsMap.end()); @@ -4045,25 +4113,27 @@ void ASTWriter::WriteASTCore(Sema &SemaRef, Preprocessor &PP = SemaRef.PP; // Set up predefined declaration IDs. - DeclIDs[Context.getTranslationUnitDecl()] = PREDEF_DECL_TRANSLATION_UNIT_ID; - if (Context.ObjCIdDecl) - DeclIDs[Context.ObjCIdDecl] = PREDEF_DECL_OBJC_ID_ID; - if (Context.ObjCSelDecl) - DeclIDs[Context.ObjCSelDecl] = PREDEF_DECL_OBJC_SEL_ID; - if (Context.ObjCClassDecl) - DeclIDs[Context.ObjCClassDecl] = PREDEF_DECL_OBJC_CLASS_ID; - if (Context.ObjCProtocolClassDecl) - DeclIDs[Context.ObjCProtocolClassDecl] = PREDEF_DECL_OBJC_PROTOCOL_ID; - if (Context.Int128Decl) - DeclIDs[Context.Int128Decl] = PREDEF_DECL_INT_128_ID; - if (Context.UInt128Decl) - DeclIDs[Context.UInt128Decl] = PREDEF_DECL_UNSIGNED_INT_128_ID; - if (Context.ObjCInstanceTypeDecl) - DeclIDs[Context.ObjCInstanceTypeDecl] = PREDEF_DECL_OBJC_INSTANCETYPE_ID; - if (Context.BuiltinVaListDecl) - DeclIDs[Context.getBuiltinVaListDecl()] = PREDEF_DECL_BUILTIN_VA_LIST_ID; - if (Context.ExternCContext) - DeclIDs[Context.ExternCContext] = PREDEF_DECL_EXTERN_C_CONTEXT_ID; + auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { + if (D) { + assert(D->isCanonicalDecl() && "predefined decl is not canonical"); + DeclIDs[D] = ID; + if (D->getMostRecentDecl() != D) + Redeclarations.push_back(D); + } + }; + RegisterPredefDecl(Context.getTranslationUnitDecl(), + PREDEF_DECL_TRANSLATION_UNIT_ID); + RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID); + RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID); + RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID); + RegisterPredefDecl(Context.ObjCProtocolClassDecl, + PREDEF_DECL_OBJC_PROTOCOL_ID); + RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID); + RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID); + RegisterPredefDecl(Context.ObjCInstanceTypeDecl, + PREDEF_DECL_OBJC_INSTANCETYPE_ID); + RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID); + RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID); // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for @@ -5667,7 +5737,7 @@ void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { assert(!DoneWritingDeclsAndTypes && "Already done writing updates!"); if (!Chain) return; - Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) { + Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { // If we don't already know the exception specification for this redecl // chain, add an update record for it. if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D) @@ -5681,7 +5751,7 @@ void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) { void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) { assert(!WritingAST && "Already writing the AST!"); if (!Chain) return; - Chain->forEachFormerlyCanonicalImportedDecl(FD, [&](const Decl *D) { + Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) { DeclUpdates[D].push_back( DeclUpdate(UPD_CXX_DEDUCED_RETURN_TYPE, ReturnType)); }); @@ -5692,7 +5762,7 @@ void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD, assert(!WritingAST && "Already writing the AST!"); assert(Delete && "Not given an operator delete"); if (!Chain) return; - Chain->forEachFormerlyCanonicalImportedDecl(DD, [&](const Decl *D) { + Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) { DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_RESOLVED_DTOR_DELETE, Delete)); }); } |