diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index 49fd920d1ec43..8fe63d7c2141b 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -118,6 +118,9 @@ class DependencyFileGenerator : public DependencyCollector { void outputDependencyFile(llvm::raw_ostream &OS); private: + void outputDependencyFilename(llvm::raw_ostream &OS, + StringRef Filename) const; + void outputDependencyFile(DiagnosticsEngine &Diags); std::string OutputFile; @@ -128,6 +131,7 @@ class DependencyFileGenerator : public DependencyCollector { bool SeenMissingHeader; bool IncludeModuleFiles; DependencyOutputFormat OutputFormat; + bool MSCompatible; unsigned InputFileIndex; }; diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index 15fa7de35df97..fc5b7949afa22 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -223,7 +223,7 @@ DependencyFileGenerator::DependencyFileGenerator( PhonyTarget(Opts.UsePhonyTargets), AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false), IncludeModuleFiles(Opts.IncludeModuleFiles), - OutputFormat(Opts.OutputFormat), InputFileIndex(0) { + OutputFormat(Opts.OutputFormat), MSCompatible(false), InputFileIndex(0) { for (const auto &ExtraDep : Opts.ExtraDeps) { if (addDependency(ExtraDep.first)) ++InputFileIndex; @@ -235,6 +235,8 @@ void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) { if (AddMissingHeaderDeps) PP.SetSuppressIncludeNotFoundError(true); + MSCompatible = PP.getLangOpts().MicrosoftExt; + DependencyCollector::attachToPreprocessor(PP); } @@ -312,11 +314,20 @@ void DependencyFileGenerator::finishedMainFile(DiagnosticsEngine &Diags) { /// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info, /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx /// for Windows file-naming info. -static void PrintFilename(raw_ostream &OS, StringRef Filename, - DependencyOutputFormat OutputFormat) { - // Convert filename to platform native path +/// +/// Whether backslashes in the filename are treated as path separators or +/// ordinary characters depends on whether the Clang invocation is MS-compatible +/// (-fms-compatibility). If it is, backslashes are treated as path separators, +/// and are converted to the native path separator (backslash on Windows, +/// forward slash on other platforms); if not, backslashes are treated as +/// ordinary characters, and are not converted. +void DependencyFileGenerator::outputDependencyFilename( + raw_ostream &OS, StringRef Filename) const { llvm::SmallString<256> NativePath; - llvm::sys::path::native(Filename.str(), NativePath); + if (MSCompatible) + llvm::sys::path::native(Filename.str(), NativePath); + else + NativePath = Filename; if (OutputFormat == DependencyOutputFormat::NMake) { // Add quotes if needed. These are the characters listed as "special" to @@ -400,7 +411,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) { Columns = 2; } OS << ' '; - PrintFilename(OS, File, OutputFormat); + outputDependencyFilename(OS, File); Columns += N + 1; } OS << '\n'; @@ -411,7 +422,7 @@ void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) { for (auto I = Files.begin(), E = Files.end(); I != E; ++I) { if (Index++ == InputFileIndex) continue; - PrintFilename(OS, *I, OutputFormat); + outputDependencyFilename(OS, *I); OS << ":\n"; } } diff --git a/clang/test/Frontend/dependency-gen-posix-ms-compatible.c b/clang/test/Frontend/dependency-gen-posix-ms-compatible.c new file mode 100644 index 0000000000000..208240b03a844 --- /dev/null +++ b/clang/test/Frontend/dependency-gen-posix-ms-compatible.c @@ -0,0 +1,17 @@ +// REQUIRES: !system-windows +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/include/foo +// RUN: echo > %t.dir/include/foo/bar.h +// RUN: echo > %t.dir/include/foo\\bar.h + +// RUN: %clang -MD -MF - %s -fsyntax-only -fms-compatibility -I %t.dir/include | FileCheck -check-prefix=CHECK-ONE %s +// CHECK-ONE: foo/bar.h +// CHECK-ONE-NOT: foo\bar.h +// CHECK-ONE-NOT: foo\\bar.h + +// RUN: %clang -MD -MF - %s -fsyntax-only -fno-ms-compatibility -I %t.dir/include | FileCheck -check-prefix=CHECK-TWO %s +// CHECK-TWO: foo\bar.h +// CHECK-TWO-NOT: foo/bar.h +// CHECK-TWO-NOT: foo\\bar.h + +#include "foo\bar.h"