Index: include/clang/Lex/PreprocessorOptions.h =================================================================== --- include/clang/Lex/PreprocessorOptions.h +++ include/clang/Lex/PreprocessorOptions.h @@ -98,6 +98,9 @@ /// 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 @@ ImplicitPTHInclude.clear(); TokenCache.clear(); SingleFileParseMode = false; + LexEditorPlaceholders = true; RetainRemappedFileBuffers = true; PrecompiledPreambleBytes.first = 0; PrecompiledPreambleBytes.second = 0; Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2379,9 +2379,51 @@ 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 @@ 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 @@ 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 @@ // 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); Index: lib/Lex/Lexer.cpp =================================================================== --- lib/Lex/Lexer.cpp +++ 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 @@ 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) Index: test/Frontend/pp-only-no-editor-placeholders.c =================================================================== --- /dev/null +++ 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#>;