elsteveogrande updated this revision to Diff 73224.
elsteveogrande added a comment.

Updated to actually use the include token's text, not a hardcoded `#include`.  
Updated unit test to expect the right word here.


https://reviews.llvm.org/D25153

Files:
  include/clang/Driver/Options.td
  include/clang/Frontend/PreprocessorOutputOptions.h
  lib/Frontend/CompilerInvocation.cpp
  lib/Frontend/PrintPreprocessedOutput.cpp
  test/Preprocessor/dump_import.h
  test/Preprocessor/dump_import.m
  test/Preprocessor/dump_include.c
  test/Preprocessor/dump_include.h

Index: test/Preprocessor/dump_include.h
===================================================================
--- /dev/null
+++ test/Preprocessor/dump_include.h
@@ -0,0 +1,2 @@
+#pragma once
+#define DUMP_INCLUDE_TESTVAL 1
Index: test/Preprocessor/dump_include.c
===================================================================
--- /dev/null
+++ test/Preprocessor/dump_include.c
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -E -dI %s -o - | grep '^#include'
+#include "dump_include.h"
Index: test/Preprocessor/dump_import.m
===================================================================
--- /dev/null
+++ test/Preprocessor/dump_import.m
@@ -0,0 +1,2 @@
+// RUN: %clang_cc1 -E -dI %s -o - | grep '^#import'
+#import "dump_import.h"
Index: test/Preprocessor/dump_import.h
===================================================================
--- /dev/null
+++ test/Preprocessor/dump_import.h
@@ -0,0 +1 @@
+#define DUMP_IMPORT_TESTVAL 1
Index: lib/Frontend/PrintPreprocessedOutput.cpp
===================================================================
--- lib/Frontend/PrintPreprocessedOutput.cpp
+++ lib/Frontend/PrintPreprocessedOutput.cpp
@@ -93,13 +93,15 @@
   bool Initialized;
   bool DisableLineMarkers;
   bool DumpDefines;
+  bool DumpIncludeDirectives;
   bool UseLineDirectives;
   bool IsFirstFileEntered;
 public:
   PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
-                           bool defines, bool UseLineDirectives)
+                           bool defines, bool dumpIncludeDirectives, bool UseLineDirectives)
       : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
         DisableLineMarkers(lineMarkers), DumpDefines(defines),
+        DumpIncludeDirectives(dumpIncludeDirectives),
         UseLineDirectives(UseLineDirectives) {
     CurLine = 0;
     CurFilename += "<uninit>";
@@ -154,7 +156,7 @@
   }
   bool MoveToLine(unsigned LineNo);
 
-  bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, 
+  bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok,
                    const Token &Tok) {
     return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok);
   }
@@ -238,7 +240,7 @@
       ++CurLine;
     return true;
   }
-  
+
   return false;
 }
 
@@ -252,11 +254,11 @@
   // Unless we are exiting a #include, make sure to skip ahead to the line the
   // #include directive was at.
   SourceManager &SourceMgr = SM;
-  
+
   PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc);
   if (UserLoc.isInvalid())
     return;
-  
+
   unsigned NewLine = UserLoc.getLine();
 
   if (Reason == PPCallbacks::EnterFile) {
@@ -271,7 +273,7 @@
     // off by one. We can do better by simply incrementing NewLine here.
     NewLine += 1;
   }
-  
+
   CurLine = NewLine;
 
   CurFilename.clear();
@@ -282,7 +284,7 @@
     startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false);
     return;
   }
-  
+
   if (!Initialized) {
     WriteLineInfo(CurLine);
     Initialized = true;
@@ -311,6 +313,54 @@
   }
 }
 
+namespace {
+/**
+ * Escape chars which are bad to print inside preprocessed output; e.g. we cannot break lines
+ * if we're emitting a '#'-style directive (escape both CR and LF).  Paths are quoted in some
+ * instances, so escape quotes.  Escaping is with a backslash (and backslashes themselves have
+ * to be escaped); for CR or LF, we use "\r" or "\n".
+ */
+std::string sanitizePath(const StringRef& path) {
+  std::string str(path.size() * 2, '\0');
+  size_t len = 0;
+  for (size_t i = 0; i < path.size(); i++) {
+    const char c = path[i];
+    switch (c) {
+      case '\\':
+        str[len++] = '\\';
+        str[len++] = '\\';
+        break;
+      case '\r':
+        str[len++] = '\\';
+        str[len++] = 'r';
+        break;
+      case '\n':
+        str[len++] = '\\';
+        str[len++] = 'n';
+        break;
+      case '"':
+        str[len++] = '\\';
+        str[len++] = '"';
+        break;
+      default:
+        str[len++] = c;
+    }
+  }
+  return str.substr(0, len);
+}
+
+bool tryGetTokenText(std::string* InclusionKeyword, const Token &tok) {
+  if (tok.getKind() == clang::tok::identifier) {
+    const auto* idInfo = tok.getIdentifierInfo();
+    if (idInfo && idInfo->getNameStart() != nullptr) {
+      *InclusionKeyword = std::string(idInfo->getNameStart(), idInfo->getLength());
+      return true;
+    }
+  }
+  return false;
+}
+}
+
 void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
                                                   const Token &IncludeTok,
                                                   StringRef FileName,
