xref: /llvm-project/clang/lib/Basic/Module.cpp (revision 1fb5c3a63a88e4758b196f1bda64eecce9b29d3f)
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 "clang/Basic/LangOptions.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringSwitch.h"
21 using namespace clang;
22 
23 Module::~Module() {
24   for (llvm::StringMap<Module *>::iterator I = SubModules.begin(),
25                                         IEnd = SubModules.end();
26        I != IEnd; ++I) {
27     delete I->getValue();
28   }
29 
30 }
31 
32 /// \brief Determine whether a translation unit built using the current
33 /// language options has the given feature.
34 static bool hasFeature(StringRef Feature, const LangOptions &LangOpts) {
35   return llvm::StringSwitch<bool>(Feature)
36            .Case("blocks", LangOpts.Blocks)
37            .Case("cplusplus", LangOpts.CPlusPlus)
38            .Case("cplusplus11", LangOpts.CPlusPlus0x)
39            .Case("objc", LangOpts.ObjC1)
40            .Case("objc_arc", LangOpts.ObjCAutoRefCount)
41            .Default(false);
42 }
43 
44 bool
45 Module::isAvailable(const LangOptions &LangOpts, StringRef &Feature) const {
46   if (IsAvailable)
47     return true;
48 
49   for (const Module *Current = this; Current; Current = Current->Parent) {
50     for (unsigned I = 0, N = Current->Requires.size(); I != N; ++I) {
51       if (!hasFeature(Current->Requires[I], LangOpts)) {
52         Feature = Current->Requires[I];
53         return false;
54       }
55     }
56   }
57 
58   llvm_unreachable("could not find a reason why module is unavailable");
59   return false;
60 }
61 
62 bool Module::isSubModuleOf(Module *Other) const {
63   const Module *This = this;
64   do {
65     if (This == Other)
66       return true;
67 
68     This = This->Parent;
69   } while (This);
70 
71   return false;
72 }
73 
74 const Module *Module::getTopLevelModule() const {
75   const Module *Result = this;
76   while (Result->Parent)
77     Result = Result->Parent;
78 
79   return Result;
80 }
81 
82 std::string Module::getFullModuleName() const {
83   llvm::SmallVector<StringRef, 2> Names;
84 
85   // Build up the set of module names (from innermost to outermost).
86   for (const Module *M = this; M; M = M->Parent)
87     Names.push_back(M->Name);
88 
89   std::string Result;
90   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
91                                                       IEnd = Names.rend();
92        I != IEnd; ++I) {
93     if (!Result.empty())
94       Result += '.';
95 
96     Result += *I;
97   }
98 
99   return Result;
100 }
101 
102 const DirectoryEntry *Module::getUmbrellaDir() const {
103   if (const FileEntry *Header = getUmbrellaHeader())
104     return Header->getDir();
105 
106   return Umbrella.dyn_cast<const DirectoryEntry *>();
107 }
108 
109 void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts) {
110   Requires.push_back(Feature);
111 
112   // If this feature is currently available, we're done.
113   if (hasFeature(Feature, LangOpts))
114     return;
115 
116   if (!IsAvailable)
117     return;
118 
119   llvm::SmallVector<Module *, 2> Stack;
120   Stack.push_back(this);
121   while (!Stack.empty()) {
122     Module *Current = Stack.back();
123     Stack.pop_back();
124 
125     if (!Current->IsAvailable)
126       continue;
127 
128     Current->IsAvailable = false;
129     for (llvm::StringMap<Module *>::iterator Sub = Current->SubModules.begin(),
130                                           SubEnd = Current->SubModules.end();
131          Sub != SubEnd; ++Sub) {
132       if (Sub->second->IsAvailable)
133         Stack.push_back(Sub->second);
134     }
135   }
136 }
137 
138 static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
139   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
140     if (I)
141       OS << ".";
142     OS << Id[I].first;
143   }
144 }
145 
146 void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
147   OS.indent(Indent);
148   if (IsFramework)
149     OS << "framework ";
150   if (IsExplicit)
151     OS << "explicit ";
152   OS << "module " << Name << " {\n";
153 
154   if (!Requires.empty()) {
155     OS.indent(Indent + 2);
156     OS << "requires ";
157     for (unsigned I = 0, N = Requires.size(); I != N; ++I) {
158       if (I)
159         OS << ", ";
160       OS << Requires[I];
161     }
162     OS << "\n";
163   }
164 
165   if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
166     OS.indent(Indent + 2);
167     OS << "umbrella header \"";
168     OS.write_escaped(UmbrellaHeader->getName());
169     OS << "\"\n";
170   } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) {
171     OS.indent(Indent + 2);
172     OS << "umbrella \"";
173     OS.write_escaped(UmbrellaDir->getName());
174     OS << "\"\n";
175   }
176 
177   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
178     OS.indent(Indent + 2);
179     OS << "header \"";
180     OS.write_escaped(Headers[I]->getName());
181     OS << "\"\n";
182   }
183 
184   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
185                                               MIEnd = SubModules.end();
186        MI != MIEnd; ++MI)
187     MI->getValue()->print(OS, Indent + 2);
188 
189   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
190     OS.indent(Indent + 2);
191     OS << "export ";
192     if (Module *Restriction = Exports[I].getPointer()) {
193       OS << Restriction->getFullModuleName();
194       if (Exports[I].getInt())
195         OS << ".*";
196     } else {
197       OS << "*";
198     }
199     OS << "\n";
200   }
201 
202   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
203     OS.indent(Indent + 2);
204     OS << "export ";
205     printModuleId(OS, UnresolvedExports[I].Id);
206     if (UnresolvedExports[I].Wildcard) {
207       if (UnresolvedExports[I].Id.empty())
208         OS << "*";
209       else
210         OS << ".*";
211     }
212     OS << "\n";
213   }
214 
215   if (InferSubmodules) {
216     OS.indent(Indent + 2);
217     if (InferExplicitSubmodules)
218       OS << "explicit ";
219     OS << "module * {\n";
220     if (InferExportWildcard) {
221       OS.indent(Indent + 4);
222       OS << "export *\n";
223     }
224     OS.indent(Indent + 2);
225     OS << "}\n";
226   }
227 
228   OS.indent(Indent);
229   OS << "}\n";
230 }
231 
232 void Module::dump() const {
233   print(llvm::errs());
234 }
235 
236 
237