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

llvm-svn: 230587
This commit is contained in:
Reid Kleckner 2015-02-26 00:17:25 +00:00
parent ebdfc00995
commit 1df0fea593
9 changed files with 60 additions and 30 deletions

View 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]>,

View 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;

View 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,

View 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) {

View 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",

View 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));

View File

@ -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; }

View 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>

View 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: }