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