diff options
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 104 | ||||
-rw-r--r-- | test/Modules/Inputs/diamond_bottom.h | 1 | ||||
-rw-r--r-- | test/Modules/Inputs/diamond_left.h | 1 | ||||
-rw-r--r-- | test/Modules/Inputs/diamond_right.h | 1 | ||||
-rw-r--r-- | test/Modules/Inputs/diamond_top.h | 1 | ||||
-rw-r--r-- | test/Modules/diamond.c | 14 |
7 files changed, 93 insertions, 40 deletions
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 514d36db91..4ed86480c8 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -507,8 +507,15 @@ public: /// /// \param ImportedBy The module that is importing this module, or NULL if /// this module is imported directly by the user. - Module &addModule(StringRef FileName, ModuleKind Type, - Module *ImportedBy); + /// + /// \param ErrorStr Will be set to a non-empty string if any errors occurred + /// while trying to load the module. + /// + /// \return A pointer to the module that corresponds to this file name, + /// and a boolean indicating whether the module was newly added. + std::pair<Module *, bool> + addModule(StringRef FileName, ModuleKind Type, Module *ImportedBy, + std::string &ErrorStr); /// \brief Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index d81e9d8a36..840b665cd7 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2831,37 +2831,33 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName, ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName, ModuleKind Type, Module *ImportedBy) { - Module &F = ModuleMgr.addModule(FileName, Type, ImportedBy); + Module *M; + bool NewModule; + std::string ErrorStr; + llvm::tie(M, NewModule) = ModuleMgr.addModule(FileName, Type, ImportedBy, + ErrorStr); + + if (!M) { + // We couldn't load the module. + std::string Msg = "Unable to load module \"" + FileName.str() + "\": " + + ErrorStr; + Error(Msg); + return Failure; + } + + if (!NewModule) { + // We've already loaded this module. + return Success; + } + // FIXME: This seems rather a hack. Should CurrentDir be part of the + // module? if (FileName != "-") { CurrentDir = llvm::sys::path::parent_path(FileName); if (CurrentDir.empty()) CurrentDir = "."; } - if (llvm::MemoryBuffer *Buffer = ModuleMgr.lookupBuffer(FileName)) { - F.Buffer.reset(Buffer); - assert(F.Buffer && "Passed null buffer"); - } else { - // Open the AST file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - llvm::error_code ec; - if (FileName == "-") { - ec = llvm::MemoryBuffer::getSTDIN(F.Buffer); - if (ec) - ErrStr = ec.message(); - } else - F.Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrStr)); - if (!F.Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; - } - } - - // Initialize the stream - F.StreamFile.init((const unsigned char *)F.Buffer->getBufferStart(), - (const unsigned char *)F.Buffer->getBufferEnd()); + Module &F = *M; llvm::BitstreamCursor &Stream = F.Stream; Stream.init(F.StreamFile); F.SizeInBits = F.Buffer->getBufferSize() * 8; @@ -5709,25 +5705,57 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) { return InMemoryBuffers[Entry]; } -/// \brief Creates a new module and adds it to the list of known modules -Module &ModuleManager::addModule(StringRef FileName, ModuleKind Type, - Module *ImportedBy) { - Module *Current = new Module(Type); - Current->FileName = FileName.str(); - Chain.push_back(Current); - +std::pair<Module *, bool> +ModuleManager::addModule(StringRef FileName, ModuleKind Type, + Module *ImportedBy, std::string &ErrorStr) { const FileEntry *Entry = FileMgr.getFile(FileName); - // FIXME: Check whether we already loaded this module, before - Modules[Entry] = Current; + if (!Entry && FileName != "-") { + ErrorStr = "file not found"; + return std::make_pair(static_cast<Module*>(0), false); + } + + // Check whether we already loaded this module, before + Module *&ModuleEntry = Modules[Entry]; + bool NewModule = false; + if (!ModuleEntry) { + // Allocate a new module. + Module *New = new Module(Type); + New->FileName = FileName.str(); + Chain.push_back(New); + NewModule = true; + ModuleEntry = New; + + // Load the contents of the module + if (llvm::MemoryBuffer *Buffer = lookupBuffer(FileName)) { + // The buffer was already provided for us. + assert(Buffer && "Passed null buffer"); + New->Buffer.reset(Buffer); + } else { + // Open the AST file. + llvm::error_code ec; + if (FileName == "-") { + ec = llvm::MemoryBuffer::getSTDIN(New->Buffer); + if (ec) + ErrorStr = ec.message(); + } else + New->Buffer.reset(FileMgr.getBufferForFile(FileName, &ErrorStr)); + + if (!New->Buffer) + return std::make_pair(static_cast<Module*>(0), false); + } + + // Initialize the stream + New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), + (const unsigned char *)New->Buffer->getBufferEnd()); } if (ImportedBy) { - Current->ImportedBy.insert(ImportedBy); - ImportedBy->Imports.insert(Current); + ModuleEntry->ImportedBy.insert(ImportedBy); + ImportedBy->Imports.insert(ModuleEntry); } else { - Current->DirectlyImported = true; + ModuleEntry->DirectlyImported = true; } - return *Current; + return std::make_pair(ModuleEntry, NewModule); } void ModuleManager::addInMemoryBuffer(StringRef FileName, diff --git a/test/Modules/Inputs/diamond_bottom.h b/test/Modules/Inputs/diamond_bottom.h new file mode 100644 index 0000000000..40afc9b152 --- /dev/null +++ b/test/Modules/Inputs/diamond_bottom.h @@ -0,0 +1 @@ +char bottom(char *x); diff --git a/test/Modules/Inputs/diamond_left.h b/test/Modules/Inputs/diamond_left.h new file mode 100644 index 0000000000..dfdd803a0a --- /dev/null +++ b/test/Modules/Inputs/diamond_left.h @@ -0,0 +1 @@ +float left(float *); diff --git a/test/Modules/Inputs/diamond_right.h b/test/Modules/Inputs/diamond_right.h new file mode 100644 index 0000000000..bbed7ec805 --- /dev/null +++ b/test/Modules/Inputs/diamond_right.h @@ -0,0 +1 @@ +double right(double *); diff --git a/test/Modules/Inputs/diamond_top.h b/test/Modules/Inputs/diamond_top.h new file mode 100644 index 0000000000..189687aab1 --- /dev/null +++ b/test/Modules/Inputs/diamond_top.h @@ -0,0 +1 @@ +int top(int *); diff --git a/test/Modules/diamond.c b/test/Modules/diamond.c new file mode 100644 index 0000000000..fdec7b3aab --- /dev/null +++ b/test/Modules/diamond.c @@ -0,0 +1,14 @@ +// in diamond-bottom.h: expected-note{{passing argument to parameter 'x' here}} +void test_diamond(int i, float f, double d, char c) { + top(&i); + left(&f); + right(&d); + bottom(&c); + bottom(&d); // expected-warning{{incompatible pointer types passing 'double *' to parameter of type 'char *'}} +} + +// RUN: %clang_cc1 -emit-pch -o %t_top.h.pch %S/Inputs/diamond_top.h +// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_left.h.pch %S/Inputs/diamond_left.h +// RUN: %clang_cc1 -import-module %t_top.h.pch -emit-pch -o %t_right.h.pch %S/Inputs/diamond_right.h +// RUN: %clang_cc1 -import-module %t_left.h.pch -import-module %t_right.h.pch -emit-pch -o %t_bottom.h.pch %S/Inputs/diamond_bottom.h +// RUN: %clang_cc1 -import-module %t_bottom.h.pch -verify %s |