summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp37
-rw-r--r--clang/test/Modules/Inputs/va_list/left.h7
-rw-r--r--clang/test/Modules/Inputs/va_list/module.modulemap3
-rw-r--r--clang/test/Modules/Inputs/va_list/right.h7
-rw-r--r--clang/test/Modules/Inputs/va_list/top.h1
-rw-r--r--clang/test/Modules/va_list.cpp8
6 files changed, 57 insertions, 6 deletions
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 95c1620fcbb..331fa385905 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -5630,27 +5630,52 @@ void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
}
}
+static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {
+ if (D->isFromASTFile())
+ return true;
+
+ // If we've not loaded any modules, this can't be imported.
+ if (!Chain || !Chain->getModuleManager().size())
+ return false;
+
+ // The predefined __va_list_tag struct is imported if we imported any decls.
+ // FIXME: This is a gross hack.
+ return D == D->getASTContext().getVaListTagDecl();
+}
+
void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
// TU and namespaces are handled elsewhere.
if (isa<TranslationUnitDecl>(DC) || isa<NamespaceDecl>(DC))
return;
- if (!(!D->isFromASTFile() && cast<Decl>(DC)->isFromASTFile()))
- return; // Not a source decl added to a DeclContext from PCH.
+ // We're only interested in cases where a local declaration is added to an
+ // imported context.
+ if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC)))
+ return;
assert(DC == DC->getPrimaryContext() && "added to non-primary context");
assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
assert(!WritingAST && "Already writing the AST!");
- UpdatedDeclContexts.insert(DC);
+ if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {
+ // We're adding a visible declaration to a predefined decl context. Ensure
+ // that we write out all of its lookup results so we don't get a nasty
+ // surprise when we try to emit its lookup table.
+ for (auto *Child : DC->decls())
+ UpdatingVisibleDecls.push_back(Child);
+ }
UpdatingVisibleDecls.push_back(D);
}
void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
assert(D->isImplicit());
- if (!(!D->isFromASTFile() && RD->isFromASTFile()))
- return; // Not a source member added to a class from PCH.
+
+ // We're only interested in cases where a local declaration is added to an
+ // imported context.
+ if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD))
+ return;
+
if (!isa<CXXMethodDecl>(D))
- return; // We are interested in lazily declared implicit methods.
+ return;
// A decl coming from PCH was modified.
assert(RD->isCompleteDefinition());
diff --git a/clang/test/Modules/Inputs/va_list/left.h b/clang/test/Modules/Inputs/va_list/left.h
new file mode 100644
index 00000000000..6842f9f7d0a
--- /dev/null
+++ b/clang/test/Modules/Inputs/va_list/left.h
@@ -0,0 +1,7 @@
+@import top;
+
+template<typename T>
+void f(int k, ...) {
+ va_list va;
+ __builtin_va_start(va, k);
+}
diff --git a/clang/test/Modules/Inputs/va_list/module.modulemap b/clang/test/Modules/Inputs/va_list/module.modulemap
index 870f38bb0ec..bd9c61456fb 100644
--- a/clang/test/Modules/Inputs/va_list/module.modulemap
+++ b/clang/test/Modules/Inputs/va_list/module.modulemap
@@ -1,2 +1,5 @@
module va_list_a { header "va_list_a.h" }
module va_list_b { header "va_list_b.h" }
+module top { header "top.h" }
+module left { header "left.h" }
+module right { header "right.h" }
diff --git a/clang/test/Modules/Inputs/va_list/right.h b/clang/test/Modules/Inputs/va_list/right.h
new file mode 100644
index 00000000000..6842f9f7d0a
--- /dev/null
+++ b/clang/test/Modules/Inputs/va_list/right.h
@@ -0,0 +1,7 @@
+@import top;
+
+template<typename T>
+void f(int k, ...) {
+ va_list va;
+ __builtin_va_start(va, k);
+}
diff --git a/clang/test/Modules/Inputs/va_list/top.h b/clang/test/Modules/Inputs/va_list/top.h
new file mode 100644
index 00000000000..5660b876552
--- /dev/null
+++ b/clang/test/Modules/Inputs/va_list/top.h
@@ -0,0 +1 @@
+typedef __builtin_va_list va_list;
diff --git a/clang/test/Modules/va_list.cpp b/clang/test/Modules/va_list.cpp
new file mode 100644
index 00000000000..35694cdec6f
--- /dev/null
+++ b/clang/test/Modules/va_list.cpp
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/va_list %s -verify
+// expected-no-diagnostics
+
+@import left;
+@import right;
+
+void g(int k, ...) { f<int>(k); }
OpenPOWER on IntegriCloud