1de3ef502SDouglas Gregor //===--- Module.h - Describe a module ---------------------------*- C++ -*-===// 2de3ef502SDouglas Gregor // 3de3ef502SDouglas Gregor // The LLVM Compiler Infrastructure 4de3ef502SDouglas Gregor // 5de3ef502SDouglas Gregor // This file is distributed under the University of Illinois Open Source 6de3ef502SDouglas Gregor // License. See LICENSE.TXT for details. 7de3ef502SDouglas Gregor // 8de3ef502SDouglas Gregor //===----------------------------------------------------------------------===// 9de3ef502SDouglas Gregor // 10de3ef502SDouglas Gregor // This file defines the Module class, which describes a module in the source 11de3ef502SDouglas Gregor // code. 12de3ef502SDouglas Gregor // 13de3ef502SDouglas Gregor //===----------------------------------------------------------------------===// 14de3ef502SDouglas Gregor #include "clang/Basic/Module.h" 15de3ef502SDouglas Gregor #include "clang/Basic/FileManager.h" 161fb5c3a6SDouglas Gregor #include "clang/Basic/LangOptions.h" 171fb5c3a6SDouglas Gregor #include "llvm/Support/ErrorHandling.h" 18de3ef502SDouglas Gregor #include "llvm/Support/raw_ostream.h" 191fb5c3a6SDouglas Gregor #include "llvm/ADT/SmallVector.h" 201fb5c3a6SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 21de3ef502SDouglas Gregor using namespace clang; 22de3ef502SDouglas Gregor 23eb90e830SDouglas Gregor Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, 24eb90e830SDouglas Gregor bool IsFramework, bool IsExplicit) 25eb90e830SDouglas Gregor : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), 26eb90e830SDouglas Gregor Umbrella(), IsAvailable(true), IsFromModuleFile(false), 27*a686e1b0SDouglas Gregor IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), 28*a686e1b0SDouglas Gregor InferSubmodules(false), InferExplicitSubmodules(false), 29*a686e1b0SDouglas Gregor InferExportWildcard(false), NameVisibility(Hidden) 30eb90e830SDouglas Gregor { 31eb90e830SDouglas Gregor if (Parent) { 32eb90e830SDouglas Gregor if (!Parent->isAvailable()) 33eb90e830SDouglas Gregor IsAvailable = false; 34eb90e830SDouglas Gregor 35eb90e830SDouglas Gregor Parent->SubModuleIndex[Name] = Parent->SubModules.size(); 36eb90e830SDouglas Gregor Parent->SubModules.push_back(this); 37eb90e830SDouglas Gregor } 38eb90e830SDouglas Gregor } 39eb90e830SDouglas Gregor 40de3ef502SDouglas Gregor Module::~Module() { 41eb90e830SDouglas Gregor for (submodule_iterator I = submodule_begin(), IEnd = submodule_end(); 42de3ef502SDouglas Gregor I != IEnd; ++I) { 43eb90e830SDouglas Gregor delete *I; 44de3ef502SDouglas Gregor } 45de3ef502SDouglas Gregor 46de3ef502SDouglas Gregor } 47de3ef502SDouglas Gregor 481fb5c3a6SDouglas Gregor /// \brief Determine whether a translation unit built using the current 491fb5c3a6SDouglas Gregor /// language options has the given feature. 501fb5c3a6SDouglas Gregor static bool hasFeature(StringRef Feature, const LangOptions &LangOpts) { 511fb5c3a6SDouglas Gregor return llvm::StringSwitch<bool>(Feature) 521fb5c3a6SDouglas Gregor .Case("blocks", LangOpts.Blocks) 531fb5c3a6SDouglas Gregor .Case("cplusplus", LangOpts.CPlusPlus) 541fb5c3a6SDouglas Gregor .Case("cplusplus11", LangOpts.CPlusPlus0x) 551fb5c3a6SDouglas Gregor .Case("objc", LangOpts.ObjC1) 561fb5c3a6SDouglas Gregor .Case("objc_arc", LangOpts.ObjCAutoRefCount) 571fb5c3a6SDouglas Gregor .Default(false); 581fb5c3a6SDouglas Gregor } 591fb5c3a6SDouglas Gregor 601fb5c3a6SDouglas Gregor bool 611fb5c3a6SDouglas Gregor Module::isAvailable(const LangOptions &LangOpts, StringRef &Feature) const { 621fb5c3a6SDouglas Gregor if (IsAvailable) 631fb5c3a6SDouglas Gregor return true; 641fb5c3a6SDouglas Gregor 651fb5c3a6SDouglas Gregor for (const Module *Current = this; Current; Current = Current->Parent) { 661fb5c3a6SDouglas Gregor for (unsigned I = 0, N = Current->Requires.size(); I != N; ++I) { 671fb5c3a6SDouglas Gregor if (!hasFeature(Current->Requires[I], LangOpts)) { 681fb5c3a6SDouglas Gregor Feature = Current->Requires[I]; 691fb5c3a6SDouglas Gregor return false; 701fb5c3a6SDouglas Gregor } 711fb5c3a6SDouglas Gregor } 721fb5c3a6SDouglas Gregor } 731fb5c3a6SDouglas Gregor 741fb5c3a6SDouglas Gregor llvm_unreachable("could not find a reason why module is unavailable"); 751fb5c3a6SDouglas Gregor } 761fb5c3a6SDouglas Gregor 77f5eedd05SDouglas Gregor bool Module::isSubModuleOf(Module *Other) const { 78f5eedd05SDouglas Gregor const Module *This = this; 79f5eedd05SDouglas Gregor do { 80f5eedd05SDouglas Gregor if (This == Other) 81f5eedd05SDouglas Gregor return true; 82f5eedd05SDouglas Gregor 83f5eedd05SDouglas Gregor This = This->Parent; 84f5eedd05SDouglas Gregor } while (This); 85f5eedd05SDouglas Gregor 86f5eedd05SDouglas Gregor return false; 87f5eedd05SDouglas Gregor } 88f5eedd05SDouglas Gregor 8973441091SDouglas Gregor const Module *Module::getTopLevelModule() const { 9073441091SDouglas Gregor const Module *Result = this; 9173441091SDouglas Gregor while (Result->Parent) 9273441091SDouglas Gregor Result = Result->Parent; 9373441091SDouglas Gregor 9473441091SDouglas Gregor return Result; 9573441091SDouglas Gregor } 9673441091SDouglas Gregor 97de3ef502SDouglas Gregor std::string Module::getFullModuleName() const { 98de3ef502SDouglas Gregor llvm::SmallVector<StringRef, 2> Names; 99de3ef502SDouglas Gregor 100de3ef502SDouglas Gregor // Build up the set of module names (from innermost to outermost). 101de3ef502SDouglas Gregor for (const Module *M = this; M; M = M->Parent) 102de3ef502SDouglas Gregor Names.push_back(M->Name); 103de3ef502SDouglas Gregor 104de3ef502SDouglas Gregor std::string Result; 105de3ef502SDouglas Gregor for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 106de3ef502SDouglas Gregor IEnd = Names.rend(); 107de3ef502SDouglas Gregor I != IEnd; ++I) { 108de3ef502SDouglas Gregor if (!Result.empty()) 109de3ef502SDouglas Gregor Result += '.'; 110de3ef502SDouglas Gregor 111de3ef502SDouglas Gregor Result += *I; 112de3ef502SDouglas Gregor } 113de3ef502SDouglas Gregor 114de3ef502SDouglas Gregor return Result; 115de3ef502SDouglas Gregor } 116de3ef502SDouglas Gregor 11773141fa9SDouglas Gregor const DirectoryEntry *Module::getUmbrellaDir() const { 11873141fa9SDouglas Gregor if (const FileEntry *Header = getUmbrellaHeader()) 11973141fa9SDouglas Gregor return Header->getDir(); 12073141fa9SDouglas Gregor 12173141fa9SDouglas Gregor return Umbrella.dyn_cast<const DirectoryEntry *>(); 12273141fa9SDouglas Gregor } 12373141fa9SDouglas Gregor 1241fb5c3a6SDouglas Gregor void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts) { 1251fb5c3a6SDouglas Gregor Requires.push_back(Feature); 1261fb5c3a6SDouglas Gregor 1271fb5c3a6SDouglas Gregor // If this feature is currently available, we're done. 1281fb5c3a6SDouglas Gregor if (hasFeature(Feature, LangOpts)) 1291fb5c3a6SDouglas Gregor return; 1301fb5c3a6SDouglas Gregor 1311fb5c3a6SDouglas Gregor if (!IsAvailable) 1321fb5c3a6SDouglas Gregor return; 1331fb5c3a6SDouglas Gregor 1341fb5c3a6SDouglas Gregor llvm::SmallVector<Module *, 2> Stack; 1351fb5c3a6SDouglas Gregor Stack.push_back(this); 1361fb5c3a6SDouglas Gregor while (!Stack.empty()) { 1371fb5c3a6SDouglas Gregor Module *Current = Stack.back(); 1381fb5c3a6SDouglas Gregor Stack.pop_back(); 1391fb5c3a6SDouglas Gregor 1401fb5c3a6SDouglas Gregor if (!Current->IsAvailable) 1411fb5c3a6SDouglas Gregor continue; 1421fb5c3a6SDouglas Gregor 1431fb5c3a6SDouglas Gregor Current->IsAvailable = false; 144eb90e830SDouglas Gregor for (submodule_iterator Sub = Current->submodule_begin(), 145eb90e830SDouglas Gregor SubEnd = Current->submodule_end(); 1461fb5c3a6SDouglas Gregor Sub != SubEnd; ++Sub) { 147eb90e830SDouglas Gregor if ((*Sub)->IsAvailable) 148eb90e830SDouglas Gregor Stack.push_back(*Sub); 1491fb5c3a6SDouglas Gregor } 1501fb5c3a6SDouglas Gregor } 1511fb5c3a6SDouglas Gregor } 1521fb5c3a6SDouglas Gregor 153eb90e830SDouglas Gregor Module *Module::findSubmodule(StringRef Name) const { 154eb90e830SDouglas Gregor llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name); 155eb90e830SDouglas Gregor if (Pos == SubModuleIndex.end()) 156eb90e830SDouglas Gregor return 0; 157eb90e830SDouglas Gregor 158eb90e830SDouglas Gregor return SubModules[Pos->getValue()]; 159eb90e830SDouglas Gregor } 160eb90e830SDouglas Gregor 16124bb923aSDouglas Gregor static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) { 16224bb923aSDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 16324bb923aSDouglas Gregor if (I) 16424bb923aSDouglas Gregor OS << "."; 16524bb923aSDouglas Gregor OS << Id[I].first; 16624bb923aSDouglas Gregor } 16724bb923aSDouglas Gregor } 16824bb923aSDouglas Gregor 169de3ef502SDouglas Gregor void Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 170de3ef502SDouglas Gregor OS.indent(Indent); 171de3ef502SDouglas Gregor if (IsFramework) 172de3ef502SDouglas Gregor OS << "framework "; 173de3ef502SDouglas Gregor if (IsExplicit) 174de3ef502SDouglas Gregor OS << "explicit "; 175*a686e1b0SDouglas Gregor OS << "module " << Name; 176*a686e1b0SDouglas Gregor 177*a686e1b0SDouglas Gregor if (IsSystem) { 178*a686e1b0SDouglas Gregor OS.indent(Indent + 2); 179*a686e1b0SDouglas Gregor OS << " [system]"; 180*a686e1b0SDouglas Gregor } 181*a686e1b0SDouglas Gregor 182*a686e1b0SDouglas Gregor OS << " {\n"; 183de3ef502SDouglas Gregor 1841fb5c3a6SDouglas Gregor if (!Requires.empty()) { 1851fb5c3a6SDouglas Gregor OS.indent(Indent + 2); 1861fb5c3a6SDouglas Gregor OS << "requires "; 1871fb5c3a6SDouglas Gregor for (unsigned I = 0, N = Requires.size(); I != N; ++I) { 1881fb5c3a6SDouglas Gregor if (I) 1891fb5c3a6SDouglas Gregor OS << ", "; 1901fb5c3a6SDouglas Gregor OS << Requires[I]; 1911fb5c3a6SDouglas Gregor } 1921fb5c3a6SDouglas Gregor OS << "\n"; 1931fb5c3a6SDouglas Gregor } 1941fb5c3a6SDouglas Gregor 19573141fa9SDouglas Gregor if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { 196de3ef502SDouglas Gregor OS.indent(Indent + 2); 197322f633cSDouglas Gregor OS << "umbrella header \""; 198de3ef502SDouglas Gregor OS.write_escaped(UmbrellaHeader->getName()); 199de3ef502SDouglas Gregor OS << "\"\n"; 200322f633cSDouglas Gregor } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { 201322f633cSDouglas Gregor OS.indent(Indent + 2); 202322f633cSDouglas Gregor OS << "umbrella \""; 203322f633cSDouglas Gregor OS.write_escaped(UmbrellaDir->getName()); 204322f633cSDouglas Gregor OS << "\"\n"; 205de3ef502SDouglas Gregor } 206de3ef502SDouglas Gregor 207de3ef502SDouglas Gregor for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 208de3ef502SDouglas Gregor OS.indent(Indent + 2); 209de3ef502SDouglas Gregor OS << "header \""; 210de3ef502SDouglas Gregor OS.write_escaped(Headers[I]->getName()); 211de3ef502SDouglas Gregor OS << "\"\n"; 212de3ef502SDouglas Gregor } 213de3ef502SDouglas Gregor 214eb90e830SDouglas Gregor for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end(); 215de3ef502SDouglas Gregor MI != MIEnd; ++MI) 216eb90e830SDouglas Gregor (*MI)->print(OS, Indent + 2); 217de3ef502SDouglas Gregor 21824bb923aSDouglas Gregor for (unsigned I = 0, N = Exports.size(); I != N; ++I) { 21924bb923aSDouglas Gregor OS.indent(Indent + 2); 2208c7c8352SDouglas Gregor OS << "export "; 2218c7c8352SDouglas Gregor if (Module *Restriction = Exports[I].getPointer()) { 2228c7c8352SDouglas Gregor OS << Restriction->getFullModuleName(); 22324bb923aSDouglas Gregor if (Exports[I].getInt()) 22424bb923aSDouglas Gregor OS << ".*"; 2258c7c8352SDouglas Gregor } else { 2268c7c8352SDouglas Gregor OS << "*"; 2278c7c8352SDouglas Gregor } 22824bb923aSDouglas Gregor OS << "\n"; 22924bb923aSDouglas Gregor } 23024bb923aSDouglas Gregor 23124bb923aSDouglas Gregor for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { 23224bb923aSDouglas Gregor OS.indent(Indent + 2); 23324bb923aSDouglas Gregor OS << "export "; 23424bb923aSDouglas Gregor printModuleId(OS, UnresolvedExports[I].Id); 2358c7c8352SDouglas Gregor if (UnresolvedExports[I].Wildcard) { 2368c7c8352SDouglas Gregor if (UnresolvedExports[I].Id.empty()) 2378c7c8352SDouglas Gregor OS << "*"; 2388c7c8352SDouglas Gregor else 23924bb923aSDouglas Gregor OS << ".*"; 2408c7c8352SDouglas Gregor } 24124bb923aSDouglas Gregor OS << "\n"; 24224bb923aSDouglas Gregor } 24324bb923aSDouglas Gregor 24473441091SDouglas Gregor if (InferSubmodules) { 24573441091SDouglas Gregor OS.indent(Indent + 2); 24673441091SDouglas Gregor if (InferExplicitSubmodules) 24773441091SDouglas Gregor OS << "explicit "; 24873441091SDouglas Gregor OS << "module * {\n"; 24973441091SDouglas Gregor if (InferExportWildcard) { 25073441091SDouglas Gregor OS.indent(Indent + 4); 25173441091SDouglas Gregor OS << "export *\n"; 25273441091SDouglas Gregor } 25373441091SDouglas Gregor OS.indent(Indent + 2); 25473441091SDouglas Gregor OS << "}\n"; 25573441091SDouglas Gregor } 25673441091SDouglas Gregor 257de3ef502SDouglas Gregor OS.indent(Indent); 258de3ef502SDouglas Gregor OS << "}\n"; 259de3ef502SDouglas Gregor } 260de3ef502SDouglas Gregor 261de3ef502SDouglas Gregor void Module::dump() const { 262de3ef502SDouglas Gregor print(llvm::errs()); 263de3ef502SDouglas Gregor } 264de3ef502SDouglas Gregor 265de3ef502SDouglas Gregor 266