From 91a68a7abe24a6925ea1f90105694c08917e21c8 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 26 Feb 2015 00:17:25 +0000 Subject: [PATCH] Add -fuse-line-directive flag to control usage of #line with -E Currently -fms-extensions controls this behavior, which doesn't make much sense. It means we can't identify what is and isn't a system header when compiling our own preprocessed output, because #line doesn't represent this information. If someone is feeding Clang's preprocessed output to another compiler, they can use this flag. Fixes PR20553. Reviewers: rsmith Differential Revision: http://reviews.llvm.org/D5217 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230587 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/Options.td | 4 ++++ .../Frontend/PreprocessorOutputOptions.h | 2 ++ lib/Driver/Tools.cpp | 5 +++++ lib/Frontend/CompilerInvocation.cpp | 1 + lib/Frontend/PrintPreprocessedOutput.cpp | 22 ++++++++----------- lib/Frontend/Rewrite/InclusionRewriter.cpp | 20 ++++++++--------- test/Frontend/rewrite-includes-line-markers.c | 22 +++++++++++++++++++ test/Lexer/pragma-operators.cpp | 2 +- test/Preprocessor/_Pragma-location.c | 12 +++++----- 9 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 test/Frontend/rewrite-includes-line-markers.c diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index dae80f9702..4e17cee799 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -596,6 +596,10 @@ def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">, Group, Flags<[DriverOption]>; +def fuse_line_directives : Flag<["-"], "fuse-line-directives">, Group, + Flags<[CC1Option]>; +def fno_use_line_directives : Flag<["-"], "fno-use-line-directives">, Group; + def ffreestanding : Flag<["-"], "ffreestanding">, Group, Flags<[CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group, Flags<[CC1Option]>, diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h index e273dd613d..f86c49039e 100644 --- a/include/clang/Frontend/PreprocessorOutputOptions.h +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -19,6 +19,7 @@ public: unsigned ShowCPP : 1; ///< Print normal preprocessed output. unsigned ShowComments : 1; ///< Show comments. unsigned ShowLineMarkers : 1; ///< Show \#line markers. + unsigned UseLineDirectives : 1; ///< Use \#line instead of GCC-style \# N. unsigned ShowMacroComments : 1; ///< Show comments, even in macros. unsigned ShowMacros : 1; ///< Print macro definitions. unsigned RewriteIncludes : 1; ///< Preprocess include directives only. @@ -28,6 +29,7 @@ public: ShowCPP = 0; ShowComments = 0; ShowLineMarkers = 1; + UseLineDirectives = 0; ShowMacroComments = 0; ShowMacros = 0; RewriteIncludes = 0; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index c04737544f..b0e581bc78 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -4067,6 +4067,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, IsWindowsMSVC)) CmdArgs.push_back("-fms-extensions"); + // -fno-use-line-directives is default. + if (Args.hasFlag(options::OPT_fuse_line_directives, + options::OPT_fno_use_line_directives, false)) + CmdArgs.push_back("-fuse-line-directives"); + // -fms-compatibility=0 is default. if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index ef76cbfebd..2098dec172 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1826,6 +1826,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, Opts.ShowMacroComments = Args.hasArg(OPT_CC); Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes); + Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives); } static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 7c1d9a5688..6507f8e4b6 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -94,14 +94,14 @@ private: bool Initialized; bool DisableLineMarkers; bool DumpDefines; - bool UseLineDirective; + bool UseLineDirectives; bool IsFirstFileEntered; public: - PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, - bool lineMarkers, bool defines) - : PP(pp), SM(PP.getSourceManager()), - ConcatInfo(PP), OS(os), DisableLineMarkers(lineMarkers), - DumpDefines(defines) { + PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers, + bool defines, bool UseLineDirectives) + : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), + DisableLineMarkers(lineMarkers), DumpDefines(defines), + UseLineDirectives(UseLineDirectives) { CurLine = 0; CurFilename += ""; EmittedTokensOnThisLine = false; @@ -109,9 +109,6 @@ public: FileType = SrcMgr::C_User; Initialized = false; IsFirstFileEntered = false; - - // If we're in microsoft mode, use normal #line instead of line markers. - UseLineDirective = PP.getLangOpts().MicrosoftExt; } void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } @@ -183,7 +180,7 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); // Emit #line directives or GNU line markers depending on what mode we're in. - if (UseLineDirective) { + if (UseLineDirectives) { OS << "#line" << ' ' << LineNo << ' ' << '"'; OS.write_escaped(CurFilename); OS << '"'; @@ -719,9 +716,8 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, // to -C or -CC. PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); - PrintPPOutputPPCallbacks *Callbacks = - new PrintPPOutputPPCallbacks(PP, *OS, !Opts.ShowLineMarkers, - Opts.ShowMacros); + PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( + PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.UseLineDirectives); PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks)); PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks)); PP.AddPragmaHandler("clang", diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index 140055735a..5cc503ad35 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -43,14 +43,15 @@ class InclusionRewriter : public PPCallbacks { StringRef MainEOL; ///< The line ending marker to use. const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines. bool ShowLineMarkers; ///< Show #line markers. - bool UseLineDirective; ///< Use of line directives or line markers. + bool UseLineDirectives; ///< Use of line directives or line markers. typedef std::map FileChangeMap; FileChangeMap FileChanges; ///< Tracks which files were included where. /// Used transitively for building up the FileChanges mapping over the /// various \c PPCallbacks callbacks. FileChangeMap::iterator LastInsertedFileChange; public: - InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers); + InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, + bool UseLineDirectives); bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType); void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) { PredefinesBuffer = Buf; @@ -89,13 +90,12 @@ private: /// Initializes an InclusionRewriter with a \p PP source and \p OS destination. InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS, - bool ShowLineMarkers) + bool ShowLineMarkers, + bool UseLineDirectives) : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"), PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers), - LastInsertedFileChange(FileChanges.end()) { - // If we're in microsoft mode, use normal #line instead of line markers. - UseLineDirective = PP.getLangOpts().MicrosoftExt; -} + LastInsertedFileChange(FileChanges.end()), + UseLineDirectives(UseLineDirectives) {} /// Write appropriate line information as either #line directives or GNU line /// markers depending on what mode we're in, including the \p Filename and @@ -106,7 +106,7 @@ void InclusionRewriter::WriteLineInfo(const char *Filename, int Line, StringRef Extra) { if (!ShowLineMarkers) return; - if (UseLineDirective) { + if (UseLineDirectives) { OS << "#line" << ' ' << Line << ' ' << '"'; OS.write_escaped(Filename); OS << '"'; @@ -561,8 +561,8 @@ bool InclusionRewriter::Process(FileID FileId, void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts) { SourceManager &SM = PP.getSourceManager(); - InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS, - Opts.ShowLineMarkers); + InclusionRewriter *Rewrite = new InclusionRewriter( + PP, *OS, Opts.ShowLineMarkers, Opts.UseLineDirectives); Rewrite->detectMainFileEOL(); PP.addPPCallbacks(std::unique_ptr(Rewrite)); diff --git a/test/Frontend/rewrite-includes-line-markers.c b/test/Frontend/rewrite-includes-line-markers.c new file mode 100644 index 0000000000..14692a19e9 --- /dev/null +++ b/test/Frontend/rewrite-includes-line-markers.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -E -frewrite-includes -I %S/Inputs %s | FileCheck %s --check-prefix=GNU +// RUN: %clang_cc1 -E -frewrite-includes -fuse-line-directives -I %S/Inputs %s | FileCheck %s --check-prefix=LINE +#include "test.h" +int f() { return x; } + +// GNU: {{^}}# 1 "{{.*}}rewrite-includes-line-markers.c" +// GNU: {{^}}#include "test.h" +// GNU: {{^}}# 1 "{{.*}}test.h" +// GNU: {{^}}#include "test2.h" +// GNU: {{^}}# 1 "{{.*}}test2.h" +// GNU: {{^}}int x; +// GNU: {{^}}# 4 "{{.*}}rewrite-includes-line-markers.c" 2 +// GNU: {{^}}int f() { return x; } + +// LINE: {{^}}#line 1 "{{.*}}rewrite-includes-line-markers.c" +// LINE: {{^}}#include "test.h" +// LINE: {{^}}#line 1 "{{.*}}test.h" +// LINE: {{^}}#include "test2.h" +// LINE: {{^}}#line 1 "{{.*}}test2.h" +// LINE: {{^}}int x; +// LINE: {{^}}#line 4 "{{.*}}rewrite-includes-line-markers.c" +// LINE: {{^}}int f() { return x; } diff --git a/test/Lexer/pragma-operators.cpp b/test/Lexer/pragma-operators.cpp index 7270f1eed2..4d288c9372 100644 --- a/test/Lexer/pragma-operators.cpp +++ b/test/Lexer/pragma-operators.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fms-extensions -std=c++11 -E %s | FileCheck %s +// RUN: %clang_cc1 -fms-extensions -std=c++11 -E %s -fuse-line-directives | FileCheck %s // Test that we properly expand the C99 _Pragma and Microsoft __pragma // into #pragma directives, with newlines where needed. diff --git a/test/Preprocessor/_Pragma-location.c b/test/Preprocessor/_Pragma-location.c index 5031ee4edc..a523c26b01 100644 --- a/test/Preprocessor/_Pragma-location.c +++ b/test/Preprocessor/_Pragma-location.c @@ -10,9 +10,9 @@ push_p push_p _Pragma("pack(push)") __pragma(pack(push)) // CHECK: #pragma pack(push) -// CHECK-NEXT: #line 11 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 11 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma pack(push) -// CHECK-NEXT: #line 11 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 11 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma pack(push) @@ -31,17 +31,17 @@ void test () { // CHECK: void test () { // CHECK-NEXT: 1; -// CHECK-NEXT: #line 24 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 24 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma clang diagnostic push // CHECK-NEXT: #pragma clang diagnostic ignored "-Wformat-extra-args" // CHECK-NEXT: #pragma clang diagnostic pop // CHECK: 2; -// CHECK-NEXT: #line 28 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 28 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma clang diagnostic push -// CHECK-NEXT: #line 28 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 28 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma clang diagnostic ignored "-Wformat-extra-args" // CHECK-NEXT: 3; -// CHECK-NEXT: #line 29 "{{.*}}_Pragma-location.c" +// CHECK-NEXT: # 29 "{{.*}}_Pragma-location.c" // CHECK-NEXT: #pragma clang diagnostic pop // CHECK-NEXT: } -- 2.40.0