diff options
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 37 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/va_list/left.h | 7 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/va_list/module.modulemap | 3 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/va_list/right.h | 7 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/va_list/top.h | 1 | ||||
-rw-r--r-- | clang/test/Modules/va_list.cpp | 8 |
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); } |