[PR33394] Avoid lexing editor placeholders when Clang is used only

for preprocessing

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
This commit is contained in:
Alex Lorenz 2017-06-16 20:13:39 +00:00
parent 2d736e0181
commit fb40328fb1
4 changed files with 64 additions and 41 deletions

View File

@ -98,6 +98,9 @@ public:
/// When enabled, preprocessor is in a mode for parsing a single file only. /// When enabled, preprocessor is in a mode for parsing a single file only.
bool SingleFileParseMode = false; 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 /// \brief True if the SourceManager should report the original file name for
/// contents of files that were remapped to other files. Defaults to true. /// contents of files that were remapped to other files. Defaults to true.
bool RemappedFilesKeepOriginalName; bool RemappedFilesKeepOriginalName;
@ -185,6 +188,7 @@ public:
ImplicitPTHInclude.clear(); ImplicitPTHInclude.clear();
TokenCache.clear(); TokenCache.clear();
SingleFileParseMode = false; SingleFileParseMode = false;
LexEditorPlaceholders = true;
RetainRemappedFileBuffers = true; RetainRemappedFileBuffers = true;
PrecompiledPreambleBytes.first = 0; PrecompiledPreambleBytes.first = 0;
PrecompiledPreambleBytes.second = 0; PrecompiledPreambleBytes.second = 0;

View File

@ -2379,9 +2379,51 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); 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, static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
FileManager &FileMgr, FileManager &FileMgr,
DiagnosticsEngine &Diags) { DiagnosticsEngine &Diags,
frontend::ActionKind Action) {
using namespace options; using namespace options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
@ -2454,6 +2496,12 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
else else
Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; 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, static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
@ -2461,45 +2509,10 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
frontend::ActionKind Action) { frontend::ActionKind Action) {
using namespace options; using namespace options;
switch (Action) { if (isStrictlyPreprocessorAction(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:
Opts.ShowCPP = !Args.hasArg(OPT_dM); Opts.ShowCPP = !Args.hasArg(OPT_dM);
break; else
} Opts.ShowCPP = 0;
Opts.ShowComments = Args.hasArg(OPT_C); Opts.ShowComments = Args.hasArg(OPT_C);
Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
@ -2626,7 +2639,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
// ParsePreprocessorArgs and remove the FileManager // ParsePreprocessorArgs and remove the FileManager
// parameters from the function and the "FileManager.h" #include. // parameters from the function and the "FileManager.h" #include.
FileManager FileMgr(Res.getFileSystemOpts()); FileManager FileMgr(Res.getFileSystemOpts());
ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags); ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags,
Res.getFrontendOpts().ProgramAction);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args,
Res.getFrontendOpts().ProgramAction); Res.getFrontendOpts().ProgramAction);

View File

@ -19,6 +19,7 @@
#include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LexDiagnostic.h"
#include "clang/Lex/LiteralSupport.h" #include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h" #include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.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) { bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) {
assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!"); assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!");
if (!PP || LexingRawMode) if (!PP || !PP->getPreprocessorOpts().LexEditorPlaceholders || LexingRawMode)
return false; return false;
const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd); const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd);
if (!End) if (!End)

View File

@ -0,0 +1,4 @@
// RUN: %clang_cc1 -E -verify -o - %s | FileCheck %s
// expected-no-diagnostics
<#placeholder#>; // CHECK: <#placeholder#>;