Clang Project

clang_source_code/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
21namespace clang {
22
23/// A source location that has been parsed on the command line.
24struct ParsedSourceLocation {
25  std::string FileName;
26  unsigned Line;
27  unsigned Column;
28
29public:
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<StringRefStringRefColSplit = Str.rsplit(':');
35    std::pair<StringRefStringRefLineSplit =
36      ColSplit.first.rsplit(':');
37
38    // If both tail splits were valid integers, return success.
39    if (!ColSplit.second.getAsInteger(10PSL.Column) &&
40        !LineSplit.second.getAsInteger(10PSL.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.
54struct 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<unsignedunsignedBegin;
59  /// The ending location of the range. The first element is the line and the
60  /// second element is the column.
61  std::pair<unsignedunsignedEnd;
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<ParsedSourceRangefromString(StringRef Str) {
73    std::pair<StringRefStringRefRangeSplit = Str.rsplit('-');
74    unsigned EndLineEndColumn;
75    bool HasEndLoc = false;
76    if (!RangeSplit.second.empty()) {
77      std::pair<StringRefStringRefSplit = RangeSplit.second.rsplit(':');
78      if (Split.first.getAsInteger(10EndLine) ||
79          Split.second.getAsInteger(10EndColumn)) {
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
101namespace 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 &OStringRef ArgNameStringRef 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
133
clang::ParsedSourceLocation::FileName
clang::ParsedSourceLocation::Line
clang::ParsedSourceLocation::Column
clang::ParsedSourceLocation::FromString
clang::ParsedSourceRange::FileName
clang::ParsedSourceRange::Begin
clang::ParsedSourceRange::End
clang::ParsedSourceRange::fromString
llvm::cl::parser::parse