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