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 getClangStripDependencyFileAdjuster() { 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 // All dependency-file options begin with -M. These include -MM, 66 // -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD. 67 if (!Arg.startswith("-M")) { 68 AdjustedArgs.push_back(Args[i]); 69 continue; 70 } 71 72 if (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ") 73 // These flags take an argument: -MX foo. Skip the next argument also. 74 ++i; 75 } 76 return AdjustedArgs; 77 }; 78 } 79 80 ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, 81 ArgumentInsertPosition Pos) { 82 return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) { 83 CommandLineArguments Return(Args); 84 85 CommandLineArguments::iterator I; 86 if (Pos == ArgumentInsertPosition::END) { 87 I = Return.end(); 88 } else { 89 I = Return.begin(); 90 ++I; // To leave the program name in place 91 } 92 93 Return.insert(I, Extra.begin(), Extra.end()); 94 return Return; 95 }; 96 } 97 98 ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, 99 ArgumentInsertPosition Pos) { 100 return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos); 101 } 102 103 ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, 104 ArgumentsAdjuster Second) { 105 if (!First) 106 return Second; 107 if (!Second) 108 return First; 109 return [First, Second](const CommandLineArguments &Args, StringRef File) { 110 return Second(First(Args, File), File); 111 }; 112 } 113 114 ArgumentsAdjuster getStripPluginsAdjuster() { 115 return [](const CommandLineArguments &Args, StringRef /*unused*/) { 116 CommandLineArguments AdjustedArgs; 117 for (size_t I = 0, E = Args.size(); I != E; I++) { 118 // According to https://clang.llvm.org/docs/ClangPlugins.html 119 // plugin arguments are in the form: 120 // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin} 121 // -Xclang <arbitrary-argument> 122 if (I + 4 < E && Args[I] == "-Xclang" && 123 (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" || 124 llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") || 125 Args[I + 1] == "-add-plugin") && 126 Args[I + 2] == "-Xclang") { 127 I += 3; 128 continue; 129 } 130 AdjustedArgs.push_back(Args[I]); 131 } 132 return AdjustedArgs; 133 }; 134 } 135 136 } // end namespace tooling 137 } // end namespace clang 138