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" 16*1fb5c3a6SDouglas Gregor #include "clang/Basic/LangOptions.h" 17*1fb5c3a6SDouglas Gregor #include "llvm/Support/ErrorHandling.h" 18de3ef502SDouglas Gregor #include "llvm/Support/raw_ostream.h" 19*1fb5c3a6SDouglas Gregor #include "llvm/ADT/SmallVector.h" 20*1fb5c3a6SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 21de3ef502SDouglas Gregor using namespace clang; 22de3ef502SDouglas Gregor 23de3ef502SDouglas Gregor Module::~Module() { 24de3ef502SDouglas Gregor for (llvm::StringMap<Module *>::iterator I = SubModules.begin(), 25de3ef502SDouglas Gregor IEnd = SubModules.end(); 26de3ef502SDouglas Gregor I != IEnd; ++I) { 27de3ef502SDouglas Gregor delete I->getValue(); 28de3ef502SDouglas Gregor } 29de3ef502SDouglas Gregor 30de3ef502SDouglas Gregor } 31de3ef502SDouglas Gregor 32*1fb5c3a6SDouglas Gregor /// \brief Determine whether a translation unit built using the current 33*1fb5c3a6SDouglas Gregor /// language options has the given feature. 34*1fb5c3a6SDouglas Gregor static bool hasFeature(StringRef Feature, const LangOptions &LangOpts) { 35*1fb5c3a6SDouglas Gregor return llvm::StringSwitch<bool>(Feature) 36*1fb5c3a6SDouglas Gregor .Case("blocks", LangOpts.Blocks) 37*1fb5c3a6SDouglas Gregor .Case("cplusplus", LangOpts.CPlusPlus) 38*1fb5c3a6SDouglas Gregor .Case("cplusplus11", LangOpts.CPlusPlus0x) 39*1fb5c3a6SDouglas Gregor .Case("objc", LangOpts.ObjC1) 40*1fb5c3a6SDouglas Gregor .Case("objc_arc", LangOpts.ObjCAutoRefCount) 41*1fb5c3a6SDouglas Gregor .Default(false); 42*1fb5c3a6SDouglas Gregor } 43*1fb5c3a6SDouglas Gregor 44*1fb5c3a6SDouglas Gregor bool 45*1fb5c3a6SDouglas Gregor Module::isAvailable(const LangOptions &LangOpts, StringRef &Feature) const { 46*1fb5c3a6SDouglas Gregor if (IsAvailable) 47*1fb5c3a6SDouglas Gregor return true; 48*1fb5c3a6SDouglas Gregor 49*1fb5c3a6SDouglas Gregor for (const Module *Current = this; Current; Current = Current->Parent) { 50*1fb5c3a6SDouglas Gregor for (unsigned I = 0, N = Current->Requires.size(); I != N; ++I) { 51*1fb5c3a6SDouglas Gregor if (!hasFeature(Current->Requires[I], LangOpts)) { 52*1fb5c3a6SDouglas Gregor Feature = Current->Requires[I]; 53*1fb5c3a6SDouglas Gregor return false; 54*1fb5c3a6SDouglas Gregor } 55*1fb5c3a6SDouglas Gregor } 56*1fb5c3a6SDouglas Gregor } 57*1fb5c3a6SDouglas Gregor 58*1fb5c3a6SDouglas Gregor llvm_unreachable("could not find a reason why module is unavailable"); 59*1fb5c3a6SDouglas Gregor return false; 60*1fb5c3a6SDouglas Gregor } 61*1fb5c3a6SDouglas Gregor 62f5eedd05SDouglas Gregor bool Module::isSubModuleOf(Module *Other) const { 63f5eedd05SDouglas Gregor const Module *This = this; 64f5eedd05SDouglas Gregor do { 65f5eedd05SDouglas Gregor if (This == Other) 66f5eedd05SDouglas Gregor return true; 67f5eedd05SDouglas Gregor 68f5eedd05SDouglas Gregor This = This->Parent; 69f5eedd05SDouglas Gregor } while (This); 70f5eedd05SDouglas Gregor 71f5eedd05SDouglas Gregor return false; 72f5eedd05SDouglas Gregor } 73f5eedd05SDouglas Gregor 7473441091SDouglas Gregor const Module *Module::getTopLevelModule() const { 7573441091SDouglas Gregor const Module *Result = this; 7673441091SDouglas Gregor while (Result->Parent) 7773441091SDouglas Gregor Result = Result->Parent; 7873441091SDouglas Gregor 7973441091SDouglas Gregor return Result; 8073441091SDouglas Gregor } 8173441091SDouglas Gregor 82de3ef502SDouglas Gregor std::string Module::getFullModuleName() const { 83de3ef502SDouglas Gregor llvm::SmallVector<StringRef, 2> Names; 84de3ef502SDouglas Gregor 85de3ef502SDouglas Gregor // Build up the set of module names (from innermost to outermost). 86de3ef502SDouglas Gregor for (const Module *M = this; M; M = M->Parent) 87de3ef502SDouglas Gregor Names.push_back(M->Name); 88de3ef502SDouglas Gregor 89de3ef502SDouglas Gregor std::string Result; 90de3ef502SDouglas Gregor for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 91de3ef502SDouglas Gregor IEnd = Names.rend(); 92de3ef502SDouglas Gregor I != IEnd; ++I) { 93de3ef502SDouglas Gregor if (!Result.empty()) 94de3ef502SDouglas Gregor Result += '.'; 95de3ef502SDouglas Gregor 96de3ef502SDouglas Gregor Result += *I; 97de3ef502SDouglas Gregor } 98de3ef502SDouglas Gregor 99de3ef502SDouglas Gregor return Result; 100de3ef502SDouglas Gregor } 101de3ef502SDouglas Gregor 10273141fa9SDouglas Gregor const DirectoryEntry *Module::getUmbrellaDir() const { 10373141fa9SDouglas Gregor if (const FileEntry *Header = getUmbrellaHeader()) 10473141fa9SDouglas Gregor return Header->getDir(); 10573141fa9SDouglas Gregor 10673141fa9SDouglas Gregor return Umbrella.dyn_cast<const DirectoryEntry *>(); 10773141fa9SDouglas Gregor } 10873141fa9SDouglas Gregor 109*1fb5c3a6SDouglas Gregor void Module::addRequirement(StringRef Feature, const LangOptions &LangOpts) { 110*1fb5c3a6SDouglas Gregor Requires.push_back(Feature); 111*1fb5c3a6SDouglas Gregor 112*1fb5c3a6SDouglas Gregor // If this feature is currently available, we're done. 113*1fb5c3a6SDouglas Gregor if (hasFeature(Feature, LangOpts)) 114*1fb5c3a6SDouglas Gregor return; 115*1fb5c3a6SDouglas Gregor 116*1fb5c3a6SDouglas Gregor if (!IsAvailable) 117*1fb5c3a6SDouglas Gregor return; 118*1fb5c3a6SDouglas Gregor 119*1fb5c3a6SDouglas Gregor llvm::SmallVector<Module *, 2> Stack; 120*1fb5c3a6SDouglas Gregor Stack.push_back(this); 121*1fb5c3a6SDouglas Gregor while (!Stack.empty()) { 122*1fb5c3a6SDouglas Gregor Module *Current = Stack.back(); 123*1fb5c3a6SDouglas Gregor Stack.pop_back(); 124*1fb5c3a6SDouglas Gregor 125*1fb5c3a6SDouglas Gregor if (!Current->IsAvailable) 126*1fb5c3a6SDouglas Gregor continue; 127*1fb5c3a6SDouglas Gregor 128*1fb5c3a6SDouglas Gregor Current->IsAvailable = false; 129*1fb5c3a6SDouglas Gregor for (llvm::StringMap<Module *>::iterator Sub = Current->SubModules.begin(), 130*1fb5c3a6SDouglas Gregor SubEnd = Current->SubModules.end(); 131*1fb5c3a6SDouglas Gregor Sub != SubEnd; ++Sub) { 132*1fb5c3a6SDouglas Gregor if (Sub->second->IsAvailable) 133*1fb5c3a6SDouglas Gregor Stack.push_back(Sub->second); 134*1fb5c3a6SDouglas Gregor } 135*1fb5c3a6SDouglas Gregor } 136*1fb5c3a6SDouglas Gregor } 137*1fb5c3a6SDouglas Gregor 13824bb923aSDouglas Gregor static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) { 13924bb923aSDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 14024bb923aSDouglas Gregor if (I) 14124bb923aSDouglas Gregor OS << "."; 14224bb923aSDouglas Gregor OS << Id[I].first; 14324bb923aSDouglas Gregor } 14424bb923aSDouglas Gregor } 14524bb923aSDouglas Gregor 146de3ef502SDouglas Gregor void Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 147de3ef502SDouglas Gregor OS.indent(Indent); 148de3ef502SDouglas Gregor if (IsFramework) 149de3ef502SDouglas Gregor OS << "framework "; 150de3ef502SDouglas Gregor if (IsExplicit) 151de3ef502SDouglas Gregor OS << "explicit "; 152de3ef502SDouglas Gregor OS << "module " << Name << " {\n"; 153de3ef502SDouglas Gregor 154*1fb5c3a6SDouglas Gregor if (!Requires.empty()) { 155*1fb5c3a6SDouglas Gregor OS.indent(Indent + 2); 156*1fb5c3a6SDouglas Gregor OS << "requires "; 157*1fb5c3a6SDouglas Gregor for (unsigned I = 0, N = Requires.size(); I != N; ++I) { 158*1fb5c3a6SDouglas Gregor if (I) 159*1fb5c3a6SDouglas Gregor OS << ", "; 160*1fb5c3a6SDouglas Gregor OS << Requires[I]; 161*1fb5c3a6SDouglas Gregor } 162*1fb5c3a6SDouglas Gregor OS << "\n"; 163*1fb5c3a6SDouglas Gregor } 164*1fb5c3a6SDouglas Gregor 16573141fa9SDouglas Gregor if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) { 166de3ef502SDouglas Gregor OS.indent(Indent + 2); 167322f633cSDouglas Gregor OS << "umbrella header \""; 168de3ef502SDouglas Gregor OS.write_escaped(UmbrellaHeader->getName()); 169de3ef502SDouglas Gregor OS << "\"\n"; 170322f633cSDouglas Gregor } else if (const DirectoryEntry *UmbrellaDir = getUmbrellaDir()) { 171322f633cSDouglas Gregor OS.indent(Indent + 2); 172322f633cSDouglas Gregor OS << "umbrella \""; 173322f633cSDouglas Gregor OS.write_escaped(UmbrellaDir->getName()); 174322f633cSDouglas Gregor OS << "\"\n"; 175de3ef502SDouglas Gregor } 176de3ef502SDouglas Gregor 177de3ef502SDouglas Gregor for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 178de3ef502SDouglas Gregor OS.indent(Indent + 2); 179de3ef502SDouglas Gregor OS << "header \""; 180de3ef502SDouglas Gregor OS.write_escaped(Headers[I]->getName()); 181de3ef502SDouglas Gregor OS << "\"\n"; 182de3ef502SDouglas Gregor } 183de3ef502SDouglas Gregor 184de3ef502SDouglas Gregor for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(), 185de3ef502SDouglas Gregor MIEnd = SubModules.end(); 186de3ef502SDouglas Gregor MI != MIEnd; ++MI) 187de3ef502SDouglas Gregor MI->getValue()->print(OS, Indent + 2); 188de3ef502SDouglas Gregor 18924bb923aSDouglas Gregor for (unsigned I = 0, N = Exports.size(); I != N; ++I) { 19024bb923aSDouglas Gregor OS.indent(Indent + 2); 1918c7c8352SDouglas Gregor OS << "export "; 1928c7c8352SDouglas Gregor if (Module *Restriction = Exports[I].getPointer()) { 1938c7c8352SDouglas Gregor OS << Restriction->getFullModuleName(); 19424bb923aSDouglas Gregor if (Exports[I].getInt()) 19524bb923aSDouglas Gregor OS << ".*"; 1968c7c8352SDouglas Gregor } else { 1978c7c8352SDouglas Gregor OS << "*"; 1988c7c8352SDouglas Gregor } 19924bb923aSDouglas Gregor OS << "\n"; 20024bb923aSDouglas Gregor } 20124bb923aSDouglas Gregor 20224bb923aSDouglas Gregor for (unsigned I = 0, N = UnresolvedExports.size(); I != N; ++I) { 20324bb923aSDouglas Gregor OS.indent(Indent + 2); 20424bb923aSDouglas Gregor OS << "export "; 20524bb923aSDouglas Gregor printModuleId(OS, UnresolvedExports[I].Id); 2068c7c8352SDouglas Gregor if (UnresolvedExports[I].Wildcard) { 2078c7c8352SDouglas Gregor if (UnresolvedExports[I].Id.empty()) 2088c7c8352SDouglas Gregor OS << "*"; 2098c7c8352SDouglas Gregor else 21024bb923aSDouglas Gregor OS << ".*"; 2118c7c8352SDouglas Gregor } 21224bb923aSDouglas Gregor OS << "\n"; 21324bb923aSDouglas Gregor } 21424bb923aSDouglas Gregor 21573441091SDouglas Gregor if (InferSubmodules) { 21673441091SDouglas Gregor OS.indent(Indent + 2); 21773441091SDouglas Gregor if (InferExplicitSubmodules) 21873441091SDouglas Gregor OS << "explicit "; 21973441091SDouglas Gregor OS << "module * {\n"; 22073441091SDouglas Gregor if (InferExportWildcard) { 22173441091SDouglas Gregor OS.indent(Indent + 4); 22273441091SDouglas Gregor OS << "export *\n"; 22373441091SDouglas Gregor } 22473441091SDouglas Gregor OS.indent(Indent + 2); 22573441091SDouglas Gregor OS << "}\n"; 22673441091SDouglas Gregor } 22773441091SDouglas Gregor 228de3ef502SDouglas Gregor OS.indent(Indent); 229de3ef502SDouglas Gregor OS << "}\n"; 230de3ef502SDouglas Gregor } 231de3ef502SDouglas Gregor 232de3ef502SDouglas Gregor void Module::dump() const { 233de3ef502SDouglas Gregor print(llvm::errs()); 234de3ef502SDouglas Gregor } 235de3ef502SDouglas Gregor 236de3ef502SDouglas Gregor 237