@@ -320,10 +370,10 @@
                                                   StringRef SearchPath,
                                                   StringRef RelativePath,
                                                   const Module *Imported) {
-  // When preprocessing, turn implicit imports into @imports.
-  // FIXME: This is a stop-gap until a more comprehensive "preprocessing with
-  // modules" solution is introduced.
   if (Imported) {
+    // When preprocessing, turn implicit imports into @imports.
+    // FIXME: This is a stop-gap until a more comprehensive "preprocessing with
+    // modules" solution is introduced.
     startNewLineIfNeeded();
     MoveToLine(HashLoc);
     if (PP.getLangOpts().ObjC2) {
@@ -344,6 +394,31 @@
     // line immediately.
     EmittedTokensOnThisLine = true;
     startNewLineIfNeeded();
+  } else {
+    // Not a module import; it's a more vanilla inclusion of some file using one of:
+    // #include, #import, #include_next, #include_macros.
+    if (DumpIncludeDirectives) {
+      // If we couldn't determine the actual token used in the source, just say #include in output.
+      std::string InclusionKeyword("include");
+      tryGetTokenText(&InclusionKeyword, IncludeTok);
+      OS << "#" << InclusionKeyword << " "
+         << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"');
+
+      OS << " /* clang -E -dI:";
+
+      auto SanitizedSearchPath = sanitizePath(SearchPath);
+      auto SanitizedRelativePath = sanitizePath(RelativePath);
+      if (SanitizedSearchPath.size() == 0 && SanitizedRelativePath.size() > 0) {
+        OS << " absolute=\"" << SanitizedRelativePath << "\"";
+      } else if (SanitizedSearchPath.size() > 0 && SanitizedRelativePath.size() > 0) {
+        OS << " path=\"" << SanitizedSearchPath << "\"";
+      }
+
+      OS << " */";
+
+      setEmittedDirectiveOnThisLine();
+      startNewLineIfNeeded();
+    }
   }
 }
 
@@ -751,7 +826,8 @@
   PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments);
 
   PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(
-      PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.UseLineDirectives);
+      PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.ShowIncludeDirectives,
+      Opts.UseLineDirectives);
 
   // Expand macros in pragmas with -fms-extensions.  The assumption is that
   // the majority of pragmas in such a file will be Microsoft pragmas.
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -2332,6 +2332,7 @@
   Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
   Opts.ShowMacroComments = Args.hasArg(OPT_CC);
   Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+  Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI);
   Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes);
   Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives);
 }
Index: include/clang/Frontend/PreprocessorOutputOptions.h
===================================================================
--- include/clang/Frontend/PreprocessorOutputOptions.h
+++ include/clang/Frontend/PreprocessorOutputOptions.h
@@ -22,6 +22,7 @@
   unsigned UseLineDirectives : 1;   ///< Use \#line instead of GCC-style \# N.
   unsigned ShowMacroComments : 1;  ///< Show comments, even in macros.
   unsigned ShowMacros : 1;         ///< Print macro definitions.
+  unsigned ShowIncludeDirectives : 1;  ///< Print includes, imports etc. within preprocessed output.
   unsigned RewriteIncludes : 1;    ///< Preprocess include directives only.
 
 public:
@@ -32,6 +33,7 @@
     UseLineDirectives = 0;
     ShowMacroComments = 0;
     ShowMacros = 0;
+    ShowIncludeDirectives = 0;
     RewriteIncludes = 0;
   }
 };
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -429,6 +429,8 @@
 def dA : Flag<["-"], "dA">, Group<d_Group>;
 def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>,
   HelpText<"Print macro definitions in -E mode in addition to normal output">;
+def dI : Flag<["-"], "dI">, Group<d_Group>, Flags<[CC1Option]>,
+  HelpText<"Print include directives in -E mode in addition to normal output">;
 def dM : Flag<["-"], "dM">, Group<d_Group>, Flags<[CC1Option]>,
   HelpText<"Print macro definitions in -E mode instead of normal output">;
 def dead__strip : Flag<["-"], "dead_strip">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to