aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Serialization/ASTReader.h11
-rw-r--r--lib/Serialization/ASTReader.cpp104
-rw-r--r--test/Modules/Inputs/diamond_bottom.h1
-rw-r--r--test/Modules/Inputs/diamond_left.h1
-rw-r--r--test/Modules/Inputs/diamond_right.h1
-rw-r--r--test/Modules/Inputs/diamond_top.h1
-rw-r--r--test/Modules/diamond.c14
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