[cfe-dev] Help rewriting the __FILE__ macro

Erik Cederstrand erik at cederstrand.dk
Tue May 22 11:40:44 PDT 2012


Hi folks,

I'm trying to get the FreeBSD source tree to produce two identical binaries for two builds with the same source revision. Currently, this is not the case, and one of the reasons is that the value of __FILE__ is sometimes stored in the binary. This is a problem if the source location or location of temporary object files is not the same between the two builds.

Ideally, what I want is for __FILE__ to expand to a path relative to the location of the root of my source tree instead of an absolute path on the file system, i.e. src/foo/bar.c instead of /home/erik/freebsd/head/src/foo/bar.c

This has been implemented as an "-iremap=src:dst" option for GCC (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47047) and applied to GCC in NetBSD (http://www.mail-archive.com/source-changes-full@netbsd.org/msg08590.html) by Joerg Sonnenberger. 'src' is meant to be the prefix and 'dst' the replacement.

I've made an attempt to add a similar flag for Clang, but I'm a C++ and Clang novice and got lost somewhere between the driver accepting the option and the preprocessor rewriting the __FILE__ macro. I'm wondering if someone could lend me a hand completing the attached patch. Thanks!

Thanks,
Erik Cederstrand


Index: llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h
===================================================================
--- llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h	(revision 235777)
+++ llvm/tools/clang/include/clang/Frontend/PreprocessorOptions.h	(working copy)
@@ -97,6 +97,10 @@
  /// contents of files that were remapped to other files. Defaults to true.
  bool RemappedFilesKeepOriginalName;

+  /// \brief If given, the SourceManager should substitute the file name prefix
+  /// first with second when expanding the __FILE__ macro.
+  std:pair<string, string> FilenamePrefixSubstitute;
+
  /// \brief The set of file remappings, which take existing files on
  /// the system (the first part of each pair) and gives them the
  /// contents of other files on the system (the second part of each
@@ -172,6 +176,7 @@
                          DumpDeserializedPCHDecls(false),
                          PrecompiledPreambleBytes(0, true),
                          RemappedFilesKeepOriginalName(true),
+                          FilenamePrefixSubstitute("", ""),
                          RetainRemappedFileBuffers(false),
                          ObjCXXARCStandardLibrary(ARCXX_nolib) { }

Index: llvm/tools/clang/include/clang/Frontend/ASTUnit.h
===================================================================
--- llvm/tools/clang/include/clang/Frontend/ASTUnit.h	(revision 235777)
+++ llvm/tools/clang/include/clang/Frontend/ASTUnit.h	(working copy)
@@ -727,6 +727,7 @@
                                      RemappedFile *RemappedFiles = 0,
                                      unsigned NumRemappedFiles = 0,
                                      bool RemappedFilesKeepOriginalName = true,
+                                      std::pair <string, string> FilenamePrefixSubstitute("", ""),
                                      bool PrecompilePreamble = false,
                                      TranslationUnitKind TUKind = TU_Complete,
                                      bool CacheCodeCompletionResults = false,
Index: llvm/tools/clang/include/clang/Basic/SourceManager.h
===================================================================
--- llvm/tools/clang/include/clang/Basic/SourceManager.h	(revision 235777)
+++ llvm/tools/clang/include/clang/Basic/SourceManager.h	(working copy)
@@ -497,6 +497,10 @@
  /// non-null, FileEntry pointers.
  llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos;

+  /// \brief A filename prefix of path src will be replaced with prefix dst.
+  /// This allows the __FILE__ macro to return relative paths.
+  std::pair<string, string> PLocPrefixSubstitute;
+
  /// \brief True if the ContentCache for files that are overriden by other
  /// files, should report the original file name. Defaults to true.
  bool OverridenFilesKeepOriginalName;
Index: llvm/tools/clang/include/clang/Driver/Options.td
===================================================================
--- llvm/tools/clang/include/clang/Driver/Options.td	(revision 235777)
+++ llvm/tools/clang/include/clang/Driver/Options.td	(working copy)
@@ -582,6 +582,7 @@
def integrated_as : Flag<"-integrated-as">, Flags<[DriverOption]>;
def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>;
def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>;
+def iremap_EQ : Joined<"-iremap=">, Group<clang_i_Group>;
def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>;
def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>;
def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>;
Index: llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp
===================================================================
--- llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp	(revision 235777)
+++ llvm/tools/clang/lib/Lex/PPMacroExpansion.cpp	(working copy)
@@ -952,7 +952,13 @@
    if (PLoc.isValid()) {
      FN += PLoc.getFilename();
      Lexer::Stringify(FN);
-      OS << '"' << FN.str() << '"';
+      string src = SourceMgr.PLocPrefixSubstitute.first;
+      string dst = SourceMgr.PLocPrefixSubstitute.second;
+      if (FN.str().find(src) == 0) {
+        OS << '"' << FN.str().replace(0, src.length(), dst) << '"';
+      } else {
+        OS << '"' << FN.str() << '"';
+      }
    }
    Tok.setKind(tok::string_literal);
  } else if (II == Ident__DATE__) {
Index: llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp
===================================================================
--- llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp	(revision 235777)
+++ llvm/tools/clang/lib/Frontend/InitPreprocessor.cpp	(working copy)
@@ -667,6 +667,8 @@

  SourceMgr.setOverridenFilesKeepOriginalName(
                                        InitOpts.RemappedFilesKeepOriginalName);
+
+  SourceMgr.PLocPrefixSubstitute = InitOpts.FilenamePrefixSubstitute;
}

/// InitializePreprocessor - Initialize the preprocessor getting it and the
Index: llvm/tools/clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- llvm/tools/clang/lib/Frontend/ASTUnit.cpp	(revision 235777)
+++ llvm/tools/clang/lib/Frontend/ASTUnit.cpp	(working copy)
@@ -1880,6 +1880,7 @@
                                      RemappedFile *RemappedFiles,
                                      unsigned NumRemappedFiles,
                                      bool RemappedFilesKeepOriginalName,
+                                      std::pair <string, string> FilenamePrefixSubstitute,
                                      bool PrecompilePreamble,
                                      TranslationUnitKind TUKind,
                                      bool CacheCodeCompletionResults,
@@ -1924,7 +1925,8 @@
  PreprocessorOptions &PPOpts = CI->getPreprocessorOpts();
  PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName;
  PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors;
-  
+  PPOpts.FilenamePrefixSubstitute = FilenamePrefixSubstitute;
+
  // Override the resources path.
  CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;




More information about the cfe-dev mailing list