xref: /llvm-project/clang/lib/Basic/Module.cpp (revision 8c7c83522bd43949f369bb0dbf28b81f9c81f68c)
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 std::string Module::getFullModuleName() const {
41   llvm::SmallVector<StringRef, 2> Names;
42 
43   // Build up the set of module names (from innermost to outermost).
44   for (const Module *M = this; M; M = M->Parent)
45     Names.push_back(M->Name);
46 
47   std::string Result;
48   for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(),
49                                                       IEnd = Names.rend();
50        I != IEnd; ++I) {
51     if (!Result.empty())
52       Result += '.';
53 
54     Result += *I;
55   }
56 
57   return Result;
58 }
59 
60 StringRef Module::getTopLevelModuleName() const {
61   const Module *Top = this;
62   while (Top->Parent)
63     Top = Top->Parent;
64 
65   return Top->Name;
66 }
67 
68 static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
69   for (unsigned I = 0, N = Id.size(); I != N; ++I) {
70     if (I)
71       OS << ".";
72     OS << Id[I].first;
73   }
74 }
75 
76 void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
77   OS.indent(Indent);
78   if (IsFramework)
79     OS << "framework ";
80   if (IsExplicit)
81     OS << "explicit ";
82   OS << "module " << Name << " {\n";
83 
84   if (UmbrellaHeader) {
85     OS.indent(Indent + 2);
86     OS << "umbrella \"";
87     OS.write_escaped(UmbrellaHeader->getName());
88     OS << "\"\n";
89   }
90 
91   for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
92     OS.indent(Indent + 2);
93     OS << "header \"";
94     OS.write_escaped(Headers[I]->getName());
95     OS << "\"\n";
96   }
97 
98   for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(),
99        MIEnd = SubModules.end();
100        MI != MIEnd; ++MI)
101     MI->getValue()->print(OS, Indent + 2);
102 
103   for (unsigned I = 0, N = Exports.size(); I != N; ++I) {
104     OS.indent(Indent + 2);
105     OS << "export ";
106     if (Module *Restriction = Exports[I].getPointer()) {
107       OS << Restriction->getFullModuleName();
108       if (Exports[I].getInt())
109         OS << ".*";
110     } else {
111       OS << "*";
112     }
113     OS << "\n";
114   }
115 
116   for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) {
117     OS.indent(Indent + 2);
118     OS << "export ";
119     printModuleId(OS, UnresolvedExports[I].Id);
120     if (UnresolvedExports[I].Wildcard) {
121       if (UnresolvedExports[I].Id.empty())
122         OS << "*";
123       else
124         OS << ".*";
125     }
126     OS << "\n";
127   }
128 
129   OS.indent(Indent);
130   OS << "}\n";
131 }
132 
133 void Module::dump() const {
134   print(llvm::errs());
135 }
136 
137 
138