Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -825,6 +825,12 @@ 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">; +def FILE_basename_only : Flag <["-"], "ffile-macro-basename-only">, + Group, Flags<[DriverOption, CC1Option]>, + HelpText<"only expand the basename of __FILE__ macro.">; def fmudflapth : Flag<["-"], "fmudflapth">, Group; def fmudflap : Flag<["-"], "fmudflap">, Group; def fnested_functions : Flag<["-"], "fnested-functions">, Group; Index: include/clang/Lex/PreprocessorOptions.h =================================================================== --- include/clang/Lex/PreprocessorOptions.h +++ include/clang/Lex/PreprocessorOptions.h @@ -108,15 +108,23 @@ /// 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 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 This string will be used in expanding __FILE__ macro. If it + /// matches the prefix of __FILE__, the matched part won't be expanded. + std::string __FILE__PrefixToRemove; + + /// \brief This falgs defaults to false; If it is set to true, only the + /// basename part of __FILE__ will be expanded. + bool __FILE__BasenameOnly; + /// \brief Records the set of modules class FailedModulesSet : public RefCountedBase { llvm::StringSet<> Failed; @@ -130,7 +138,7 @@ Failed.insert(module); } }; - + /// \brief The set of modules that failed to build. /// /// This pointer will be shared among all of the compiler instances created @@ -140,14 +148,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), ObjCXXARCStandardLibrary(ARCXX_nolib), + __FILE__PrefixToRemove(""), __FILE__BasenameOnly(false) {} void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); } void addMacroUndef(StringRef Name) { Macros.emplace_back(Name, true); } @@ -163,7 +169,7 @@ RemappedFiles.clear(); RemappedFileBuffers.clear(); } - + /// \brief Reset any options that are not considered when building a /// module. void resetNonModularOptions() { Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -570,6 +570,16 @@ // Add CUDA include arguments, if needed. if (types::isCuda(Inputs[0].getType())) getToolChain().AddCudaIncludeArgs(Args, CmdArgs); + + // Add FILE macro prefix removing arguments or basename only flags. + if (const Arg *A = Args.getLastArg(options::OPT_FILE_prefix_to_remove, + options::OPT_FILE_basename_only)) { + if (A->getOption().matches(options::OPT_FILE_basename_only)) + CmdArgs.push_back(Args.MakeArgString("-ffile-macro-basename-only")); + else if (!StringRef(A->getValue()).empty()) + CmdArgs.push_back(Args.MakeArgString( + Twine("-ffile-macro-prefix-to-remove=") + A->getValue())); + } } // FIXME: Move to target hook. Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2010,6 +2010,14 @@ else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } + + if (Arg *A = + Args.getLastArg(OPT_FILE_prefix_to_remove, OPT_FILE_basename_only)) { + if (A->getOption().matches(options::OPT_FILE_basename_only)) + Opts.__FILE__BasenameOnly = true; + else + 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 @@ -1595,7 +1597,7 @@ PLoc = SourceMgr.getPresumedLoc(NextLoc); if (PLoc.isInvalid()) break; - + NextLoc = PLoc.getIncludeLoc(); } } @@ -1603,7 +1605,18 @@ // Escape this filename. Turn '\' -> '\\' '"' -> '\"' SmallString<128> FN; if (PLoc.isValid()) { - FN += PLoc.getFilename(); + StringRef Filename(PLoc.getFilename()); + if (II == Ident__FILE__) { + const std::string &PrefixToRemove = + getPreprocessorOpts().__FILE__PrefixToRemove; + if (getPreprocessorOpts().__FILE__BasenameOnly) + FN += llvm::sys::path::filename(Filename); + else if (!PrefixToRemove.empty() && Filename.startswith(PrefixToRemove)) + FN += Filename.substr(PrefixToRemove.size()); + else + FN += Filename; + } else + FN += Filename; Lexer::Stringify(FN); OS << '"' << FN << '"'; }