From fb40328fb184e12d521a3d0179779bf29390b4b7 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 16 Jun 2017 20:13:39 +0000 Subject: [PATCH] [PR33394] Avoid lexing editor placeholders when Clang is used only for preprocessing MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit r300667 added support for editor placeholder to Clang. That commit didn’t take into account that users who use Clang for preprocessing only (-E) will get the "editor placeholder in source file" error when preprocessing their source (PR33394). This commit ensures that Clang doesn't lex editor placeholders when running a preprocessor only action. rdar://32718000 Differential Revision: https://reviews.llvm.org/D34256 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305576 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/PreprocessorOptions.h | 4 + lib/Frontend/CompilerInvocation.cpp | 94 +++++++++++-------- lib/Lex/Lexer.cpp | 3 +- .../Frontend/pp-only-no-editor-placeholders.c | 4 + 4 files changed, 64 insertions(+), 41 deletions(-) create mode 100644 test/Frontend/pp-only-no-editor-placeholders.c diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index f536be8d8e..024db926eb 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -98,6 +98,9 @@ public: /// When enabled, preprocessor is in a mode for parsing a single file only. bool SingleFileParseMode = false; + /// When enabled, the preprocessor will construct editor placeholder tokens. + bool LexEditorPlaceholders = true; + /// \brief True if the SourceManager should report the original file name for /// contents of files that were remapped to other files. Defaults to true. bool RemappedFilesKeepOriginalName; @@ -185,6 +188,7 @@ public: ImplicitPTHInclude.clear(); TokenCache.clear(); SingleFileParseMode = false; + LexEditorPlaceholders = true; RetainRemappedFileBuffers = true; PrecompiledPreambleBytes.first = 0; PrecompiledPreambleBytes.second = 0; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 1667af2d12..e6feaf7447 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2379,9 +2379,51 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); } +static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { + switch (Action) { + case frontend::ASTDeclList: + case frontend::ASTDump: + case frontend::ASTPrint: + case frontend::ASTView: + case frontend::EmitAssembly: + case frontend::EmitBC: + case frontend::EmitHTML: + case frontend::EmitLLVM: + case frontend::EmitLLVMOnly: + case frontend::EmitCodeGenOnly: + case frontend::EmitObj: + case frontend::FixIt: + case frontend::GenerateModule: + case frontend::GenerateModuleInterface: + case frontend::GeneratePCH: + case frontend::GeneratePTH: + case frontend::ParseSyntaxOnly: + case frontend::ModuleFileInfo: + case frontend::VerifyPCH: + case frontend::PluginAction: + case frontend::PrintDeclContext: + case frontend::RewriteObjC: + case frontend::RewriteTest: + case frontend::RunAnalysis: + case frontend::MigrateSource: + return false; + + case frontend::DumpRawTokens: + case frontend::DumpTokens: + case frontend::InitOnly: + case frontend::PrintPreamble: + case frontend::PrintPreprocessedInput: + case frontend::RewriteMacros: + case frontend::RunPreprocessorOnly: + return true; + } + llvm_unreachable("invalid frontend action"); +} + static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, FileManager &FileMgr, - DiagnosticsEngine &Diags) { + DiagnosticsEngine &Diags, + frontend::ActionKind Action) { using namespace options; Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); @@ -2454,6 +2496,12 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } + + // Always avoid lexing editor placeholders when we're just running the + // preprocessor as we never want to emit the + // "editor placeholder in source file" error in PP only mode. + if (isStrictlyPreprocessorAction(Action)) + Opts.LexEditorPlaceholders = false; } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -2461,45 +2509,10 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, frontend::ActionKind Action) { using namespace options; - switch (Action) { - case frontend::ASTDeclList: - case frontend::ASTDump: - case frontend::ASTPrint: - case frontend::ASTView: - case frontend::EmitAssembly: - case frontend::EmitBC: - case frontend::EmitHTML: - case frontend::EmitLLVM: - case frontend::EmitLLVMOnly: - case frontend::EmitCodeGenOnly: - case frontend::EmitObj: - case frontend::FixIt: - case frontend::GenerateModule: - case frontend::GenerateModuleInterface: - case frontend::GeneratePCH: - case frontend::GeneratePTH: - case frontend::ParseSyntaxOnly: - case frontend::ModuleFileInfo: - case frontend::VerifyPCH: - case frontend::PluginAction: - case frontend::PrintDeclContext: - case frontend::RewriteObjC: - case frontend::RewriteTest: - case frontend::RunAnalysis: - case frontend::MigrateSource: - Opts.ShowCPP = 0; - break; - - case frontend::DumpRawTokens: - case frontend::DumpTokens: - case frontend::InitOnly: - case frontend::PrintPreamble: - case frontend::PrintPreprocessedInput: - case frontend::RewriteMacros: - case frontend::RunPreprocessorOnly: + if (isStrictlyPreprocessorAction(Action)) Opts.ShowCPP = !Args.hasArg(OPT_dM); - break; - } + else + Opts.ShowCPP = 0; Opts.ShowComments = Args.hasArg(OPT_C); Opts.ShowLineMarkers = !Args.hasArg(OPT_P); @@ -2626,7 +2639,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, // ParsePreprocessorArgs and remove the FileManager // parameters from the function and the "FileManager.h" #include. FileManager FileMgr(Res.getFileSystemOpts()); - ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags); + ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags, + Res.getFrontendOpts().ProgramAction); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 447ff212f0..012189aa6f 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -19,6 +19,7 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Compiler.h" @@ -2750,7 +2751,7 @@ static const char *findPlaceholderEnd(const char *CurPtr, bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) { assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!"); - if (!PP || LexingRawMode) + if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders || LexingRawMode) return false; const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd); if (!End) diff --git a/test/Frontend/pp-only-no-editor-placeholders.c b/test/Frontend/pp-only-no-editor-placeholders.c new file mode 100644 index 0000000000..515d9893fd --- /dev/null +++ b/test/Frontend/pp-only-no-editor-placeholders.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -E -verify -o - %s | FileCheck %s +// expected-no-diagnostics + +<#placeholder#>; // CHECK: <#placeholder#>; -- 2.50.1