1
2//===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===//
3//
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
7//
8//===----------------------------------------------------------------------===//
9//
10// Command line parsing for source locations.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
15#define LLVM_CLANG_FRONTEND_COMMANDLINESOURCELOC_H
16
17#include "clang/Basic/LLVM.h"
18#include "llvm/Support/CommandLine.h"
19#include "llvm/Support/raw_ostream.h"
20#include <optional>
21
22namespace clang {
23
24/// A source location that has been parsed on the command line.
25struct ParsedSourceLocation {
26 std::string FileName;
27 // The 1-based line number
28 unsigned Line;
29 // The 1-based column number
30 unsigned Column;
31
32public:
33 /// Construct a parsed source location from a string; the Filename is empty on
34 /// error.
35 static ParsedSourceLocation FromString(StringRef Str) {
36 ParsedSourceLocation PSL;
37 std::pair<StringRef, StringRef> ColSplit = Str.rsplit(Separator: ':');
38 std::pair<StringRef, StringRef> LineSplit =
39 ColSplit.first.rsplit(Separator: ':');
40
41 // If both tail splits were valid integers, return success.
42 if (!ColSplit.second.getAsInteger(Radix: 10, Result&: PSL.Column) &&
43 !LineSplit.second.getAsInteger(Radix: 10, Result&: PSL.Line) &&
44 !(PSL.Column == 0 || PSL.Line == 0)) {
45 PSL.FileName = std::string(LineSplit.first);
46
47 // On the command-line, stdin may be specified via "-". Inside the
48 // compiler, stdin is called "<stdin>".
49 if (PSL.FileName == "-")
50 PSL.FileName = "<stdin>";
51 }
52
53 return PSL;
54 }
55
56 /// Serialize ParsedSourceLocation back to a string.
57 std::string ToString() const {
58 return (llvm::Twine(FileName == "<stdin>" ? "-" : FileName) + ":" +
59 Twine(Line) + ":" + Twine(Column))
60 .str();
61 }
62};
63
64/// A source range that has been parsed on the command line.
65struct ParsedSourceRange {
66 std::string FileName;
67 /// The starting location of the range. The first element is the line and
68 /// the second element is the column.
69 std::pair<unsigned, unsigned> Begin;
70 /// The ending location of the range. The first element is the line and the
71 /// second element is the column.
72 std::pair<unsigned, unsigned> End;
73
74 /// Returns a parsed source range from a string or std::nullopt if the string
75 /// is invalid.
76 ///
77 /// These source string has the following format:
78 ///
79 /// file:start_line:start_column[-end_line:end_column]
80 ///
81 /// If the end line and column are omitted, the starting line and columns
82 /// are used as the end values.
83 static std::optional<ParsedSourceRange> fromString(StringRef Str) {
84 std::pair<StringRef, StringRef> RangeSplit = Str.rsplit(Separator: '-');
85 unsigned EndLine, EndColumn;
86 bool HasEndLoc = false;
87 if (!RangeSplit.second.empty()) {
88 std::pair<StringRef, StringRef> Split = RangeSplit.second.rsplit(Separator: ':');
89 if (Split.first.getAsInteger(Radix: 10, Result&: EndLine) ||
90 Split.second.getAsInteger(Radix: 10, Result&: EndColumn)) {
91 // The string does not end in end_line:end_column, so the '-'
92 // probably belongs to the filename which menas the whole
93 // string should be parsed.
94 RangeSplit.first = Str;
95 } else {
96 // Column and line numbers are 1-based.
97 if (EndLine == 0 || EndColumn == 0)
98 return std::nullopt;
99 HasEndLoc = true;
100 }
101 }
102 auto Begin = ParsedSourceLocation::FromString(Str: RangeSplit.first);
103 if (Begin.FileName.empty())
104 return std::nullopt;
105 if (!HasEndLoc) {
106 EndLine = Begin.Line;
107 EndColumn = Begin.Column;
108 }
109 return ParsedSourceRange{.FileName: std::move(Begin.FileName),
110 .Begin: {Begin.Line, Begin.Column},
111 .End: {EndLine, EndColumn}};
112 }
113};
114}
115
116namespace llvm {
117 namespace cl {
118 /// Command-line option parser that parses source locations.
119 ///
120 /// Source locations are of the form filename:line:column.
121 template<>
122 class parser<clang::ParsedSourceLocation> final
123 : public basic_parser<clang::ParsedSourceLocation> {
124 public:
125 inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
126 clang::ParsedSourceLocation &Val);
127 };
128
129 bool
130 parser<clang::ParsedSourceLocation>::
131 parse(Option &O, StringRef ArgName, StringRef ArgValue,
132 clang::ParsedSourceLocation &Val) {
133 using namespace clang;
134
135 Val = ParsedSourceLocation::FromString(Str: ArgValue);
136 if (Val.FileName.empty()) {
137 errs() << "error: "
138 << "source location must be of the form filename:line:column\n";
139 return true;
140 }
141
142 return false;
143 }
144 }
145}
146
147#endif
148

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/include/clang/Frontend/CommandLineSourceLoc.h