xref: /llvm-project/clang/lib/Basic/Module.cpp (revision 322f633c1c148a474d7d3b1176ca63c1f744b04c)
1 //===--- Module.h - Describe a module ---------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the Module class, which describes a module in the source
11 // code.
12 //
13 //===----------------------------------------------------------------------===//
14 #include "clang/Basic/Module.h"
15 #include "clang/Basic/FileManager.h"
16 #include "llvm/Support/raw_ostream.h"
17 using namespace clang;
18 
19 Module::~Module() {
20   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
21                                         IEnd = SubModules.end();
22        I != IEnd; ++I) {
23     delete I->getValue();
24   }
25 
26 }
27 
28 bool Module::isSubModuleOf(Module *Other) const {
29   const Module *This = this;
30   do {
31     if (This == Other)
32       return true;
33 
34     This = This->Parent;
35   } while (This);
36 
37   return false;
38 }
39 
40 const Module *Module::getTopLevelModule() const {
41   const Module *Result = this;
42   while (Result->Parent)
43     Result = Result->Parent;
44 
45   return Result;
46 }
47 
48 std::string Module::getFullModuleName() const {
49   llvm::SmallVector<StringRef, 2> Names;
50 
51   // Build up the set of module names (from innermost to outermost).
52   for (const Module *M = this; M; M = M->Parent)
53     Names.push_back(M->Name);
54 
55   std::string Result;
56   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
57                                                       IEnd = Names.rend();
58        I != IEnd; ++I) {
59     if (!Result.empty())
60       Result += '.';
61 
62     Result += *I;
63   }
64 
65   return Result;
66 }
67 
68 const DirectoryEntry *Module::getUmbrellaDir() const {
69   if (const FileEntry *Header = getUmbrellaHeader())
70     return Header->getDir();
71 
72   return Umbrella.dyn_cast<const DirectoryEntry *>();
73 }
74 
75 static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
76   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
77     if (I)
78       OS << ".";
79     OS << Id[I].first;
80   }
81 }
82 
83 void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
84   OS.indent(Indent);
85   if (IsFramework)
86     OS << "framework ";
87   if (IsExplicit)
88     OS << "explicit ";
89   OS << "module " << Name << " {\n";
90 
91   if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
92     OS.indent(Indent + 2);
93     OS << "umbrella header \"";
94     OS.write_escaped(UmbrellaHeader->getName());
95     OS << "\"\n";
96   } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) {
97     OS.indent(Indent + 2);
98     OS << "umbrella \"";
99     OS.write_escaped(UmbrellaDir->getName());
100     OS << "\"\n";
101   }
102 
103   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
104     OS.indent(Indent + 2);
105     OS << "header \"";
106     OS.write_escaped(Headers[I]->getName());
107     OS << "\"\n";
108   }
109 
110   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
111                                               MIEnd = SubModules.end();
112        MI != MIEnd; ++MI)
113     MI->getValue()->print(OS, Indent + 2);
114 
115   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
116     OS.indent(Indent + 2);
117     OS << "export ";
118     if (Module *Restriction = Exports[I].getPointer()) {
119       OS << Restriction->getFullModuleName();
120       if (Exports[I].getInt())
121         OS << ".*";
122     } else {
123       OS << "*";
124     }
125     OS << "\n";
126   }
127 
128   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
129     OS.indent(Indent + 2);
130     OS << "export ";
131     printModuleId(OS, UnresolvedExports[I].Id);
132     if (UnresolvedExports[I].Wildcard) {
133       if (UnresolvedExports[I].Id.empty())
134         OS << "*";
135       else
136         OS << ".*";
137     }
138     OS << "\n";
139   }
140 
141   if (InferSubmodules) {
142     OS.indent(Indent + 2);
143     if (InferExplicitSubmodules)
144       OS << "explicit ";
145     OS << "module * {\n";
146     if (InferExportWildcard) {
147       OS.indent(Indent + 4);
148       OS << "export *\n";
149     }
150     OS.indent(Indent + 2);
151     OS << "}\n";
152   }
153 
154   OS.indent(Indent);
155   OS << "}\n";
156 }
157 
158 void Module::dump() const {
159   print(llvm::errs());
160 }
161 
162 
163