2 //===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 // Command line parsing for source locations.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
15 #define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
17 #include "clang/Basic/LLVM.h"
18 #include "llvm/Support/CommandLine.h"
19 #include "llvm/Support/raw_ostream.h"
23 /// A source location that has been parsed on the command line.
24 struct ParsedSourceLocation {
30 /// Construct a parsed source location from a string; the Filename is empty on
32 static ParsedSourceLocation FromString(StringRef Str) {
33 ParsedSourceLocation PSL;
34 std::pair<StringRef, StringRef> ColSplit = Str.rsplit(':');
35 std::pair<StringRef, StringRef> LineSplit =
36 ColSplit.first.rsplit(':');
38 // If both tail splits were valid integers, return success.
39 if (!ColSplit.second.getAsInteger(10, PSL.Column) &&
40 !LineSplit.second.getAsInteger(10, PSL.Line)) {
41 PSL.FileName = LineSplit.first;
43 // On the command-line, stdin may be specified via "-". Inside the
44 // compiler, stdin is called "<stdin>".
45 if (PSL.FileName == "-")
46 PSL.FileName = "<stdin>";
53 /// A source range that has been parsed on the command line.
54 struct ParsedSourceRange {
56 /// The starting location of the range. The first element is the line and
57 /// the second element is the column.
58 std::pair<unsigned, unsigned> Begin;
59 /// The ending location of the range. The first element is the line and the
60 /// second element is the column.
61 std::pair<unsigned, unsigned> End;
63 /// Returns a parsed source range from a string or None if the string is
66 /// These source string has the following format:
68 /// file:start_line:start_column[-end_line:end_column]
70 /// If the end line and column are omitted, the starting line and columns
71 /// are used as the end values.
72 static Optional<ParsedSourceRange> fromString(StringRef Str) {
73 std::pair<StringRef, StringRef> RangeSplit = Str.rsplit('-');
74 unsigned EndLine, EndColumn;
75 bool HasEndLoc = false;
76 if (!RangeSplit.second.empty()) {
77 std::pair<StringRef, StringRef> Split = RangeSplit.second.rsplit(':');
78 if (Split.first.getAsInteger(10, EndLine) ||
79 Split.second.getAsInteger(10, EndColumn)) {
80 // The string does not end in end_line:end_column, so the '-'
81 // probably belongs to the filename which menas the whole
82 // string should be parsed.
83 RangeSplit.first = Str;
87 auto Begin = ParsedSourceLocation::FromString(RangeSplit.first);
88 if (Begin.FileName.empty())
92 EndColumn = Begin.Column;
94 return ParsedSourceRange{std::move(Begin.FileName),
95 {Begin.Line, Begin.Column},
96 {EndLine, EndColumn}};
103 /// Command-line option parser that parses source locations.
105 /// Source locations are of the form filename:line:column.
107 class parser<clang::ParsedSourceLocation> final
108 : public basic_parser<clang::ParsedSourceLocation> {
110 inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
111 clang::ParsedSourceLocation &Val);
115 parser<clang::ParsedSourceLocation>::
116 parse(Option &O, StringRef ArgName, StringRef ArgValue,
117 clang::ParsedSourceLocation &Val) {
118 using namespace clang;
120 Val = ParsedSourceLocation::FromString(ArgValue);
121 if (Val.FileName.empty()) {
123 << "source location must be of the form filename:line:column\n";