From 3edbeb78fe5ea7fffea7a94575478cde19e830e0 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 29 Mar 2010 17:55:58 +0000 Subject: [PATCH] add support for -MQ flag to quote targets in dependency file, PR6661, patch by Ori Avtalion! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99821 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 2 +- include/clang/Driver/CC1Options.td | 1 + lib/Driver/Tools.cpp | 58 +++++++++++++++++-- test/Preprocessor/dependencies-and-pp.c | 26 +++++++++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b1453e3f49..2e0b4bad6b 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -22,7 +22,7 @@ def err_fe_stdout_binary : Error<"unable to change standard output to binary">, def err_fe_stderr_binary : Error<"unable to change standard error to binary">, DefaultFatal; def err_fe_dependency_file_requires_MT : Error< - "-dependency-file requires at least one -MT option">; + "-dependency-file requires at least one -MT or -MQ option">; def err_fe_incompatible_options : Error< "'%0' cannot be used with '%1'">, DefaultFatal; def err_fe_no_fixit_and_codegen : Error< diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 488e33631b..124288a763 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -156,6 +156,7 @@ def dependency_file : Separate<"-dependency-file">, HelpText<"Filename (or -) to write dependency output to">; def sys_header_deps : Flag<"-sys-header-deps">, HelpText<"Include system headers in dependency output">; +def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; def MP : Flag<"-MP">, HelpText<"Create phony target for each dependency (other than main file)">; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index e5ee287f87..2a3799152a 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -56,6 +56,35 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) { << A->getAsString(Args) << "-static"; } +// Quote target names for inclusion in GNU Make dependency files. +// Only the characters '$', '#', ' ', '\t' are quoted. +static void QuoteTarget(llvm::StringRef Target, + llvm::SmallVectorImpl &Res) { + for (unsigned i = 0, e = Target.size(); i != e; ++i) { + switch (Target[i]) { + case ' ': + case '\t': + // Escape the preceding backslashes + for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j) + Res.push_back('\\'); + + // Escape the space/tab + Res.push_back('\\'); + break; + case '$': + Res.push_back('$'); + break; + case '#': + Res.push_back('\\'); + break; + default: + break; + } + + Res.push_back(Target[i]); + } +} + void Clang::AddPreprocessingOptions(const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, @@ -91,9 +120,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); - // Add an -MT option if the user didn't specify their own. - // - // FIXME: This should use -MQ, when we support it. + // Add a default target if one wasn't specified. if (!Args.hasArg(options::OPT_MT) && !Args.hasArg(options::OPT_MQ)) { const char *DepTarget; @@ -114,7 +141,9 @@ void Clang::AddPreprocessingOptions(const Driver &D, } CmdArgs.push_back("-MT"); - CmdArgs.push_back(DepTarget); + llvm::SmallString<128> Quoted; + QuoteTarget(DepTarget, Quoted); + CmdArgs.push_back(Args.MakeArgString(Quoted)); } if (A->getOption().matches(options::OPT_M) || @@ -123,7 +152,25 @@ void Clang::AddPreprocessingOptions(const Driver &D, } Args.AddLastArg(CmdArgs, options::OPT_MP); - Args.AddAllArgs(CmdArgs, options::OPT_MT); + + // Convert all -MQ args to -MT + for (arg_iterator it = Args.filtered_begin(options::OPT_MT, + options::OPT_MQ), + ie = Args.filtered_end(); it != ie; ++it) { + + it->claim(); + + if (it->getOption().matches(options::OPT_MQ)) { + CmdArgs.push_back("-MT"); + llvm::SmallString<128> Quoted; + QuoteTarget(it->getValue(Args), Quoted); + CmdArgs.push_back(Args.MakeArgString(Quoted)); + + // -MT flag - no change + } else { + it->render(Args, CmdArgs); + } + } // Add -i* options, and automatically translate to // -include-pch/-include-pth for transparent PCH support. It's @@ -930,7 +977,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Arg *Unsupported; if ((Unsupported = Args.getLastArg(options::OPT_MG)) || - (Unsupported = Args.getLastArg(options::OPT_MQ)) || (Unsupported = Args.getLastArg(options::OPT_iframework)) || (Unsupported = Args.getLastArg(options::OPT_fshort_enums))) D.Diag(clang::diag::err_drv_clang_unsupported) diff --git a/test/Preprocessor/dependencies-and-pp.c b/test/Preprocessor/dependencies-and-pp.c index d7bf4df51c..7877df3f78 100644 --- a/test/Preprocessor/dependencies-and-pp.c +++ b/test/Preprocessor/dependencies-and-pp.c @@ -1,5 +1,31 @@ +// Test -MT and -E flags, PR4063 + // RUN: %clang -E -o %t.1 %s // RUN: %clang -E -MD -MF %t.d -MT foo -o %t.2 %s // RUN: diff %t.1 %t.2 // RUN: grep "foo:" %t.d // RUN: grep "dependencies-and-pp.c" %t.d + +// Test -MQ flag without quoting + +// RUN: %clang -E -MD -MF %t.d -MQ foo -o %t %s +// RUN: grep "foo:" %t.d + +// Test -MQ flag with quoting + +// RUN: %clang -E -MD -MF %t.d -MQ '$fo\ooo ooo\ ooo\\ ooo#oo' -o %t %s +// RUN: fgrep '$$fo\ooo\ ooo\\\ ooo\\\\\ ooo\#oo:' %t.d + +// Test consecutive -MT flags + +// RUN: %clang -E -MD -MF %t.d -MT foo -MT bar -MT baz -o %t %s +// RUN: diff %t.1 %t +// RUN: fgrep "foo bar baz:" %t.d + +// Test consecutive -MT and -MQ flags + +// RUN: %clang -E -MD -MF %t.d -MT foo -MQ '$(bar)' -MT 'b az' -MQ 'qu ux' -MQ ' space' -o %t %s +// RUN: fgrep 'foo $$(bar) b az qu\ ux \ space:' %t.d + +// TODO: Test default target without quoting +// TODO: Test default target with quoting -- 2.50.1