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