From: Richard Smith Date: Fri, 18 Oct 2013 06:54:39 +0000 (+0000) Subject: C++ modules: don't lose track of a 'namespace std' that is imported from a module. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9b6711873cbba149dd50cedcfdf31f9dd254df50;p=clang C++ modules: don't lose track of a 'namespace std' that is imported from a module. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192951 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 00528cc387..d3cca1a849 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1268,6 +1268,9 @@ public: /// \brief Initializes the ASTContext void InitializeContext(); + /// \brief Update the state of Sema after loading some additional modules. + void UpdateSema(); + /// \brief Add in-memory (virtual file) buffer. void addInMemoryBuffer(StringRef &FileName, llvm::MemoryBuffer *Buffer) { ModuleMgr.addInMemoryBuffer(FileName, Buffer); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index bafe74b174..6fe03c7d55 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2524,9 +2524,10 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { break; case SEMA_DECL_REFS: - // Later tables overwrite earlier ones. - // FIXME: Modules will have some trouble with this. - SemaDeclRefs.clear(); + if (Record.size() != 2) { + Error("Invalid SEMA_DECL_REFS block"); + return true; + } for (unsigned I = 0, N = Record.size(); I != N; ++I) SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I])); break; @@ -3035,6 +3036,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, InitializeContext(); + if (SemaObj) + UpdateSema(); + if (DeserializationListener) DeserializationListener->ReaderInitialized(this); @@ -6136,21 +6140,13 @@ void ASTReader::InitializeSema(Sema &S) { } PreloadedDecls.clear(); - // Load the offsets of the declarations that Sema references. - // They will be lazily deserialized when needed. - if (!SemaDeclRefs.empty()) { - assert(SemaDeclRefs.size() == 2 && "More decl refs than expected!"); - if (!SemaObj->StdNamespace) - SemaObj->StdNamespace = SemaDeclRefs[0]; - if (!SemaObj->StdBadAlloc) - SemaObj->StdBadAlloc = SemaDeclRefs[1]; - } - + // FIXME: What happens if these are changed by a module import? if (!FPPragmaOptions.empty()) { assert(FPPragmaOptions.size() == 1 && "Wrong number of FP_PRAGMA_OPTIONS"); SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0]; } + // FIXME: What happens if these are changed by a module import? if (!OpenCLExtensions.empty()) { unsigned I = 0; #define OPENCLEXT(nm) SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++]; @@ -6158,6 +6154,25 @@ void ASTReader::InitializeSema(Sema &S) { assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS"); } + + UpdateSema(); +} + +void ASTReader::UpdateSema() { + assert(SemaObj && "no Sema to update"); + + // Load the offsets of the declarations that Sema references. + // They will be lazily deserialized when needed. + if (!SemaDeclRefs.empty()) { + assert(SemaDeclRefs.size() % 2 == 0); + for (unsigned I = 0; I != SemaDeclRefs.size(); I += 2) { + if (!SemaObj->StdNamespace) + SemaObj->StdNamespace = SemaDeclRefs[I]; + if (!SemaObj->StdBadAlloc) + SemaObj->StdBadAlloc = SemaDeclRefs[I+1]; + } + SemaDeclRefs.clear(); + } } IdentifierInfo* ASTReader::get(const char *NameStart, const char *NameEnd) { diff --git a/test/Modules/Inputs/initializer_list b/test/Modules/Inputs/initializer_list new file mode 100644 index 0000000000..6058f803a3 --- /dev/null +++ b/test/Modules/Inputs/initializer_list @@ -0,0 +1,9 @@ +namespace std { + using size_t = decltype(sizeof(0)); + + template struct initializer_list { + initializer_list(T*, size_t); + }; + + template int min(initializer_list); +} diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 7534eb253d..12da7a649a 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -254,3 +254,7 @@ module incomplete_mod { module warning { header "warning.h" } + +module initializer_list { + header "initializer_list" +} diff --git a/test/Modules/initializer_list.cpp b/test/Modules/initializer_list.cpp new file mode 100644 index 0000000000..0cbcbbb70e --- /dev/null +++ b/test/Modules/initializer_list.cpp @@ -0,0 +1,7 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11 + +// expected-no-diagnostics +@import initializer_list; + +int n = std::min({1, 2, 3});