diff options
-rw-r--r-- | clang/include/clang/Sema/ExternalSemaSource.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Sema/MultiplexExternalSemaSource.h | 4 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTReader.h | 8 | ||||
-rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 13 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/MethodPoolCombined1.h | 6 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/MethodPoolCombined2.h | 1 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/MethodPoolString1.h | 4 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/MethodPoolString2.h | 4 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/module.map | 17 | ||||
-rw-r--r-- | clang/test/Modules/method_pool_write.m | 11 |
15 files changed, 94 insertions, 0 deletions
diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h index 2fdc42b..c2b1304 100644 --- a/clang/include/clang/Sema/ExternalSemaSource.h +++ b/clang/include/clang/Sema/ExternalSemaSource.h @@ -70,6 +70,10 @@ public: /// selector. virtual void ReadMethodPool(Selector Sel); + /// Load the contents of the global method pool for a given + /// selector if necessary. + virtual void updateOutOfDateSelector(Selector Sel); + /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. virtual void ReadKnownNamespaces( diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h index 5f43f40..9bf8cd3 100644 --- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h @@ -203,6 +203,10 @@ public: /// selector. void ReadMethodPool(Selector Sel) override; + /// Load the contents of the global method pool for a given + /// selector if necessary. + void updateOutOfDateSelector(Selector Sel) override; + /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. void diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a0dcd70..7731569 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1017,6 +1017,7 @@ public: llvm::SmallSet<SpecialMemberDecl, 4> SpecialMembersBeingDeclared; void ReadMethodPool(Selector Sel); + void updateOutOfDateSelector(Selector Sel); /// Private Helper predicate to check for 'self'. bool isSelfExpr(Expr *RExpr); diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index a80989d..6e1cb0a 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -653,6 +653,10 @@ private: /// global method pool for this selector. llvm::DenseMap<Selector, unsigned> SelectorGeneration; + /// Whether a selector is out of date. We mark a selector as out of date + /// if we load another module after the method pool entry was pulled in. + llvm::DenseMap<Selector, bool> SelectorOutOfDate; + struct PendingMacroInfo { ModuleFile *M; uint64_t MacroDirectivesOffset; @@ -1781,6 +1785,10 @@ public: /// selector. void ReadMethodPool(Selector Sel) override; + /// Load the contents of the global method pool for a given + /// selector if necessary. + void updateOutOfDateSelector(Selector Sel) override; + /// \brief Load the set of namespaces that are known to the external source, /// which will be used during typo correction. void ReadKnownNamespaces( diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp index 89eec24..eee4c00 100644 --- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp @@ -197,6 +197,11 @@ void MultiplexExternalSemaSource::ReadMethodPool(Selector Sel) { Sources[i]->ReadMethodPool(Sel); } +void MultiplexExternalSemaSource::updateOutOfDateSelector(Selector Sel) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->updateOutOfDateSelector(Sel); +} + void MultiplexExternalSemaSource::ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl*> &Namespaces){ for(size_t i = 0; i < Sources.size(); ++i) diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 541b318..d8d10b6 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1237,6 +1237,7 @@ void Sema::ActOnComment(SourceRange Comment) { ExternalSemaSource::~ExternalSemaSource() {} void ExternalSemaSource::ReadMethodPool(Selector Sel) { } +void ExternalSemaSource::updateOutOfDateSelector(Selector Sel) { } void ExternalSemaSource::ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces) { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 8090bec..400dc63 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -3305,6 +3305,12 @@ void Sema::ReadMethodPool(Selector Sel) { ExternalSource->ReadMethodPool(Sel); } +void Sema::updateOutOfDateSelector(Selector Sel) { + if (!ExternalSource) + return; + ExternalSource->updateOutOfDateSelector(Sel); +} + void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance) { // Ignore methods of invalid containers. diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 910f5dc..aa672b3 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3606,6 +3606,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName, Id != IdEnd; ++Id) Id->second->setOutOfDate(true); } + // Mark selectors as out of date. + for (auto Sel : SelectorGeneration) + SelectorOutOfDate[Sel.first] = true; // Resolve any unresolved module exports. for (unsigned I = 0, N = UnresolvedModuleRefs.size(); I != N; ++I) { @@ -7139,6 +7142,7 @@ void ASTReader::ReadMethodPool(Selector Sel) { unsigned &Generation = SelectorGeneration[Sel]; unsigned PriorGeneration = Generation; Generation = getGeneration(); + SelectorOutOfDate[Sel] = false; // Search for methods defined with this selector. ++NumMethodPoolLookups; @@ -7170,6 +7174,11 @@ void ASTReader::ReadMethodPool(Selector Sel) { addMethodsToPool(S, Visitor.getFactoryMethods(), Pos->second.second); } +void ASTReader::updateOutOfDateSelector(Selector Sel) { + if (SelectorOutOfDate[Sel]) + ReadMethodPool(Sel); +} + void ASTReader::ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces) { Namespaces.clear(); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 32c9c47..606228a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4387,6 +4387,19 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } } + // For method pool in the module, if it contains an entry for a selector, + // the entry should be complete, containing everything introduced by that + // module and all modules it imports. It's possible that the entry is out of + // date, so we need to pull in the new content here. + + // It's possible that updateOutOfDateSelector can update SelectorIDs. To be + // safe, we copy all selectors out. + llvm::SmallVector<Selector, 256> AllSelectors; + for (auto &SelectorAndID : SelectorIDs) + AllSelectors.push_back(SelectorAndID.first); + for (auto &Selector : AllSelectors) + SemaRef.updateOutOfDateSelector(Selector); + // Form the record of special types. RecordData SpecialTypes; AddTypeRef(Context.getRawCFConstantStringType(), SpecialTypes); diff --git a/clang/test/Modules/Inputs/MethodPoolCombined1.h b/clang/test/Modules/Inputs/MethodPoolCombined1.h new file mode 100644 index 0000000..057b738 --- /dev/null +++ b/clang/test/Modules/Inputs/MethodPoolCombined1.h @@ -0,0 +1,6 @@ + +@import MethodPoolString1; +@interface A +- (int)stringValue; +@end + diff --git a/clang/test/Modules/Inputs/MethodPoolCombined2.h b/clang/test/Modules/Inputs/MethodPoolCombined2.h new file mode 100644 index 0000000..166906e --- /dev/null +++ b/clang/test/Modules/Inputs/MethodPoolCombined2.h @@ -0,0 +1 @@ +@import MethodPoolString2; diff --git a/clang/test/Modules/Inputs/MethodPoolString1.h b/clang/test/Modules/Inputs/MethodPoolString1.h new file mode 100644 index 0000000..c64ad95 --- /dev/null +++ b/clang/test/Modules/Inputs/MethodPoolString1.h @@ -0,0 +1,4 @@ + +@interface S1 +- (int)stringValue; +@end diff --git a/clang/test/Modules/Inputs/MethodPoolString2.h b/clang/test/Modules/Inputs/MethodPoolString2.h new file mode 100644 index 0000000..30e9bfb --- /dev/null +++ b/clang/test/Modules/Inputs/MethodPoolString2.h @@ -0,0 +1,4 @@ + +@interface S2 +- (int)stringValue; +@end diff --git a/clang/test/Modules/Inputs/module.map b/clang/test/Modules/Inputs/module.map index 632517d..1249387 100644 --- a/clang/test/Modules/Inputs/module.map +++ b/clang/test/Modules/Inputs/module.map @@ -393,3 +393,20 @@ module ElaboratedTypeStructs { header "elaborated-type-structs.h" } } + +// We import a module, then declare a method with selector stringValue in +// MethodPoolCombined1.h. In MethodPoolCombined2.h, we import another module +// that also contains a method for selector stringValue. We make sure that +// the method pool entry for stringValue in this module is complete. +module MethodPoolCombined { + header "MethodPoolCombined1.h" + header "MethodPoolCombined2.h" +} + +module MethodPoolString1 { + header "MethodPoolString1.h" +} + +module MethodPoolString2 { + header "MethodPoolString2.h" +} diff --git a/clang/test/Modules/method_pool_write.m b/clang/test/Modules/method_pool_write.m new file mode 100644 index 0000000..b7f8ac64b --- /dev/null +++ b/clang/test/Modules/method_pool_write.m @@ -0,0 +1,11 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fsyntax-only -I %S/Inputs %s -verify +// expected-no-diagnostics + +@import MethodPoolCombined; +@import MethodPoolString2; + +void message_kindof_object(__kindof S2 *kindof_S2) { + [kindof_S2 stringValue]; +} + |