std::string Context::getThunkTarget(llvm::StringRef MangledName) { if (!isThunkSymbol(MangledName)) return std::string(); if (isMangledName(MangledName)) { // The targets of those thunks not derivable from the mangling. if (MangledName.endswith("TR") || MangledName.endswith("Tr") || MangledName.endswith("TW") ) return std::string(); if (MangledName.endswith("fC")) { std::string target = MangledName.str(); target[target.size() - 1] = 'c'; return target; } return MangledName.substr(0, MangledName.size() - 2).str(); } // Old mangling. assert(MangledName.startswith("_T")); StringRef Remaining = MangledName.substr(2); if (Remaining.startswith("PA_")) return Remaining.substr(3).str(); if (Remaining.startswith("PAo_")) return Remaining.substr(4).str(); assert(Remaining.startswith("To") || Remaining.startswith("TO")); return std::string("_T") + Remaining.substr(2).str(); }
bool MocPPCallbacks::FileNotFound(llvm::StringRef FileName, llvm::SmallVectorImpl< char >& RecoveryPath) { if (FileName.endswith(".moc") || FileName.endswith("_moc.cpp") || FileName.startswith("moc_")) { if (!PP.GetSuppressIncludeNotFoundError()) { PP.SetSuppressIncludeNotFoundError(true); IncludeNotFoundSupressed = true; } } else { if (IncludeNotFoundSupressed) { PP.SetSuppressIncludeNotFoundError(false); IncludeNotFoundSupressed = false; } else { ShouldWarnHeaderNotFound = true; } } return false; }
bool Context::isThunkSymbol(llvm::StringRef MangledName) { if (isMangledName(MangledName)) { // First do a quick check if (MangledName.endswith("TA") || // partial application forwarder MangledName.endswith("Ta") || // ObjC partial application forwarder MangledName.endswith("To") || // swift-as-ObjC thunk MangledName.endswith("TO") || // ObjC-as-swift thunk MangledName.endswith("TR") || // reabstraction thunk helper function MangledName.endswith("Tr") || // reabstraction thunk MangledName.endswith("TW") || // protocol witness thunk MangledName.endswith("fC")) { // allocating constructor // To avoid false positives, we need to fully demangle the symbol. NodePointer Nd = D->demangleSymbol(MangledName); if (!Nd || Nd->getKind() != Node::Kind::Global || Nd->getNumChildren() == 0) return false; switch (Nd->getFirstChild()->getKind()) { case Node::Kind::ObjCAttribute: case Node::Kind::NonObjCAttribute: case Node::Kind::PartialApplyObjCForwarder: case Node::Kind::PartialApplyForwarder: case Node::Kind::ReabstractionThunkHelper: case Node::Kind::ReabstractionThunk: case Node::Kind::ProtocolWitness: case Node::Kind::Allocator: return true; default: break; } } return false; } if (MangledName.startswith("_T")) { // Old mangling. StringRef Remaining = MangledName.substr(2); if (Remaining.startswith("To") || // swift-as-ObjC thunk Remaining.startswith("TO") || // ObjC-as-swift thunk Remaining.startswith("PA_") || // partial application forwarder Remaining.startswith("PAo_")) { // ObjC partial application forwarder return true; } } return false; }
void MocPPCallbacks::EnterMainFile(llvm::StringRef Name) { if (Name.endswith("global/qnamespace.h")) { // qnamsepace.h is a bit special because it contains all the Qt namespace enums // but all the Q_ENUMS are within a Q_MOC_RUN scope, which also do all sort of things. clang::MacroInfo *MI = PP.AllocateMacroInfo({}); MI->setIsBuiltinMacro(); #if CLANG_VERSION_MAJOR != 3 || CLANG_VERSION_MINOR > 2 PP.appendDefMacroDirective(PP.getIdentifierInfo("Q_MOC_RUN"), MI); #else PP.setMacroInfo(PP.getIdentifierInfo("Q_MOC_RUN"), MI); #endif InjectQObjectDefs({}); } }
bool SplitPaths(llvm::StringRef PathStr, llvm::SmallVectorImpl<llvm::StringRef>& Paths, SplitMode Mode, llvm::StringRef Delim, bool Verbose) { assert(Delim.size() && "Splitting without a delimiter"); #if defined(LLVM_ON_WIN32) // Support using a ':' delimiter on Windows. const bool WindowsColon = Delim.equals(":"); #endif bool AllExisted = true; for (std::pair<llvm::StringRef, llvm::StringRef> Split = PathStr.split(Delim); !Split.second.empty(); Split = PathStr.split(Delim)) { if (!Split.first.empty()) { bool Exists = llvm::sys::fs::is_directory(Split.first); #if defined(LLVM_ON_WIN32) // Because drive letters will have a colon we have to make sure the split // occurs at a colon not followed by a path separator. if (!Exists && WindowsColon && Split.first.size()==1) { // Both clang and cl.exe support '\' and '/' path separators. if (Split.second.front() == '\\' || Split.second.front() == '/') { const std::pair<llvm::StringRef, llvm::StringRef> Tmp = Split.second.split(Delim); // Split.first = 'C', but we want 'C:', so Tmp.first.size()+2 Split.first = llvm::StringRef(Split.first.data(), Tmp.first.size() + 2); Split.second = Tmp.second; Exists = llvm::sys::fs::is_directory(Split.first); } } #endif AllExisted = AllExisted && Exists; if (!Exists) { if (Mode == kFailNonExistant) { if (Verbose) { // Exiting early, but still log all non-existant paths that we have LogNonExistantDirectory(Split.first); while (!Split.second.empty()) { Split = PathStr.split(Delim); if (llvm::sys::fs::is_directory(Split.first)) { llvm::errs() << " ignoring directory that exists \"" << Split.first << "\"\n"; } else LogNonExistantDirectory(Split.first); Split = Split.second.split(Delim); } if (!llvm::sys::fs::is_directory(Split.first)) LogNonExistantDirectory(Split.first); } return false; } else if (Mode == kAllowNonExistant) Paths.push_back(Split.first); else if (Verbose) LogNonExistantDirectory(Split.first); } else Paths.push_back(Split.first); } PathStr = Split.second; } // Trim trailing sep in case of A:B:C:D: if (!PathStr.empty() && PathStr.endswith(Delim)) PathStr = PathStr.substr(0, PathStr.size()-Delim.size()); if (!PathStr.empty()) { if (!llvm::sys::fs::is_directory(PathStr)) { AllExisted = false; if (Mode == kAllowNonExistant) Paths.push_back(PathStr); else if (Verbose) LogNonExistantDirectory(PathStr); } else Paths.push_back(PathStr); } return AllExisted; }
/// ApplyQAOverride - Apply a list of edits to the input argument lists. /// /// The input string is a space separate list of edits to perform, /// they are applied in order to the input argument lists. Edits /// should be one of the following forms: /// /// '#': Silence information about the changes to the command line arguments. /// /// '^': Add FOO as a new argument at the beginning of the command line. /// /// '+': Add FOO as a new argument at the end of the command line. /// /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command /// line. /// /// 'xOPTION': Removes all instances of the literal argument OPTION. /// /// 'XOPTION': Removes all instances of the literal argument OPTION, /// and the following argument. /// /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' /// at the end of the command line. /// /// \param OS - The stream to write edit information to. /// \param Args - The vector of command line arguments. /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. static void ApplyOneQAOverride(llvm::raw_ostream &OS, llvm::SmallVectorImpl<const char*> &Args, llvm::StringRef Edit, std::set<std::string> &SavedStrings) { // This does not need to be efficient. if (Edit[0] == '^') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at beginning\n"; Args.insert(Args.begin() + 1, Str); } else if (Edit[0] == '+') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at end\n"; Args.push_back(Str); } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) { llvm::StringRef MatchPattern = Edit.substr(2).split('/').first; llvm::StringRef ReplPattern = Edit.substr(2).split('/').second; ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); if (Repl != Args[i]) { OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; Args[i] = SaveStringInSet(SavedStrings, Repl); } } } else if (Edit[0] == 'x' || Edit[0] == 'X') { std::string Option = Edit.substr(1, std::string::npos); for (unsigned i = 1; i < Args.size();) { if (Option == Args[i]) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); if (Edit[0] == 'X') { if (i < Args.size()) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else OS << "### Invalid X edit, end of command line!\n"; } } else ++i; } } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { const char *A = Args[i]; if (A[0] == '-' && A[1] == 'O' && (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || ('0' <= A[2] && A[2] <= '9'))))) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else ++i; } OS << "### Adding argument " << Edit << " at end\n"; Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); } else { OS << "### Unrecognized edit: " << Edit << "\n"; } }