aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td15
-rw-r--r--include/clang/Lex/HeaderSearch.h22
-rw-r--r--include/clang/Lex/ModuleMap.h124
3 files changed, 160 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index f1e8c75d6b..97095e792c 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -374,4 +374,19 @@ def err_pp_include_in_arc_cf_code_audited : Error<
def err_pp_eof_in_arc_cf_code_audited : Error<
"'#pragma clang arc_cf_code_audited' was not ended within this file">;
+// Module map parsing
+def err_mmap_unknown_token : Error<"skipping stray token">;
+def err_mmap_expected_module : Error<"expected module declaration">;
+def err_mmap_expected_module_after_explicit : Error<
+ "expected 'module' keyword after 'explicit'">;
+def err_mmap_expected_module_name : Error<"expected module name">;
+def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">;
+def err_mmap_expected_rbrace : Error<"expected '}'">;
+def note_mmap_lbrace_match : Note<"to match this '{'">;
+def err_mmap_expected_member : Error<
+ "expected umbrella header, header, or submodule">;
+def err_mmap_expected_header : Error<"expected a header name after '%0'">;
+def err_mmap_module_redefinition : Error<
+ "redefinition of module '%0'">;
+def note_mmap_prev_definition : Note<"previously defined here">;
}
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 0b21373858..995deab9dc 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_LEX_HEADERSEARCH_H
#include "clang/Lex/DirectoryLookup.h"
+#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Allocator.h"
@@ -151,7 +152,6 @@ class HeaderSearch {
llvm::StringMap<std::pair<unsigned, unsigned>, llvm::BumpPtrAllocator>
LookupFileCache;
-
/// FrameworkMap - This is a collection mapping a framework or subframework
/// name like "Carbon" to the Carbon.framework directory.
llvm::StringMap<const DirectoryEntry *, llvm::BumpPtrAllocator>
@@ -161,6 +161,12 @@ class HeaderSearch {
/// headermaps. This vector owns the headermap.
std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
+ /// \brief The mapping between modules and headers.
+ ModuleMap ModMap;
+
+ /// \brief Describes whether a given directory has a module map in it.
+ llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap;
+
/// \brief Uniqued set of framework names, which is used to track which
/// headers were included as framework headers.
llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames;
@@ -347,6 +353,20 @@ public:
void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
+ /// \brief Determine whether there is a module map that may map the header
+ /// with the given file name to a (sub)module.
+ ///
+ /// \param Filename The name of the file.
+ ///
+ /// \param Root The "root" directory, at which we should stop looking for
+ /// module maps.
+ bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root);
+
+ /// \brief Retrieve the module that corresponds to the given file, if any.
+ ///
+ /// FIXME: This will need to be generalized for submodules.
+ StringRef getModuleForHeader(const FileEntry *File);
+
typedef std::vector<HeaderFileInfo>::const_iterator header_file_iterator;
header_file_iterator header_file_begin() const { return FileInfo.begin(); }
header_file_iterator header_file_end() const { return FileInfo.end(); }
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
new file mode 100644
index 0000000000..2834f6a11b
--- /dev/null
+++ b/include/clang/Lex/ModuleMap.h
@@ -0,0 +1,124 @@
+//===--- ModuleMap.h - Describe the layout of modules -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ModuleMap interface, which describes the layout of a
+// module as it relates to headers.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_CLANG_LEX_MODULEMAP_H
+#define LLVM_CLANG_LEX_MODULEMAP_H
+
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+#include <string>
+
+namespace clang {
+
+class FileEntry;
+class FileManager;
+class DiagnosticConsumer;
+class DiagnosticsEngine;
+class ModuleMapParser;
+
+class ModuleMap {
+public:
+ /// \brief Describes a module or submodule.
+ struct Module {
+ /// \brief The name of this module.
+ std::string Name;
+
+ /// \brief The location of the module definition.
+ SourceLocation DefinitionLoc;
+
+ /// \brief The parent of this module. This will be NULL for the top-level
+ /// module.
+ Module *Parent;
+
+ /// \brief The umbrella header, if any.
+ ///
+ /// Only the top-level module can have an umbrella header.
+ const FileEntry *UmbrellaHeader;
+
+ /// \brief The submodules of this module, indexed by name.
+ llvm::StringMap<Module *> SubModules;
+
+ /// \brief The headers that are part of this module.
+ llvm::SmallVector<const FileEntry *, 2> Headers;
+
+ /// \brief Whether this is an explicit submodule.
+ bool IsExplicit;
+
+ /// \brief Construct a top-level module.
+ explicit Module(StringRef Name, SourceLocation DefinitionLoc)
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0),
+ IsExplicit(false) { }
+
+ /// \brief Construct a new module or submodule.
+ Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
+ bool IsExplicit)
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
+ UmbrellaHeader(0), IsExplicit(IsExplicit) {
+ }
+
+ /// \brief Determine whether this module is a submodule.
+ bool isSubModule() const { return Parent != 0; }
+
+ /// \brief Retrieve the full name of this module, including the path from
+ /// its top-level module.
+ std::string getFullModuleName() const;
+ };
+
+private:
+ SourceManager *SourceMgr;
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+ LangOptions LangOpts;
+
+ /// \brief The top-level modules that are known
+ llvm::StringMap<Module *> Modules;
+
+ /// \brief Mapping from each header to the module that owns the contents of the
+ /// that header.
+ llvm::DenseMap<const FileEntry *, Module *> Headers;
+
+ friend class ModuleMapParser;
+
+public:
+ /// \brief Construct a new module map.
+ ///
+ /// \param FileMgr The file manager used to find module files and headers.
+ /// This file manager should be shared with the header-search mechanism, since
+ /// they will refer to the same headers.
+ ///
+ /// \param DC A diagnostic consumer that will be cloned for use in generating
+ /// diagnostics.
+ ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC);
+
+ ~ModuleMap();
+
+ /// \brief Parse the given module map file, and record any modules we
+ /// encounter.
+ ///
+ /// \param File The file to be parsed.
+ ///
+ /// \returns true if an error occurred, false otherwise.
+ bool parseModuleMapFile(const FileEntry *File);
+
+ /// \brief Dump the contents of the module map, for debugging purposes.
+ void dump();
+};
+
+}
+#endif