Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains definitions of classes which implement ArgumentsAdjuster
10
// interface.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/Tooling/ArgumentsAdjusters.h"
15
#include "clang/Basic/LLVM.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/ADT/StringRef.h"
18
#include <cstddef>
19
#include <vector>
20
21
namespace clang {
22
namespace tooling {
23
24
0
static StringRef getDriverMode(const CommandLineArguments &Args) {
25
0
  for (const auto &Arg : Args) {
26
0
    StringRef ArgRef = Arg;
27
0
    if (ArgRef.consume_front("--driver-mode=")) {
28
0
      return ArgRef;
29
0
    }
30
0
  }
31
0
  return StringRef();
32
0
}
33
34
/// Add -fsyntax-only option and drop options that triggers output generation.
35
0
ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
36
0
  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
37
0
    CommandLineArguments AdjustedArgs;
38
0
    bool HasSyntaxOnly = false;
39
0
    constexpr llvm::StringRef OutputCommands[] = {
40
        // FIXME: Add other options that generate output.
41
0
        "-save-temps",
42
0
        "--save-temps",
43
0
    };
44
0
    for (size_t i = 0, e = Args.size(); i < e; ++i) {
45
0
      StringRef Arg = Args[i];
46
      // Skip output commands.
47
0
      if (llvm::any_of(OutputCommands, [&Arg](llvm::StringRef OutputCommand) {
48
0
            return Arg.starts_with(OutputCommand);
49
0
          }))
50
0
        continue;
51
52
0
      if (!Arg.starts_with("-fcolor-diagnostics") &&
53
0
          !Arg.starts_with("-fdiagnostics-color"))
54
0
        AdjustedArgs.push_back(Args[i]);
55
      // If we strip a color option, make sure we strip any preceeding `-Xclang`
56
      // option as well.
57
      // FIXME: This should be added to most argument adjusters!
58
0
      else if (!AdjustedArgs.empty() && AdjustedArgs.back() == "-Xclang")
59
0
        AdjustedArgs.pop_back();
60
61
0
      if (Arg == "-fsyntax-only")
62
0
        HasSyntaxOnly = true;
63
0
    }
64
0
    if (!HasSyntaxOnly)
65
0
      AdjustedArgs =
66
0
          getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, "");
67
0
    return AdjustedArgs;
68
0
  };
69
0
}
70
71
0
ArgumentsAdjuster getClangStripOutputAdjuster() {
72
0
  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
73
0
    CommandLineArguments AdjustedArgs;
74
0
    for (size_t i = 0, e = Args.size(); i < e; ++i) {
75
0
      StringRef Arg = Args[i];
76
0
      if (!Arg.starts_with("-o"))
77
0
        AdjustedArgs.push_back(Args[i]);
78
79
0
      if (Arg == "-o") {
80
        // Output is specified as -o foo. Skip the next argument too.
81
0
        ++i;
82
0
      }
83
      // Else, the output is specified as -ofoo. Just do nothing.
84
0
    }
85
0
    return AdjustedArgs;
86
0
  };
87
0
}
88
89
0
ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
90
0
  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
91
0
    auto UsingClDriver = (getDriverMode(Args) == "cl");
92
93
0
    CommandLineArguments AdjustedArgs;
94
0
    for (size_t i = 0, e = Args.size(); i < e; ++i) {
95
0
      StringRef Arg = Args[i];
96
97
      // These flags take an argument: -MX foo. Skip the next argument also.
98
0
      if (!UsingClDriver && (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")) {
99
0
        ++i;
100
0
        continue;
101
0
      }
102
      // When not using the cl driver mode, dependency file generation options
103
      // begin with -M. These include -MM, -MF, -MG, -MP, -MT, -MQ, -MD, and
104
      // -MMD.
105
0
      if (!UsingClDriver && Arg.starts_with("-M"))
106
0
        continue;
107
      // Under MSVC's cl driver mode, dependency file generation is controlled
108
      // using /showIncludes
109
0
      if (Arg.starts_with("/showIncludes") || Arg.starts_with("-showIncludes"))
110
0
        continue;
111
112
0
      AdjustedArgs.push_back(Args[i]);
113
0
    }
114
0
    return AdjustedArgs;
115
0
  };
116
0
}
117
118
ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
119
0
                                            ArgumentInsertPosition Pos) {
120
0
  return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
121
0
    CommandLineArguments Return(Args);
122
123
0
    CommandLineArguments::iterator I;
124
0
    if (Pos == ArgumentInsertPosition::END) {
125
0
      I = llvm::find(Return, "--");
126
0
    } else {
127
0
      I = Return.begin();
128
0
      ++I; // To leave the program name in place
129
0
    }
130
131
0
    Return.insert(I, Extra.begin(), Extra.end());
132
0
    return Return;
133
0
  };
134
0
}
135
136
ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
137
0
                                            ArgumentInsertPosition Pos) {
138
0
  return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);
139
0
}
140
141
ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
142
0
                                   ArgumentsAdjuster Second) {
143
0
  if (!First)
144
0
    return Second;
145
0
  if (!Second)
146
0
    return First;
147
0
  return [First, Second](const CommandLineArguments &Args, StringRef File) {
148
0
    return Second(First(Args, File), File);
149
0
  };
150
0
}
151
152
0
ArgumentsAdjuster getStripPluginsAdjuster() {
153
0
  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
154
0
    CommandLineArguments AdjustedArgs;
155
0
    for (size_t I = 0, E = Args.size(); I != E; I++) {
156
      // According to https://clang.llvm.org/docs/ClangPlugins.html
157
      // plugin arguments are in the form:
158
      // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
159
      // -Xclang <arbitrary-argument>
160
0
      if (I + 4 < E && Args[I] == "-Xclang" &&
161
0
          (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
162
0
           llvm::StringRef(Args[I + 1]).starts_with("-plugin-arg-") ||
163
0
           Args[I + 1] == "-add-plugin") &&
164
0
          Args[I + 2] == "-Xclang") {
165
0
        I += 3;
166
0
        continue;
167
0
      }
168
0
      AdjustedArgs.push_back(Args[I]);
169
0
    }
170
0
    return AdjustedArgs;
171
0
  };
172
0
}
173
174
} // end namespace tooling
175
} // end namespace clang