Clang Project

clang_source_code/lib/Tooling/ArgumentsAdjusters.cpp
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/StringRef.h"
17#include <cstddef>
18
19namespace clang {
20namespace tooling {
21
22/// Add -fsyntax-only option to the command line arguments.
23ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {
24  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
25    CommandLineArguments AdjustedArgs;
26    for (size_t i = 0, e = Args.size(); i < e; ++i) {
27      StringRef Arg = Args[i];
28      // FIXME: Remove options that generate output.
29      if (!Arg.startswith("-fcolor-diagnostics") &&
30          !Arg.startswith("-fdiagnostics-color"))
31        AdjustedArgs.push_back(Args[i]);
32    }
33    AdjustedArgs.push_back("-fsyntax-only");
34    return AdjustedArgs;
35  };
36}
37
38ArgumentsAdjuster getClangStripOutputAdjuster() {
39  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
40    CommandLineArguments AdjustedArgs;
41    for (size_t i = 0, e = Args.size(); i < e; ++i) {
42      StringRef Arg = Args[i];
43      if (!Arg.startswith("-o"))
44        AdjustedArgs.push_back(Args[i]);
45
46      if (Arg == "-o") {
47        // Output is specified as -o foo. Skip the next argument too.
48        ++i;
49      }
50      // Else, the output is specified as -ofoo. Just do nothing.
51    }
52    return AdjustedArgs;
53  };
54}
55
56ArgumentsAdjuster getClangStripDependencyFileAdjuster() {
57  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
58    CommandLineArguments AdjustedArgs;
59    for (size_t i = 0, e = Args.size(); i < e; ++i) {
60      StringRef Arg = Args[i];
61      // All dependency-file options begin with -M. These include -MM,
62      // -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD.
63      if (!Arg.startswith("-M")) {
64        AdjustedArgs.push_back(Args[i]);
65        continue;
66      }
67
68      if (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")
69        // These flags take an argument: -MX foo. Skip the next argument also.
70        ++i;
71    }
72    return AdjustedArgs;
73  };
74}
75
76ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,
77                                            ArgumentInsertPosition Pos) {
78  return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {
79    CommandLineArguments Return(Args);
80
81    CommandLineArguments::iterator I;
82    if (Pos == ArgumentInsertPosition::END) {
83      I = Return.end();
84    } else {
85      I = Return.begin();
86      ++I; // To leave the program name in place
87    }
88
89    Return.insert(I, Extra.begin(), Extra.end());
90    return Return;
91  };
92}
93
94ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,
95                                            ArgumentInsertPosition Pos) {
96  return getInsertArgumentAdjuster(CommandLineArguments(1Extra), Pos);
97}
98
99ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,
100                                   ArgumentsAdjuster Second) {
101  if (!First)
102    return Second;
103  if (!Second)
104    return First;
105  return [First, Second](const CommandLineArguments &Args, StringRef File) {
106    return Second(First(Args, File), File);
107  };
108}
109
110ArgumentsAdjuster getStripPluginsAdjuster() {
111  return [](const CommandLineArguments &Args, StringRef /*unused*/) {
112    CommandLineArguments AdjustedArgs;
113    for (size_t I = 0, E = Args.size(); I != E; I++) {
114      // According to https://clang.llvm.org/docs/ClangPlugins.html
115      // plugin arguments are in the form:
116      // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}
117      // -Xclang <arbitrary-argument>
118      if (I + 4 < E && Args[I] == "-Xclang" &&
119          (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||
120           llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") ||
121           Args[I + 1] == "-add-plugin") &&
122          Args[I + 2] == "-Xclang") {
123        I += 3;
124        continue;
125      }
126      AdjustedArgs.push_back(Args[I]);
127    }
128    return AdjustedArgs;
129  };
130}
131
132// end namespace tooling
133// end namespace clang
134