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