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), InferSubmodules(false), 28 InferExplicitSubmodules(false), InferExportWildcard(false), 29 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 return false; 76 } 77 78 bool Module::isSubModuleOf(Module *Other) const { 79 const Module *This = this; 80 do { 81 if (This == Other) 82 return true; 83 84 This = This->Parent; 85 } while (This); 86 87 return false; 88 } 89 90 const Module *Module::getTopLevelModule() const { 91 const Module *Result = this; 92 while (Result->Parent) 93 Result = Result->Parent; 94 95 return Result; 96 } 97 98 std::string Module::getFullModuleName() const { 99 llvm::SmallVector<StringRef, 2> Names; 100 101 // Build up the set of module names (from innermost to outermost). 102 for (const Module *M = this; M; M = M->Parent) 103 Names.push_back(M->Name); 104 105 std::string Result; 106 for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 107 IEnd = Names.rend(); 108 I != IEnd; ++I) { 109 if (!Result.empty()) 110 Result += '.'; 111 112 Result += *I; 113 } 114 115 return Result; 116 } 117 118 const DirectoryEntry *Module::getUmbrellaDir() const { 119 if (const FileEntry *Header = getUmbrellaHeader()) 120 return Header->getDir(); 121 122 return Umbrella.dyn_cast<const DirectoryEntry *>(); 123 } 124 125 void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts) { 126 Requires.push_back(Feature); 127 128 // If this feature is currently available, we're done. 129 if (hasFeature(Feature, LangOpts)) 130 return; 131 132 if (!IsAvailable) 133 return; 134 135 llvm::SmallVector<Module *, 2> Stack; 136 Stack.push_back(this); 137 while (!Stack.empty()) { 138 Module *Current = Stack.back(); 139 Stack.pop_back(); 140 141 if (!Current->IsAvailable) 142 continue; 143 144 Current->IsAvailable = false; 145 for (submodule_iterator Sub = Current->submodule_begin(), 146 SubEnd = Current->submodule_end(); 147 Sub != SubEnd; ++Sub) { 148 if ((*Sub)->IsAvailable) 149 Stack.push_back(*Sub); 150 } 151 } 152 } 153 154 Module *Module::findSubmodule(StringRef Name) const { 155 llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name); 156 if (Pos == SubModuleIndex.end()) 157 return 0; 158 159 return SubModules[Pos->getValue()]; 160 } 161 162 static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) { 163 for (unsigned I = 0, N = Id.size(); I != N; ++I) { 164 if (I) 165 OS << "."; 166 OS << Id[I].first; 167 } 168 } 169 170 void Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 171 OS.indent(Indent); 172 if (IsFramework) 173 OS << "framework "; 174 if (IsExplicit) 175 OS << "explicit "; 176 OS << "module " << Name << " {\n"; 177 178 if (!Requires.empty()) { 179 OS.indent(Indent + 2); 180 OS << "requires "; 181 for (unsigned I = 0, N = Requires.size(); I != N; ++I) { 182 if (I) 183 OS << ", "; 184 OS << Requires[I]; 185 } 186 OS << "\n"; 187 } 188 189 if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { 190 OS.indent(Indent + 2); 191 OS << "umbrella header \""; 192 OS.write_escaped(UmbrellaHeader->getName()); 193 OS << "\"\n"; 194 } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { 195 OS.indent(Indent + 2); 196 OS << "umbrella \""; 197 OS.write_escaped(UmbrellaDir->getName()); 198 OS << "\"\n"; 199 } 200 201 for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 202 OS.indent(Indent + 2); 203 OS << "header \""; 204 OS.write_escaped(Headers[I]->getName()); 205 OS << "\"\n"; 206 } 207 208 for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); 209 MI != MIEnd; ++MI) 210 (*MI)->print(OS, Indent + 2); 211 212 for (unsigned I = 0, N = Exports.size(); I != N; ++I) { 213 OS.indent(Indent + 2); 214 OS << "export "; 215 if (Module *Restriction = Exports[I].getPointer()) { 216 OS << Restriction->getFullModuleName(); 217 if (Exports[I].getInt()) 218 OS << ".*"; 219 } else { 220 OS << "*"; 221 } 222 OS << "\n"; 223 } 224 225 for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { 226 OS.indent(Indent + 2); 227 OS << "export "; 228 printModuleId(OS, UnresolvedExports[I].Id); 229 if (UnresolvedExports[I].Wildcard) { 230 if (UnresolvedExports[I].Id.empty()) 231 OS << "*"; 232 else 233 OS << ".*"; 234 } 235 OS << "\n"; 236 } 237 238 if (InferSubmodules) { 239 OS.indent(Indent + 2); 240 if (InferExplicitSubmodules) 241 OS << "explicit "; 242 OS << "module * {\n"; 243 if (InferExportWildcard) { 244 OS.indent(Indent + 4); 245 OS << "export *\n"; 246 } 247 OS.indent(Indent + 2); 248 OS << "}\n"; 249 } 250 251 OS.indent(Indent); 252 OS << "}\n"; 253 } 254 255 void Module::dump() const { 256 print(llvm::errs()); 257 } 258 259 260