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