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(); }
static inline void StripSpaces(llvm::StringRef &Str) { while (!Str.empty() && isspace(Str[0])) Str = Str.substr(1); while (!Str.empty() && isspace(Str.back())) Str = Str.substr(0, Str.size()-1); }
PythonObject PythonObject::ResolveName(llvm::StringRef name) const { // Resolve the name in the context of the specified object. If, for example, // `this` refers to a PyModule, then this will look for `name` in this // module. If `this` refers to a PyType, then it will resolve `name` as an // attribute of that type. If `this` refers to an instance of an object, // then it will resolve `name` as the value of the specified field. // // This function handles dotted names so that, for example, if `m_py_obj` // refers to the `sys` module, and `name` == "path.append", then it will find // the function `sys.path.append`. size_t dot_pos = name.find('.'); if (dot_pos == llvm::StringRef::npos) { // No dots in the name, we should be able to find the value immediately as // an attribute of `m_py_obj`. return GetAttributeValue(name); } // Look up the first piece of the name, and resolve the rest as a child of // that. PythonObject parent = ResolveName(name.substr(0, dot_pos)); if (!parent.IsAllocated()) return PythonObject(); // Tail recursion.. should be optimized by the compiler return parent.ResolveName(name.substr(dot_pos + 1)); }
Symbol symbol(llvm::StringRef QName) { Symbol Sym; Sym.ID = SymbolID(QName.str()); size_t Pos = QName.rfind("::"); if (Pos == llvm::StringRef::npos) { Sym.Name = QName; Sym.Scope = ""; } else { Sym.Name = QName.substr(Pos + 2); Sym.Scope = QName.substr(0, Pos + 2); } return Sym; }
PythonObject PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict) { size_t dot_pos = name.find('.'); llvm::StringRef piece = name.substr(0, dot_pos); PythonObject result = dict.GetItemForKey(PythonString(piece)); if (dot_pos == llvm::StringRef::npos) { // There was no dot, we're done. return result; } // There was a dot. The remaining portion of the name should be looked up in // the context of the object that was found in the dictionary. return result.ResolveName(name.substr(dot_pos + 1)); }
// Parses the contents of version.txt in an CUDA installation. It should // contain one line of the from e.g. "CUDA Version 7.5.2". static CudaVersion ParseCudaVersionFile(llvm::StringRef V) { if (!V.startswith("CUDA Version ")) return CudaVersion::UNKNOWN; V = V.substr(strlen("CUDA Version ")); int Major = -1, Minor = -1; auto First = V.split('.'); auto Second = First.second.split('.'); if (First.first.getAsInteger(10, Major) || Second.first.getAsInteger(10, Minor)) return CudaVersion::UNKNOWN; if (Major == 7 && Minor == 0) { // This doesn't appear to ever happen -- version.txt doesn't exist in the // CUDA 7 installs I've seen. But no harm in checking. return CudaVersion::CUDA_70; } if (Major == 7 && Minor == 5) return CudaVersion::CUDA_75; if (Major == 8 && Minor == 0) return CudaVersion::CUDA_80; if (Major == 9 && Minor == 0) return CudaVersion::CUDA_90; if (Major == 9 && Minor == 1) return CudaVersion::CUDA_91; return CudaVersion::UNKNOWN; }
static void demangle(llvm::raw_ostream &os, llvm::StringRef name, const swift::Demangle::DemangleOptions &options) { bool hadLeadingUnderscore = false; if (name.startswith("__")) { hadLeadingUnderscore = true; name = name.substr(1); } swift::Demangle::NodePointer pointer = swift::demangle_wrappers::demangleSymbolAsNode(name); if (ExpandMode || TreeOnly) { llvm::outs() << "Demangling for " << name << '\n'; swift::demangle_wrappers::NodeDumper(pointer).print(llvm::outs()); } if (RemangleMode) { if (hadLeadingUnderscore) llvm::outs() << '_'; // Just reprint the original mangled name if it didn't demangle. // This makes it easier to share the same database between the // mangling and demangling tests. if (!pointer) { llvm::outs() << name; } else { llvm::outs() << swift::Demangle::mangleNode(pointer); } return; } if (!TreeOnly) { std::string string = swift::Demangle::nodeToString(pointer, options); if (!CompactMode) llvm::outs() << name << " ---> "; llvm::outs() << (string.empty() ? name : llvm::StringRef(string)); } }
/// HandleComment - Hook into the preprocessor and extract comments containing /// expected errors and warnings. bool VerifyDiagnosticConsumer::HandleComment(Lexer &PP, const SourceLocation& CommentBegin, const llvm::StringRef &C) { const llvm::SourceMgr &SM = PP.getSourceManager(); // If this comment is for a different source manager, ignore it. if (SrcManager && &SM != SrcManager) return false; if (C.empty()) return false; // Fold any "\<EOL>" sequences size_t loc = C.find('\\'); if (loc == StringRef::npos) { ParseDirective(C, &ED, SM, &PP, CommentBegin, Status); return false; } std::string C2; C2.reserve(C.size()); for (size_t last = 0;; loc = C.find('\\', last)) { if (loc == StringRef::npos || loc == C.size()) { C2 += C.substr(last); break; } C2 += C.substr(last, loc-last); last = loc + 1; if (C[last] == '\n' || C[last] == '\r') { ++last; // Escape \r\n or \n\r, but not \n\n. if (last < C.size()) if (C[last] == '\n' || C[last] == '\r') if (C[last] != C[last-1]) ++last; } else { // This was just a normal backslash. C2 += '\\'; } } if (!C2.empty()) ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status); return false; }
void InitHeaderSearch::AddDelimitedPaths(llvm::StringRef at) { if (at.empty()) // Empty string should not add '.' path. return; llvm::StringRef::size_type delim; while ((delim = at.find(llvm::sys::PathSeparator)) != llvm::StringRef::npos) { if (delim == 0) AddPath(".", Angled, false, true, false); else AddPath(at.substr(0, delim), Angled, false, true, false); at = at.substr(delim + 1); } if (at.empty()) AddPath(".", Angled, false, true, false); else AddPath(at, Angled, false, true, false); }
// Helpers to produce fake index symbols for memIndex() or completions(). // USRFormat is a regex replacement string for the unqualified part of the USR. Symbol sym(llvm::StringRef QName, index::SymbolKind Kind, llvm::StringRef USRFormat) { Symbol Sym; std::string USR = "******"; // We synthesize a few simple cases of USRs by hand! size_t Pos = QName.rfind("::"); if (Pos == llvm::StringRef::npos) { Sym.Name = QName; Sym.Scope = ""; } else { Sym.Name = QName.substr(Pos + 2); Sym.Scope = QName.substr(0, Pos + 2); USR += "@N@" + replace(QName.substr(0, Pos), "::", "@N@"); // ns:: -> @N@ns } USR += llvm::Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func# Sym.ID = SymbolID(USR); Sym.SymInfo.Kind = Kind; Sym.Flags |= Symbol::IndexedForCodeCompletion; Sym.Origin = SymbolOrigin::Static; return Sym; }
bool ProjectManager::shouldProcess(llvm::StringRef filename, ProjectInfo* project) { if (!project) return false; if (project->type == ProjectInfo::External) return false; std::string fn = outputPrefix % "/" % project->name % "/" % filename.substr(project->source_path.size()) % ".html"; return !llvm::sys::fs::exists(fn); // || boost::filesystem::last_write_time(p) < entry->getModificationTime(); }
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; }
static bool GetDescriptionSysV4L(llvm::StringRef path, std::string* desc) { llvm::SmallString<64> ifpath{"/sys/class/video4linux/"}; ifpath += path.substr(5); ifpath += "/device/interface"; int fd = open(ifpath.c_str(), O_RDONLY); if (fd < 0) return false; char readBuf[128]; ssize_t n = read(fd, readBuf, sizeof(readBuf)); close(fd); if (n <= 0) return false; *desc = llvm::StringRef(readBuf, n).rtrim(); return true; }
CompletionRequest::CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, int match_start_point, int max_return_elements, CompletionResult &result) : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos), m_match_start_point(match_start_point), m_max_return_elements(max_return_elements), m_result(result) { // We parse the argument up to the cursor, so the last argument in // parsed_line is the one containing the cursor, and the cursor is after the // last character. m_parsed_line = Args(command_line); m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos)); m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1; if (m_cursor_index == -1) m_cursor_char_position = 0; else m_cursor_char_position = strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index)); const char *cursor = command_line.data() + raw_cursor_pos; if (raw_cursor_pos > 0 && cursor[-1] == ' ') { // We are just after a space. If we are in an argument, then we will // continue parsing, but if we are between arguments, then we have to // complete whatever the next element would be. We can distinguish the two // cases because if we are in an argument (e.g. because the space is // protected by a quote) then the space will also be in the parsed // argument... const char *current_elem = m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index); if (m_cursor_char_position == 0 || current_elem[m_cursor_char_position - 1] != ' ') { m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(), '\0'); m_cursor_index++; m_cursor_char_position = 0; } } }
bool GetSystemLibraryPaths(llvm::SmallVectorImpl<std::string>& Paths) { #if defined(__APPLE__) || defined(__CYGWIN__) Paths.push_back("/usr/local/lib/"); Paths.push_back("/usr/X11R6/lib/"); Paths.push_back("/usr/lib/"); Paths.push_back("/lib/"); #ifndef __APPLE__ Paths.push_back("/lib/x86_64-linux-gnu/"); Paths.push_back("/usr/local/lib64/"); Paths.push_back("/usr/lib64/"); Paths.push_back("/lib64/"); #endif #else llvm::SmallString<1024> Buf; platform::Popen("LD_DEBUG=libs LD_PRELOAD=DOESNOTEXIST ls", Buf, true); const llvm::StringRef Result = Buf.str(); const std::size_t NPos = std::string::npos; const std::size_t LD = Result.find("(LD_LIBRARY_PATH)"); std::size_t From = Result.find("search path=", LD == NPos ? 0 : LD); if (From != NPos) { const std::size_t To = Result.find("(system search path)", From); if (To != NPos) { From += 12; std::string SysPath = Result.substr(From, To-From); SysPath.erase(std::remove_if(SysPath.begin(), SysPath.end(), isspace), SysPath.end()); llvm::SmallVector<llvm::StringRef, 10> CurPaths; SplitPaths(SysPath, CurPaths); for (const auto& Path : CurPaths) Paths.push_back(Path.str()); } } #endif return true; }
static bool GetIdentifier (llvm::StringRef &s, llvm::StringRef &identifier) { if (!s.empty()) { char ch = s[0]; if (isalpha(ch) || ch == '_') { size_t i; for (i = 1; i < s.size(); ++i) { ch = s[i]; if (isalnum(ch) || ch == '_') continue; else break; } identifier = s.substr(0, i); s = s.drop_front(i); return true; } } return false; }
void XCTMigrator::migrateInclude(llvm::StringRef Filename, CharSourceRange FilenameRange, SourceLocation HashLoc, bool isAngled) { StringRef Parent = "SenTestingKit/"; if (!Filename.startswith(Parent)) return; if (isFromSenTestInclude(HashLoc)) return; edit::Commit commit(Editor); StringRef HeaderName = Filename.substr(Parent.size()); llvm::StringMap<llvm::StringRef>::iterator I = IncludesMap.find(HeaderName); if (I == IncludesMap.end() || I->second.empty()) { commit.remove(CharSourceRange::getCharRange(HashLoc,FilenameRange.getEnd())); } else { SmallString<128> NewInclude; NewInclude.push_back(isAngled ? '<' : '"'); NewInclude += "XCTest/"; NewInclude += I->second; NewInclude.push_back(isAngled ? '>' : '"'); commit.replace(FilenameRange, NewInclude.str()); } Editor.commit(commit); }
static void demangle(llvm::raw_ostream &os, llvm::StringRef name, swift::Demangle::Context &DCtx, const swift::Demangle::DemangleOptions &options) { bool hadLeadingUnderscore = false; if (name.startswith("__")) { hadLeadingUnderscore = true; name = name.substr(1); } swift::Demangle::NodePointer pointer = DCtx.demangleSymbolAsNode(name); if (ExpandMode || TreeOnly) { llvm::outs() << "Demangling for " << name << '\n'; llvm::outs() << getNodeTreeAsString(pointer); } if (RemangleMode) { std::string remangled; if (!pointer || !(name.startswith(MANGLING_PREFIX_STR) || name.startswith("_S"))) { // Just reprint the original mangled name if it didn't demangle or is in // the old mangling scheme. // This makes it easier to share the same database between the // mangling and demangling tests. remangled = name; } else { remangled = swift::Demangle::mangleNode(pointer); // Also accept the future mangling prefix. // TODO: remove the special "_S" handling as soon as MANGLING_PREFIX_STR // gets "_S". if (name.startswith("_S")) { assert(remangled.find(MANGLING_PREFIX_STR) == 0); remangled = "_S" + remangled.substr(3); } if (name != remangled) { llvm::errs() << "\nError: re-mangled name \n " << remangled << "\ndoes not match original name\n " << name << '\n'; exit(1); } } if (hadLeadingUnderscore) llvm::outs() << '_'; llvm::outs() << remangled; return; } if (!TreeOnly) { if (RemangleNew) { if (!pointer) { llvm::errs() << "Can't de-mangle " << name << '\n'; exit(1); } std::string remangled = swift::Demangle::mangleNode(pointer); llvm::outs() << remangled; return; } std::string string = swift::Demangle::nodeToString(pointer, options); if (!CompactMode) llvm::outs() << name << " ---> "; if (Classify) { std::string Classifications; std::string cName = name.str(); if (!swift::Demangle::isSwiftSymbol(cName.c_str())) Classifications += 'N'; if (DCtx.isThunkSymbol(name)) { if (!Classifications.empty()) Classifications += ','; Classifications += "T:"; Classifications += DCtx.getThunkTarget(name); } else { assert(DCtx.getThunkTarget(name).empty()); } if (pointer && !DCtx.hasSwiftCallingConvention(name)) { if (!Classifications.empty()) Classifications += ','; Classifications += 'C'; } if (!Classifications.empty()) llvm::outs() << '{' << Classifications << "} "; } llvm::outs() << (string.empty() ? name : llvm::StringRef(string)); } DCtx.clear(); }
lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName (const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) { lldb::SectionType sect_type = lldb::eSectionTypeCode; switch (alloc_kind) { case AllocationKind::Stub: sect_type = lldb::eSectionTypeCode; break; case AllocationKind::Code: sect_type = lldb::eSectionTypeCode; break; case AllocationKind::Data: sect_type = lldb::eSectionTypeData; break; case AllocationKind::Global:sect_type = lldb::eSectionTypeData; break; case AllocationKind::Bytes: sect_type = lldb::eSectionTypeOther; break; } if (!name.empty()) { if (name.equals("__text") || name.equals(".text")) sect_type = lldb::eSectionTypeCode; else if (name.equals("__data") || name.equals(".data")) sect_type = lldb::eSectionTypeCode; else if (name.startswith("__debug_") || name.startswith(".debug_")) { const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef dwarf_name(name.substr(name_idx)); switch (dwarf_name[0]) { case 'a': if (dwarf_name.equals("abbrev")) sect_type = lldb::eSectionTypeDWARFDebugAbbrev; else if (dwarf_name.equals("aranges")) sect_type = lldb::eSectionTypeDWARFDebugAranges; break; case 'f': if (dwarf_name.equals("frame")) sect_type = lldb::eSectionTypeDWARFDebugFrame; break; case 'i': if (dwarf_name.equals("info")) sect_type = lldb::eSectionTypeDWARFDebugInfo; break; case 'l': if (dwarf_name.equals("line")) sect_type = lldb::eSectionTypeDWARFDebugLine; else if (dwarf_name.equals("loc")) sect_type = lldb::eSectionTypeDWARFDebugLoc; break; case 'm': if (dwarf_name.equals("macinfo")) sect_type = lldb::eSectionTypeDWARFDebugMacInfo; break; case 'p': if (dwarf_name.equals("pubnames")) sect_type = lldb::eSectionTypeDWARFDebugPubNames; else if (dwarf_name.equals("pubtypes")) sect_type = lldb::eSectionTypeDWARFDebugPubTypes; break; case 's': if (dwarf_name.equals("str")) sect_type = lldb::eSectionTypeDWARFDebugStr; break; case 'r': if (dwarf_name.equals("ranges")) sect_type = lldb::eSectionTypeDWARFDebugRanges; break; default: break; } } else if (name.startswith("__apple_") || name.startswith(".apple_")) { #if 0 const uint32_t name_idx = name[0] == '_' ? 8 : 7; llvm::StringRef apple_name(name.substr(name_idx)); switch (apple_name[0]) { case 'n': if (apple_name.equals("names")) sect_type = lldb::eSectionTypeDWARFAppleNames; else if (apple_name.equals("namespac") || apple_name.equals("namespaces")) sect_type = lldb::eSectionTypeDWARFAppleNamespaces; break; case 't': if (apple_name.equals("types")) sect_type = lldb::eSectionTypeDWARFAppleTypes; break; case 'o': if (apple_name.equals("objc")) sect_type = lldb::eSectionTypeDWARFAppleObjC; break; default: break; } #else sect_type = lldb::eSectionTypeInvalid; #endif } else if (name.equals("__objc_imageinfo")) sect_type = lldb::eSectionTypeOther; } return sect_type; }
static bool IsPercentageProperty(llvm::StringRef name) { if (name.startswith("raw_")) name = name.substr(4); return name == "brightness" || name == "contrast" || name == "saturation" || name == "hue" || name == "sharpness" || name == "gain" || name == "exposure_absolute"; }
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; }
static llvm::StringRef substrAfter(llvm::StringRef whole, llvm::StringRef part) { return whole.substr((part.data() - whole.data()) + part.size()); }
static inline void LStrip(llvm::StringRef &Str, char c) { if (!Str.empty() && Str.front() == c) Str = Str.substr(1); }
static inline void RStrip(llvm::StringRef &Str, char c) { if (!Str.empty() && Str.back() == c) Str = Str.substr(0, Str.size()-1); }
/// 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"; } }
static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) { return s.startswith("c:") ? s.substr(2) : ""; }
static inline void StripLeadingSpaces(llvm::StringRef &Str) { while (!Str.empty() && isspace(Str[0])) Str = Str.substr(1); }
static llvm::StringRef StripTrailingDots(llvm::StringRef s) { for (llvm::StringRef::size_type i = s.size(); i != 0; --i) if (s[i - 1] != '.') return s.substr(0, i); return ""; }