]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Frontend/CommandLineSourceLoc.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Frontend / CommandLineSourceLoc.h
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
21 namespace clang {
22
23 /// A source location that has been parsed on the command line.
24 struct ParsedSourceLocation {
25   std::string FileName;
26   unsigned Line;
27   unsigned Column;
28
29 public:
30   /// Construct a parsed source location from a string; the Filename is empty on
31   /// error.
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(':');
37
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;
42
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>";
47     }
48
49     return PSL;
50   }
51 };
52
53 /// A source range that has been parsed on the command line.
54 struct ParsedSourceRange {
55   std::string FileName;
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;
62
63   /// Returns a parsed source range from a string or None if the string is
64   /// invalid.
65   ///
66   /// These source string has the following format:
67   ///
68   /// file:start_line:start_column[-end_line:end_column]
69   ///
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;
84       } else
85         HasEndLoc = true;
86     }
87     auto Begin = ParsedSourceLocation::FromString(RangeSplit.first);
88     if (Begin.FileName.empty())
89       return None;
90     if (!HasEndLoc) {
91       EndLine = Begin.Line;
92       EndColumn = Begin.Column;
93     }
94     return ParsedSourceRange{std::move(Begin.FileName),
95                              {Begin.Line, Begin.Column},
96                              {EndLine, EndColumn}};
97   }
98 };
99 }
100
101 namespace llvm {
102   namespace cl {
103     /// Command-line option parser that parses source locations.
104     ///
105     /// Source locations are of the form filename:line:column.
106     template<>
107     class parser<clang::ParsedSourceLocation> final
108       : public basic_parser<clang::ParsedSourceLocation> {
109     public:
110       inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
111                  clang::ParsedSourceLocation &Val);
112     };
113
114     bool
115     parser<clang::ParsedSourceLocation>::
116     parse(Option &O, StringRef ArgName, StringRef ArgValue,
117           clang::ParsedSourceLocation &Val) {
118       using namespace clang;
119
120       Val = ParsedSourceLocation::FromString(ArgValue);
121       if (Val.FileName.empty()) {
122         errs() << "error: "
123                << "source location must be of the form filename:line:column\n";
124         return true;
125       }
126
127       return false;
128     }
129   }
130 }
131
132 #endif