aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/ExternalSemaSource.h4
-rw-r--r--clang/include/clang/Sema/MultiplexExternalSemaSource.h4
-rw-r--r--clang/include/clang/Sema/Sema.h1
-rw-r--r--clang/include/clang/Serialization/ASTReader.h8
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp5
-rw-r--r--clang/lib/Sema/Sema.cpp1
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp6
-rw-r--r--clang/lib/Serialization/ASTReader.cpp9
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp13
-rw-r--r--clang/test/Modules/Inputs/MethodPoolCombined1.h6
-rw-r--r--clang/test/Modules/Inputs/MethodPoolCombined2.h1
-rw-r--r--clang/test/Modules/Inputs/MethodPoolString1.h4
-rw-r--r--clang/test/Modules/Inputs/MethodPoolString2.h4
-rw-r--r--clang/test/Modules/Inputs/module.map17
-rw-r--r--clang/test/Modules/method_pool_write.m11
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];
+}
+