Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -816,7 +816,9 @@ Flag <["-"], "fno-implicit-modules">, Group, Flags<[DriverOption, CC1Option]>; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group, Flags<[CC1Option]>; - +def FILE__prefix_to_remove : Joined<["-"], "ffile-macro-prefix-to-remove=">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"prefix to be removed from expanded string of __FILE__ macro. __ALL_DIR__ removes all dir">; def fmudflapth : Flag<["-"], "fmudflapth">, Group; def fmudflap : Flag<["-"], "fmudflap">, Group; def fnested_functions : Flag<["-"], "fnested-functions">, Group; Index: include/clang/Lex/Preprocessor.h =================================================================== --- include/clang/Lex/Preprocessor.h +++ include/clang/Lex/Preprocessor.h @@ -119,6 +119,7 @@ /// Identifiers for builtin macros and other builtins. IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__ + IdentifierInfo *Ident__CLANG_FILE_BASENAME__; // __FILE_BASENAME__ IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__ IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__ IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__ Index: include/clang/Lex/PreprocessorOptions.h =================================================================== --- include/clang/Lex/PreprocessorOptions.h +++ include/clang/Lex/PreprocessorOptions.h @@ -108,15 +108,20 @@ /// the buffers associated with remapped files. /// /// This flag defaults to false; it can be set true only through direct - /// manipulation of the compiler invocation object, in cases where the + /// manipulation of the compiler invocation object, in cases where the /// compiler invocation and its buffers will be reused. bool RetainRemappedFileBuffers; - + + /// \brief This string will be used in expanding __FILE__ macro. If it + // matches the prefix of __FILE__, the mathed part won't be expanded. + // If it is "__ALL_DIR__", only the basename will be expanded. + std::string __FILE__PrefixToRemove; + /// \brief The Objective-C++ ARC standard library that we should support, /// by providing appropriate definitions to retrofit the standard library /// with support for lifetime-qualified pointers. ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary; - + /// \brief Records the set of modules class FailedModulesSet : public RefCountedBase { llvm::StringSet<> Failed; @@ -140,14 +145,12 @@ IntrusiveRefCntPtr FailedModules; public: - PreprocessorOptions() : UsePredefines(true), DetailedRecord(false), - DisablePCHValidation(false), - AllowPCHWithCompilerErrors(false), - DumpDeserializedPCHDecls(false), - PrecompiledPreambleBytes(0, true), - RemappedFilesKeepOriginalName(true), - RetainRemappedFileBuffers(false), - ObjCXXARCStandardLibrary(ARCXX_nolib) { } + PreprocessorOptions() + : UsePredefines(true), DetailedRecord(false), DisablePCHValidation(false), + AllowPCHWithCompilerErrors(false), DumpDeserializedPCHDecls(false), + PrecompiledPreambleBytes(0, true), RemappedFilesKeepOriginalName(true), + RetainRemappedFileBuffers(false), __FILE__PrefixToRemove(""), + ObjCXXARCStandardLibrary(ARCXX_nolib) {} void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); } void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); } Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -567,6 +567,14 @@ // Add CUDA include arguments, if needed. if (types::isCuda(Inputs[0].getType())) getToolChain().AddCudaIncludeArgs(Args, CmdArgs); + + // Add FILE macro prefix removing arguments. + if (const Arg *A = Args.getLastArg(options::OPT_FILE__prefix_to_remove)) { + StringRef Value = A->getValue(); + if (!Value.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-ffile-macro-prefix-to-remove=") + Value)); + } } // FIXME: Move to target hook. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2031,6 +2031,8 @@ else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } + if (Arg *A = Args.getLastArg(OPT_FILE__prefix_to_remove)) + Opts.__FILE__PrefixToRemove = A->getValue(); } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, Index: lib/Lex/PPMacroExpansion.cpp =================================================================== --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -22,12 +21,15 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/MacroArgs.h" #include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Config/llvm-config.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -292,6 +294,8 @@ void Preprocessor::RegisterBuiltinMacros() { Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__"); Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__"); + Ident__CLANG_FILE_BASENAME__ = + RegisterBuiltinMacro(*this, "__CLANG_FILE_BASENAME__"); Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__"); Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__"); Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__"); @@ -1509,7 +1513,8 @@ // __LINE__ expands to a simple numeric value. OS << (PLoc.isValid()? PLoc.getLine() : 1); Tok.setKind(tok::numeric_constant); - } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { + } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__ || + II == Ident__CLANG_FILE_BASENAME__) { // C99 6.10.8: "__FILE__: The presumed name of the current source file (a // character string literal)". This can be affected by #line. PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); @@ -1522,7 +1527,6 @@ PLoc = SourceMgr.getPresumedLoc(NextLoc); if (PLoc.isInvalid()) break; - NextLoc = PLoc.getIncludeLoc(); } } @@ -1530,7 +1534,23 @@ // Escape this filename. Turn '\' -> '\\' '"' -> '\"' SmallString<128> FN; if (PLoc.isValid()) { - FN += PLoc.getFilename(); + const std::string &PrefixToRemove = + getPreprocessorOpts().__FILE__PrefixToRemove; + StringRef Filename(PLoc.getFilename()); + + if (II == Ident__CLANG_FILE_BASENAME__) + FN += llvm::sys::path::filename(Filename); + else if (II == Ident__FILE__ && !PrefixToRemove.empty()) { + if (PrefixToRemove == "__ALL_DIR__") { + FN += llvm::sys::path::filename(Filename); + } + else if (Filename.find(PrefixToRemove) == 0) + FN += Filename.substr(PrefixToRemove.size()); + else + FN += Filename; + } else + FN += Filename; + Lexer::Stringify(FN); OS << '"' << FN << '"'; } Index: test/Lexer/file_basename.c =================================================================== --- /dev/null +++ test/Lexer/file_basename.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -E %s | FileCheck %s --check-prefix=ALL --check-prefix=DEFAULT + +// RUN: %clang_cc1 -E -ffile-macro-prefix-to-remove=__ALL_DIR__ %s | FileCheck %s --check-prefix=ALL --check-prefix=NO-DIR +// RUN:%clang -E -ffile-macro-prefix-to-remove=__ALL_DIR__ %s | FileCheck %s --check-prefix=ALL --check-prefix=NO-DIR + +// RUN: %clang_cc1 -E -ffile-macro-prefix-to-remove=%s %s | FileCheck %s --check-prefix=ALL --check-prefix=REMOVE-ALL +// RUN: %clang -E -ffile-macro-prefix-to-remove=%s %s | FileCheck %s --check-prefix=ALL --check-prefix=REMOVE-ALL + +// RUN: %clang_cc1 -E -ffile-macro-prefix-to-remove=%s.xyz %s | FileCheck %s --check-prefix=ALL --check-prefix=MISMATCH +// RUN: %clang -E -ffile-macro-prefix-to-remove= %s | FileCheck %s --check-prefix=ALL --check-prefix=MISMATCH + +const char *filename (const char *name) { + // ALL: static const char this_file_basename[] = "file_basename.c"; + static const char this_file_basename[] = __CLANG_FILE_BASENAME__; + // DEFAULT: static const char this_file[] = "{{.*}}/Lexer/file_basename.c"; + // NO-DIR: static const char this_file[] = "file_basename.c"; + // REMOVE-ALL: static const char this_file[] = ""; + // MISMATCH: static const char this_file[] = "{{.*}}/Lexer/file_basename.c"; + static const char this_file[] = __FILE__; + return this_file; +}