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