Path: blob/main/contrib/llvm-project/clang/lib/Tooling/ArgumentsAdjusters.cpp
35233 views
//===- ArgumentsAdjusters.cpp - Command line arguments adjuster -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains definitions of classes which implement ArgumentsAdjuster9// interface.10//11//===----------------------------------------------------------------------===//1213#include "clang/Tooling/ArgumentsAdjusters.h"14#include "clang/Basic/LLVM.h"15#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/StringRef.h"17#include <cstddef>18#include <vector>1920namespace clang {21namespace tooling {2223static StringRef getDriverMode(const CommandLineArguments &Args) {24for (const auto &Arg : Args) {25StringRef ArgRef = Arg;26if (ArgRef.consume_front("--driver-mode=")) {27return ArgRef;28}29}30return StringRef();31}3233/// Add -fsyntax-only option and drop options that triggers output generation.34ArgumentsAdjuster getClangSyntaxOnlyAdjuster() {35return [](const CommandLineArguments &Args, StringRef /*unused*/) {36CommandLineArguments AdjustedArgs;37bool HasSyntaxOnly = false;38constexpr llvm::StringRef OutputCommands[] = {39// FIXME: Add other options that generate output.40"-save-temps",41"--save-temps",42};43for (size_t i = 0, e = Args.size(); i < e; ++i) {44StringRef Arg = Args[i];45// Skip output commands.46if (llvm::any_of(OutputCommands, [&Arg](llvm::StringRef OutputCommand) {47return Arg.starts_with(OutputCommand);48}))49continue;5051if (!Arg.starts_with("-fcolor-diagnostics") &&52!Arg.starts_with("-fdiagnostics-color"))53AdjustedArgs.push_back(Args[i]);54// If we strip a color option, make sure we strip any preceeding `-Xclang`55// option as well.56// FIXME: This should be added to most argument adjusters!57else if (!AdjustedArgs.empty() && AdjustedArgs.back() == "-Xclang")58AdjustedArgs.pop_back();5960if (Arg == "-fsyntax-only")61HasSyntaxOnly = true;62}63if (!HasSyntaxOnly)64AdjustedArgs =65getInsertArgumentAdjuster("-fsyntax-only")(AdjustedArgs, "");66return AdjustedArgs;67};68}6970ArgumentsAdjuster getClangStripOutputAdjuster() {71return [](const CommandLineArguments &Args, StringRef /*unused*/) {72CommandLineArguments AdjustedArgs;73for (size_t i = 0, e = Args.size(); i < e; ++i) {74StringRef Arg = Args[i];75if (!Arg.starts_with("-o"))76AdjustedArgs.push_back(Args[i]);7778if (Arg == "-o") {79// Output is specified as -o foo. Skip the next argument too.80++i;81}82// Else, the output is specified as -ofoo. Just do nothing.83}84return AdjustedArgs;85};86}8788ArgumentsAdjuster getClangStripDependencyFileAdjuster() {89return [](const CommandLineArguments &Args, StringRef /*unused*/) {90auto UsingClDriver = (getDriverMode(Args) == "cl");9192CommandLineArguments AdjustedArgs;93for (size_t i = 0, e = Args.size(); i < e; ++i) {94StringRef Arg = Args[i];9596// These flags take an argument: -MX foo. Skip the next argument also.97if (!UsingClDriver && (Arg == "-MF" || Arg == "-MT" || Arg == "-MQ")) {98++i;99continue;100}101// When not using the cl driver mode, dependency file generation options102// begin with -M. These include -MM, -MF, -MG, -MP, -MT, -MQ, -MD, and103// -MMD.104if (!UsingClDriver && Arg.starts_with("-M"))105continue;106// Under MSVC's cl driver mode, dependency file generation is controlled107// using /showIncludes108if (Arg.starts_with("/showIncludes") || Arg.starts_with("-showIncludes"))109continue;110111AdjustedArgs.push_back(Args[i]);112}113return AdjustedArgs;114};115}116117ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra,118ArgumentInsertPosition Pos) {119return [Extra, Pos](const CommandLineArguments &Args, StringRef /*unused*/) {120CommandLineArguments Return(Args);121122CommandLineArguments::iterator I;123if (Pos == ArgumentInsertPosition::END) {124I = llvm::find(Return, "--");125} else {126I = Return.begin();127++I; // To leave the program name in place128}129130Return.insert(I, Extra.begin(), Extra.end());131return Return;132};133}134135ArgumentsAdjuster getInsertArgumentAdjuster(const char *Extra,136ArgumentInsertPosition Pos) {137return getInsertArgumentAdjuster(CommandLineArguments(1, Extra), Pos);138}139140ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First,141ArgumentsAdjuster Second) {142if (!First)143return Second;144if (!Second)145return First;146return [First, Second](const CommandLineArguments &Args, StringRef File) {147return Second(First(Args, File), File);148};149}150151ArgumentsAdjuster getStripPluginsAdjuster() {152return [](const CommandLineArguments &Args, StringRef /*unused*/) {153CommandLineArguments AdjustedArgs;154for (size_t I = 0, E = Args.size(); I != E; I++) {155// According to https://clang.llvm.org/docs/ClangPlugins.html156// plugin arguments are in the form:157// -Xclang {-load, -plugin, -plugin-arg-<plugin-name>, -add-plugin}158// -Xclang <arbitrary-argument>159if (I + 4 < E && Args[I] == "-Xclang" &&160(Args[I + 1] == "-load" || Args[I + 1] == "-plugin" ||161llvm::StringRef(Args[I + 1]).starts_with("-plugin-arg-") ||162Args[I + 1] == "-add-plugin") &&163Args[I + 2] == "-Xclang") {164I += 3;165continue;166}167AdjustedArgs.push_back(Args[I]);168}169return AdjustedArgs;170};171}172173} // end namespace tooling174} // end namespace clang175176177