diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -8474,18 +8474,20 @@ continue; } - NamedDecl *D = cast(GetDecl(DeclIDs[I])); + if (Decl *DeserializedD = GetDecl(DeclIDs[I])) { + NamedDecl *D = cast(DeserializedD); - // If we're simply supposed to record the declarations, do so now. - if (Decls) { - Decls->push_back(D); - continue; - } + // If we're simply supposed to record the declarations, do so now. + if (Decls) { + Decls->push_back(D); + continue; + } - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - pushExternalDeclIntoScope(D, II); + // Introduce this declaration into the translation-unit scope + // and add it to the declaration chain for this identifier, so + // that (unqualified) name lookup will find it. + pushExternalDeclIntoScope(D, II); + } } } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3870,6 +3870,15 @@ llvm::report_fatal_error( Twine("ASTReader::readDeclRecord failed reading decl code: ") + toString(MaybeDeclCode.takeError())); + if (unsigned DeclSubmoduleID = getGlobalSubmoduleID(*Loc.F, Record.readInt())) { + if (SemaObj) { + Module *DeclOwner = getSubmodule(DeclSubmoduleID); + if (DeclOwner && !SemaObj->isModuleVisible(DeclOwner)) { + // Skip deserialization of Decls from a hidden module. + return nullptr; + } + } + } switch ((DeclCode)MaybeDeclCode.get()) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -269,6 +269,7 @@ } void ASTDeclWriter::Visit(Decl *D) { + Record.push_back(Writer.getSubmoduleID(D->getOwningModule())); DeclVisitor::Visit(D); // Source locations require array (variable-length) abbreviations. The @@ -1911,6 +1912,7 @@ // Abbreviation for DECL_FIELD Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -1944,6 +1946,7 @@ // Abbreviation for DECL_OBJC_IVAR Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext @@ -1980,6 +1983,7 @@ // Abbreviation for DECL_ENUM Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl @@ -2030,6 +2034,7 @@ // Abbreviation for DECL_RECORD Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl @@ -2092,6 +2097,7 @@ // Abbreviation for DECL_PARM_VAR Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl @@ -2140,6 +2146,7 @@ // Abbreviation for DECL_TYPEDEF Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl @@ -2169,6 +2176,7 @@ // Abbreviation for DECL_VAR Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // Redeclarable Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl @@ -2221,6 +2229,7 @@ // Abbreviation for DECL_CXX_METHOD Abv = std::make_shared(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID // RedeclarableDecl Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl // Decl diff --git a/clang/test/Modules/ambiguous-enum-lookup.m b/clang/test/Modules/ambiguous-enum-lookup.m new file mode 100644 --- /dev/null +++ b/clang/test/Modules/ambiguous-enum-lookup.m @@ -0,0 +1,42 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache -F %t/Frameworks %t/test.m + +//--- Frameworks/NonModular.framework/Headers/NonModular.h +#ifndef NonModular_NonModular_h +#define NonModular_NonModular_h +struct SomeStruct { + int x; +}; + +enum SomeEnum { + kEnumValue = 1, +}; +#endif + +//--- Frameworks/PiecewiseVisible.framework/Headers/InitiallyVisible.h +// empty + +//--- Frameworks/PiecewiseVisible.framework/Headers/InitiallyHidden.h +#include + +//--- Frameworks/PiecewiseVisible.framework/Modules/module.modulemap +framework module PiecewiseVisible { + header "InitiallyVisible.h" + export * + + explicit module HiddenPiece { + header "InitiallyHidden.h" + export * + } +} + +//--- test.m +#include +#include +#include + +void test() { + struct SomeStruct s; + s.x = kEnumValue; +}