1de3ef502SDouglas Gregor //===--- Module.h - Describe a module ---------------------------*- C++ -*-===//
2de3ef502SDouglas Gregor //
3de3ef502SDouglas Gregor //                     The LLVM Compiler Infrastructure
4de3ef502SDouglas Gregor //
5de3ef502SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6de3ef502SDouglas Gregor // License. See LICENSE.TXT for details.
7de3ef502SDouglas Gregor //
8de3ef502SDouglas Gregor //===----------------------------------------------------------------------===//
9de3ef502SDouglas Gregor //
10de3ef502SDouglas Gregor // This file defines the Module class, which describes a module in the source
11de3ef502SDouglas Gregor // code.
12de3ef502SDouglas Gregor //
13de3ef502SDouglas Gregor //===----------------------------------------------------------------------===//
14de3ef502SDouglas Gregor #include "clang/Basic/Module.h"
15de3ef502SDouglas Gregor #include "clang/Basic/FileManager.h"
16de3ef502SDouglas Gregor #include "llvm/Support/raw_ostream.h"
17de3ef502SDouglas Gregor using namespace clang;
18de3ef502SDouglas Gregor 
19de3ef502SDouglas Gregor Module::~Module() {
20de3ef502SDouglas Gregor   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
21de3ef502SDouglas Gregor                                         IEnd = SubModules.end();
22de3ef502SDouglas Gregor        I != IEnd; ++I) {
23de3ef502SDouglas Gregor     delete I->getValue();
24de3ef502SDouglas Gregor   }
25de3ef502SDouglas Gregor 
26de3ef502SDouglas Gregor }
27de3ef502SDouglas Gregor 
28f5eedd05SDouglas Gregor bool Module::isSubModuleOf(Module *Other) const {
29f5eedd05SDouglas Gregor   const Module *This = this;
30f5eedd05SDouglas Gregor   do {
31f5eedd05SDouglas Gregor     if (This == Other)
32f5eedd05SDouglas Gregor       return true;
33f5eedd05SDouglas Gregor 
34f5eedd05SDouglas Gregor     This = This->Parent;
35f5eedd05SDouglas Gregor   } while (This);
36f5eedd05SDouglas Gregor 
37f5eedd05SDouglas Gregor   return false;
38f5eedd05SDouglas Gregor }
39f5eedd05SDouglas Gregor 
4073441091SDouglas Gregor const Module *Module::getTopLevelModule() const {
4173441091SDouglas Gregor   const Module *Result = this;
4273441091SDouglas Gregor   while (Result->Parent)
4373441091SDouglas Gregor     Result = Result->Parent;
4473441091SDouglas Gregor 
4573441091SDouglas Gregor   return Result;
4673441091SDouglas Gregor }
4773441091SDouglas Gregor 
48de3ef502SDouglas Gregor std::string Module::getFullModuleName() const {
49de3ef502SDouglas Gregor   llvm::SmallVector<StringRef, 2> Names;
50de3ef502SDouglas Gregor 
51de3ef502SDouglas Gregor   // Build up the set of module names (from innermost to outermost).
52de3ef502SDouglas Gregor   for (const Module *M = this; M; M = M->Parent)
53de3ef502SDouglas Gregor     Names.push_back(M->Name);
54de3ef502SDouglas Gregor 
55de3ef502SDouglas Gregor   std::string Result;
56de3ef502SDouglas Gregor   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
57de3ef502SDouglas Gregor                                                       IEnd = Names.rend();
58de3ef502SDouglas Gregor        I != IEnd; ++I) {
59de3ef502SDouglas Gregor     if (!Result.empty())
60de3ef502SDouglas Gregor       Result += '.';
61de3ef502SDouglas Gregor 
62de3ef502SDouglas Gregor     Result += *I;
63de3ef502SDouglas Gregor   }
64de3ef502SDouglas Gregor 
65de3ef502SDouglas Gregor   return Result;
66de3ef502SDouglas Gregor }
67de3ef502SDouglas Gregor 
68*73141fa9SDouglas Gregor const DirectoryEntry *Module::getUmbrellaDir() const {
69*73141fa9SDouglas Gregor   if (const FileEntry *Header = getUmbrellaHeader())
70*73141fa9SDouglas Gregor     return Header->getDir();
71*73141fa9SDouglas Gregor 
72*73141fa9SDouglas Gregor   return Umbrella.dyn_cast<const DirectoryEntry *>();
73*73141fa9SDouglas Gregor }
74*73141fa9SDouglas Gregor 
7524bb923aSDouglas Gregor static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
7624bb923aSDouglas Gregor   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
7724bb923aSDouglas Gregor     if (I)
7824bb923aSDouglas Gregor       OS << ".";
7924bb923aSDouglas Gregor     OS << Id[I].first;
8024bb923aSDouglas Gregor   }
8124bb923aSDouglas Gregor }
8224bb923aSDouglas Gregor 
83de3ef502SDouglas Gregor void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
84de3ef502SDouglas Gregor   OS.indent(Indent);
85de3ef502SDouglas Gregor   if (IsFramework)
86de3ef502SDouglas Gregor     OS << "framework ";
87de3ef502SDouglas Gregor   if (IsExplicit)
88de3ef502SDouglas Gregor     OS << "explicit ";
89de3ef502SDouglas Gregor   OS << "module " << Name << " {\n";
90de3ef502SDouglas Gregor 
91*73141fa9SDouglas Gregor   if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
92de3ef502SDouglas Gregor     OS.indent(Indent + 2);
93de3ef502SDouglas Gregor     OS << "umbrella \"";
94de3ef502SDouglas Gregor     OS.write_escaped(UmbrellaHeader->getName());
95de3ef502SDouglas Gregor     OS << "\"\n";
96de3ef502SDouglas Gregor   }
97de3ef502SDouglas Gregor 
98de3ef502SDouglas Gregor   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
99de3ef502SDouglas Gregor     OS.indent(Indent + 2);
100de3ef502SDouglas Gregor     OS << "header \"";
101de3ef502SDouglas Gregor     OS.write_escaped(Headers[I]->getName());
102de3ef502SDouglas Gregor     OS << "\"\n";
103de3ef502SDouglas Gregor   }
104de3ef502SDouglas Gregor 
105de3ef502SDouglas Gregor   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
106de3ef502SDouglas Gregor                                               MIEnd = SubModules.end();
107de3ef502SDouglas Gregor        MI != MIEnd; ++MI)
108de3ef502SDouglas Gregor     MI->getValue()->print(OS, Indent + 2);
109de3ef502SDouglas Gregor 
11024bb923aSDouglas Gregor   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
11124bb923aSDouglas Gregor     OS.indent(Indent + 2);
1128c7c8352SDouglas Gregor     OS << "export ";
1138c7c8352SDouglas Gregor     if (Module *Restriction = Exports[I].getPointer()) {
1148c7c8352SDouglas Gregor       OS << Restriction->getFullModuleName();
11524bb923aSDouglas Gregor       if (Exports[I].getInt())
11624bb923aSDouglas Gregor         OS << ".*";
1178c7c8352SDouglas Gregor     } else {
1188c7c8352SDouglas Gregor       OS << "*";
1198c7c8352SDouglas Gregor     }
12024bb923aSDouglas Gregor     OS << "\n";
12124bb923aSDouglas Gregor   }
12224bb923aSDouglas Gregor 
12324bb923aSDouglas Gregor   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
12424bb923aSDouglas Gregor     OS.indent(Indent + 2);
12524bb923aSDouglas Gregor     OS << "export ";
12624bb923aSDouglas Gregor     printModuleId(OS, UnresolvedExports[I].Id);
1278c7c8352SDouglas Gregor     if (UnresolvedExports[I].Wildcard) {
1288c7c8352SDouglas Gregor       if (UnresolvedExports[I].Id.empty())
1298c7c8352SDouglas Gregor         OS << "*";
1308c7c8352SDouglas Gregor       else
13124bb923aSDouglas Gregor         OS << ".*";
1328c7c8352SDouglas Gregor     }
13324bb923aSDouglas Gregor     OS << "\n";
13424bb923aSDouglas Gregor   }
13524bb923aSDouglas Gregor 
13673441091SDouglas Gregor   if (InferSubmodules) {
13773441091SDouglas Gregor     OS.indent(Indent + 2);
13873441091SDouglas Gregor     if (InferExplicitSubmodules)
13973441091SDouglas Gregor       OS << "explicit ";
14073441091SDouglas Gregor     OS << "module * {\n";
14173441091SDouglas Gregor     if (InferExportWildcard) {
14273441091SDouglas Gregor       OS.indent(Indent + 4);
14373441091SDouglas Gregor       OS << "export *\n";
14473441091SDouglas Gregor     }
14573441091SDouglas Gregor     OS.indent(Indent + 2);
14673441091SDouglas Gregor     OS << "}\n";
14773441091SDouglas Gregor   }
14873441091SDouglas Gregor 
149de3ef502SDouglas Gregor   OS.indent(Indent);
150de3ef502SDouglas Gregor   OS << "}\n";
151de3ef502SDouglas Gregor }
152de3ef502SDouglas Gregor 
153de3ef502SDouglas Gregor void Module::dump() const {
154de3ef502SDouglas Gregor   print(llvm::errs());
155de3ef502SDouglas Gregor }
156de3ef502SDouglas Gregor 
157de3ef502SDouglas Gregor 
158