]> granicus.if.org Git - clang/commitdiff
Add -fuse-line-directive flag to control usage of #line with -E
authorReid Kleckner <reid@kleckner.net>
Thu, 26 Feb 2015 00:17:25 +0000 (00:17 +0000)
committerReid Kleckner <reid@kleckner.net>
Thu, 26 Feb 2015 00:17:25 +0000 (00:17 +0000)
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
include/clang/Frontend/PreprocessorOutputOptions.h
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/PrintPreprocessedOutput.cpp
lib/Frontend/Rewrite/InclusionRewriter.cpp
test/Frontend/rewrite-includes-line-markers.c [new file with mode: 0644]
test/Lexer/pragma-operators.cpp
test/Preprocessor/_Pragma-location.c

index dae80f97027cf48e168cbc3b60d77b41c06973af..4e17cee7995a983c1445ffe79003383963d28b8f 100644 (file)
@@ -596,6 +596,10 @@ def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">,
                            Group<f_Group>,
                            Flags<[DriverOption]>;
 
+def fuse_line_directives : Flag<["-"], "fuse-line-directives">, Group<f_Group>,
+  Flags<[CC1Option]>;
+def fno_use_line_directives : Flag<["-"], "fno-use-line-directives">, Group<f_Group>;
+
 def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Assert that the compilation takes place in a freestanding environment">;
 def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>,
index e273dd613def8d2eb74d7d429f89a107d8534159..f86c49039ed275d955bd672e9893c858a2341032 100644 (file)
@@ -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;
index c04737544f2de377a6322339f425d4edcfe8b2b0..b0e581bc78bd69a930a6de688d4bb384427be4b5 100644 (file)
@@ -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,
index ef76cbfebd9dcf8a564c9a7324b15a095a53ae26..2098dec172926fe3a676f03d42f0f1856b00c750 100644 (file)
@@ -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) {
index 7c1d9a568831c24589071edcac7c0aa0dc8b8ed3..6507f8e4b66724237ea6990822d584ccf36a2e4f 100644 (file)
@@ -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 += "<uninit>";
     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",
index 140055735a99e99c5c02235db579fed03e7eb2a6..5cc503ad3540f8929cef3bcc71e286b772f70634 100644 (file)
@@ -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<unsigned, FileChange> 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<PPCallbacks>(Rewrite));
diff --git a/test/Frontend/rewrite-includes-line-markers.c b/test/Frontend/rewrite-includes-line-markers.c
new file mode 100644 (file)
index 0000000..14692a1
--- /dev/null
@@ -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; }
index 7270f1eed2033051662e024d33367b8244a424e5..4d288c9372d64108cc21839173509a6fb83c47b8 100644 (file)
@@ -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. <rdar://problem/8412013>
index 5031ee4edcc6d164e7829250f5d380c7bebe8c02..a523c26b01d02a0f0292b3214719eddc62276d43 100644 (file)
@@ -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: }