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