10b57cec5SDimitry Andric //===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains definitions of classes which implement ArgumentsAdjuster 100b57cec5SDimitry Andric // interface. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "clang/Tooling/ArgumentsAdjusters.h" 150b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 170b57cec5SDimitry Andric #include <cstddef> 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace clang { 200b57cec5SDimitry Andric namespace tooling { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric /// Add -fsyntax-only option to the command line arguments. 230b57cec5SDimitry Andric ArgumentsAdjuster getClangSyntaxOnlyAdjuster() { 240b57cec5SDimitry Andric return [](const CommandLineArguments &Args, StringRef /*unused*/) { 250b57cec5SDimitry Andric CommandLineArguments AdjustedArgs; 260b57cec5SDimitry Andric bool HasSyntaxOnly = false; 270b57cec5SDimitry Andric for (size_t i = 0, e = Args.size(); i < e; ++i) { 280b57cec5SDimitry Andric StringRef Arg = Args[i]; 290b57cec5SDimitry Andric // FIXME: Remove options that generate output. 300b57cec5SDimitry Andric if (!Arg.startswith("-fcolor-diagnostics") && 310b57cec5SDimitry Andric !Arg.startswith("-fdiagnostics-color")) 320b57cec5SDimitry Andric AdjustedArgs.push_back(Args[i]); 330b57cec5SDimitry Andric if (Arg == "-fsyntax-only") 340b57cec5SDimitry Andric HasSyntaxOnly = true; 350b57cec5SDimitry Andric } 360b57cec5SDimitry Andric if (!HasSyntaxOnly) 370b57cec5SDimitry Andric AdjustedArgs.push_back("-fsyntax-only"); 380b57cec5SDimitry Andric return AdjustedArgs; 390b57cec5SDimitry Andric }; 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric ArgumentsAdjuster getClangStripOutputAdjuster() { 430b57cec5SDimitry Andric return [](const CommandLineArguments &Args, StringRef /*unused*/) { 440b57cec5SDimitry Andric CommandLineArguments AdjustedArgs; 450b57cec5SDimitry Andric for (size_t i = 0, e = Args.size(); i < e; ++i) { 460b57cec5SDimitry Andric StringRef Arg = Args[i]; 470b57cec5SDimitry Andric if (!Arg.startswith("-o")) 480b57cec5SDimitry Andric AdjustedArgs.push_back(Args[i]); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric if (Arg == "-o") { 510b57cec5SDimitry Andric // Output is specified as -o foo. Skip the next argument too. 520b57cec5SDimitry Andric ++i; 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric // Else, the output is specified as -ofoo. Just do nothing. 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric return AdjustedArgs; 570b57cec5SDimitry Andric }; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 60*a7dea167SDimitry Andric ArgumentsAdjuster getClangStripSerializeDiagnosticAdjuster() { 61*a7dea167SDimitry Andric return [](const CommandLineArguments &Args, StringRef /*unused*/) { 62*a7dea167SDimitry Andric CommandLineArguments AdjustedArgs; 63*a7dea167SDimitry Andric for (size_t i = 0, e = Args.size(); i < e; ++i) { 64*a7dea167SDimitry Andric StringRef Arg = Args[i]; 65*a7dea167SDimitry Andric if (Arg == "--serialize-diagnostics") { 66*a7dea167SDimitry Andric // Skip the diagnostic output argument. 67*a7dea167SDimitry Andric ++i; 68*a7dea167SDimitry Andric continue; 69*a7dea167SDimitry Andric } 70*a7dea167SDimitry Andric AdjustedArgs.push_back(Args[i]); 71*a7dea167SDimitry Andric } 72*a7dea167SDimitry Andric return AdjustedArgs; 73*a7dea167SDimitry Andric }; 74*a7dea167SDimitry Andric } 75*a7dea167SDimitry Andric 760b57cec5SDimitry Andric ArgumentsAdjuster getClangStripDependencyFileAdjuster() { 770b57cec5SDimitry Andric return [](const CommandLineArguments &Args, StringRef /*unused*/) { 780b57cec5SDimitry Andric CommandLineArguments AdjustedArgs; 790b57cec5SDimitry Andric for (size_t i = 0, e = Args.size(); i < e; ++i) { 800b57cec5SDimitry Andric StringRef Arg = Args[i]; 810b57cec5SDimitry Andric // All dependency-file options begin with -M. These include -MM, 820b57cec5SDimitry Andric // -MF, -MG, -MP, -MT, -MQ, -MD, and -MMD. 830b57cec5SDimitry Andric if (!Arg.startswith("-M")) { 840b57cec5SDimitry Andric AdjustedArgs.push_back(Args[i]); 850b57cec5SDimitry Andric continue; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric if (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ") 890b57cec5SDimitry Andric // These flags take an argument: -MX foo. Skip the next argument also. 900b57cec5SDimitry Andric ++i; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric return AdjustedArgs; 930b57cec5SDimitry Andric }; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, 970b57cec5SDimitry Andric ArgumentInsertPosition Pos) { 980b57cec5SDimitry Andric return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) { 990b57cec5SDimitry Andric CommandLineArguments Return(Args); 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric CommandLineArguments::iterator I; 1020b57cec5SDimitry Andric if (Pos == ArgumentInsertPosition::END) { 1030b57cec5SDimitry Andric I = Return.end(); 1040b57cec5SDimitry Andric } else { 1050b57cec5SDimitry Andric I = Return.begin(); 1060b57cec5SDimitry Andric ++I; // To leave the program name in place 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric Return.insert(I, Extra.begin(), Extra.end()); 1100b57cec5SDimitry Andric return Return; 1110b57cec5SDimitry Andric }; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra, 1150b57cec5SDimitry Andric ArgumentInsertPosition Pos) { 1160b57cec5SDimitry Andric return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, 1200b57cec5SDimitry Andric ArgumentsAdjuster Second) { 1210b57cec5SDimitry Andric if (!First) 1220b57cec5SDimitry Andric return Second; 1230b57cec5SDimitry Andric if (!Second) 1240b57cec5SDimitry Andric return First; 1250b57cec5SDimitry Andric return [First, Second](const CommandLineArguments &Args, StringRef File) { 1260b57cec5SDimitry Andric return Second(First(Args, File), File); 1270b57cec5SDimitry Andric }; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric ArgumentsAdjuster getStripPluginsAdjuster() { 1310b57cec5SDimitry Andric return [](const CommandLineArguments &Args, StringRef /*unused*/) { 1320b57cec5SDimitry Andric CommandLineArguments AdjustedArgs; 1330b57cec5SDimitry Andric for (size_t I = 0, E = Args.size(); I != E; I++) { 1340b57cec5SDimitry Andric // According to https://clang.llvm.org/docs/ClangPlugins.html 1350b57cec5SDimitry Andric // plugin arguments are in the form: 1360b57cec5SDimitry Andric // -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin} 1370b57cec5SDimitry Andric // -Xclang <arbitrary-argument> 1380b57cec5SDimitry Andric if (I + 4 < E && Args[I] == "-Xclang" && 1390b57cec5SDimitry Andric (Args[I + 1] == "-load" || Args[I + 1] == "-plugin" || 1400b57cec5SDimitry Andric llvm::StringRef(Args[I + 1]).startswith("-plugin-arg-") || 1410b57cec5SDimitry Andric Args[I + 1] == "-add-plugin") && 1420b57cec5SDimitry Andric Args[I + 2] == "-Xclang") { 1430b57cec5SDimitry Andric I += 3; 1440b57cec5SDimitry Andric continue; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric AdjustedArgs.push_back(Args[I]); 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric return AdjustedArgs; 1490b57cec5SDimitry Andric }; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric } // end namespace tooling 1530b57cec5SDimitry Andric } // end namespace clang 154