]> granicus.if.org Git - clang/commitdiff
<rdar://problem/13509689> Introduce -module-file-info option that provides informatio...
authorDouglas Gregor <dgregor@apple.com>
Wed, 27 Mar 2013 16:47:18 +0000 (16:47 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 27 Mar 2013 16:47:18 +0000 (16:47 +0000)
This option can be useful for end users who want to know why they
ended up with a ton of different variants of the "std" module in their
module cache. This problem should go away over time, as we reduce the
need for module variants, but it will never go away entirely.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178148 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
docs/Modules.rst
include/clang/Basic/DiagnosticDriverKinds.td
include/clang/Driver/Options.td
include/clang/Driver/Types.def
include/clang/Frontend/FrontendActions.h
include/clang/Frontend/FrontendOptions.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ModuleManager.h
lib/Driver/Driver.cpp
lib/Driver/Tools.cpp
lib/Driver/Types.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/FrontendActions.cpp
lib/Frontend/FrontendOptions.cpp
lib/FrontendTool/ExecuteCompilerInvocation.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ModuleManager.cpp
test/Modules/module_file_info.m [new file with mode: 0644]

index b892e382fc991146ee3c613c8648e9a5e595b5f8..8a6b8b6d2ef28be3593d8576359eef75d9038a93 100644 (file)
@@ -180,6 +180,9 @@ Command-line parameters
 ``-fmodules-prune-after=seconds``
   Specify the minimum time (in seconds) for which a file in the module cache must be unused (according to access time) before module pruning will remove it. The default delay is large (2,678,400 seconds, or 31 days) to avoid excessive module rebuilding.
 
+``-module-file-info <module file name>``
+  Debugging aid that prints information about a given module file (with a ``.pcm`` extension), including the language and preprocessor options that particular module variant was built with.
+
 Module Map Language
 ===================
 
index d14fe94d6c1fda083fe83dbe1257842f189960e3..15b89486606681c324402328bc4017680b9c6174 100644 (file)
@@ -59,6 +59,8 @@ def err_drv_no_linker_llvm_support : Error<
   "'%0': unable to pass LLVM bit-code files to linker">;
 def err_drv_no_ast_support : Error<
   "'%0': unable to use AST files with this tool">;
+def err_drv_no_module_support : Error<
+  "'%0': unable to use module files with this tool">;
 def err_drv_clang_unsupported : Error<
   "the clang compiler does not support '%0'">;
 def err_drv_clang_unsupported_per_platform : Error<
index c9575c3515549dc5fb863f1895c9e84e8743f3c3..9de13fb6fb3d6340b5229de8e7c39239e906b1e0 100644 (file)
@@ -956,6 +956,7 @@ def mips64 : Flag<["-"], "mips64">, Group<mips_CPUs_Group>,
   HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>;
 def mips64r2 : Flag<["-"], "mips64r2">, Group<mips_CPUs_Group>,
   HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>;
+def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>;
 def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
 def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>;
 def multi__module : Flag<["-"], "multi_module">;
index 4bff1f1d3e2be9e2c073820ffdf1a9aa732c3b3c..42f0709cf17ae3520db412a9bd85497ccf95382b 100644 (file)
@@ -80,6 +80,7 @@ TYPE("lto-bc",                   LTO_BC,       INVALID,         "o",     "")
 
 // Misc.
 TYPE("ast",                      AST,          INVALID,         "ast",   "u")
+TYPE("pcm",                      ModuleFile,   INVALID,         "pcm",   "u")
 TYPE("plist",                    Plist,        INVALID,         "plist", "")
 TYPE("rewritten-objc",           RewrittenObjC,INVALID,         "cpp",   "")
 TYPE("rewritten-legacy-objc",    RewrittenLegacyObjC,INVALID,   "cpp",   "")
index 477ac45a9570bbf3e2519d0a1fd2fd527d14c7de..178619047a386bc020b54508660c02a0f353f41f 100644 (file)
@@ -123,7 +123,7 @@ public:
                                           std::string &OutputFile,
                                           raw_ostream *&OS);
 };
-  
+
 class SyntaxOnlyAction : public ASTFrontendAction {
 protected:
   virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
@@ -133,6 +133,21 @@ public:
   virtual bool hasCodeCompletionSupport() const { return true; }
 };
 
+/// \brief Dump information about the given module file, to be used for
+/// basic debugging and discovery.
+class DumpModuleInfoAction : public ASTFrontendAction {
+protected:
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         StringRef InFile);
+  virtual void ExecuteAction();
+  
+public:
+  virtual bool hasPCHSupport() const { return false; }
+  virtual bool hasASTFileSupport() const { return true; }
+  virtual bool hasIRSupport() const { return false; }
+  virtual bool hasCodeCompletionSupport() const { return false; }
+};
+
 /**
  * \brief Frontend action adaptor that merges ASTs together.
  *
index c39c1908a74b17356d863b5465f436b18731e650..234e3446c809d8794aecfb69eaa0feafa01b0b4d 100644 (file)
@@ -43,6 +43,7 @@ namespace frontend {
     GeneratePCH,            ///< Generate pre-compiled header.
     GeneratePTH,            ///< Generate pre-tokenized header.
     InitOnly,               ///< Only execute frontend initialization.
+    ModuleFileInfo,         ///< Dump information about a module file.
     ParseSyntaxOnly,        ///< Parse and perform semantic analysis.
     PluginAction,           ///< Run a plugin action, \see ActionName.
     PrintDeclContext,       ///< Print DeclContext and their Decls.
index 19d49183dd0ddeadd3536b85894777d10d58b6f7..925533678c15b42ecd5789b879c2ab995c370cc1 100644 (file)
@@ -22,6 +22,7 @@
 #include "clang/Basic/FileSystemOptions.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
 #include "clang/Lex/ExternalPreprocessorSource.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/PreprocessingRecord.h"
@@ -99,6 +100,14 @@ class ASTReaderListener {
 public:
   virtual ~ASTReaderListener();
 
+  /// \brief Receives the full Clang version information.
+  ///
+  /// \returns true to indicate that the version is invalid. Subclasses should
+  /// generally defer to this implementation.
+  virtual bool ReadFullVersionInformation(StringRef FullVersion) {
+    return FullVersion != getClangFullRepositoryVersion();
+  }
+
   /// \brief Receives the language options.
   ///
   /// \returns true to indicate the options are invalid or false otherwise.
index c6e3265b3b32a1df27c909ea4ace055166f9f268..b2c406346a5f3199e6b074d2a179b68094592c36 100644 (file)
@@ -135,7 +135,10 @@ public:
   
   /// \brief Returns the module associated with the given name
   ModuleFile *lookup(StringRef Name);
-  
+
+  /// \brief Returns the module associated with the given module file.
+  ModuleFile *lookup(const FileEntry *File);
+
   /// \brief Returns the in-memory (virtual file) buffer with the given name
   llvm::MemoryBuffer *lookupBuffer(StringRef Name);
   
index 706409d05d74fcfa806b221aec17e5b98ca70f6b..29ed5cffaa5a92aa545cf28a942bba29296a2987 100644 (file)
@@ -126,6 +126,7 @@ const {
 
     // -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
+             (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
              (PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
@@ -1170,6 +1171,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
       return new MigrateJobAction(Input, types::TY_Remap);
     } else if (Args.hasArg(options::OPT_emit_ast)) {
       return new CompileJobAction(Input, types::TY_AST);
+    } else if (Args.hasArg(options::OPT_module_file_info)) {
+      return new CompileJobAction(Input, types::TY_ModuleFile);
     } else if (IsUsingLTO(Args)) {
       types::ID Output =
         Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
@@ -1432,7 +1435,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
   }
 
   // Default to writing to stdout?
-  if (AtTopLevel && isa<PreprocessJobAction>(JA) && !CCGenDiagnostics)
+  if (AtTopLevel && !CCGenDiagnostics &&
+      (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
     return "-";
 
   // Output to a temporary file?
index c7e47ad111060d89ffbca62772ffb029ef6c7874..fa3128bbd5983db5d1b957f7ee326d5a9d001fa2 100644 (file)
@@ -1860,6 +1860,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-S");
     } else if (JA.getType() == types::TY_AST) {
       CmdArgs.push_back("-emit-pch");
+    } else if (JA.getType() == types::TY_ModuleFile) {
+      CmdArgs.push_back("-module-file-info");
     } else if (JA.getType() == types::TY_RewrittenObjC) {
       CmdArgs.push_back("-rewrite-objc");
       rewriteKind = RK_NonFragile;
@@ -3696,6 +3698,9 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA,
     else if (II.getType() == types::TY_AST)
       D.Diag(diag::err_drv_no_ast_support)
         << getToolChain().getTripleString();
+    else if (II.getType() == types::TY_ModuleFile)
+      D.Diag(diag::err_drv_no_module_support)
+        << getToolChain().getTripleString();
 
     if (types::canTypeBeUserSpecified(II.getType())) {
       CmdArgs.push_back("-x");
@@ -3826,6 +3831,9 @@ void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA,
     else if (II.getType() == types::TY_AST)
       D.Diag(clang::diag::err_drv_no_ast_support)
         << getToolChain().getTripleString();
+    else if (II.getType() == types::TY_ModuleFile)
+      D.Diag(diag::err_drv_no_module_support)
+      << getToolChain().getTripleString();
 
     if (II.isFilename())
       CmdArgs.push_back(II.getFilename());
index 9665095b003cae26b323a52f7200310b41903dcc..7d22596a17ef703ea1491467f4bcc8041d9a570e 100644 (file)
@@ -87,7 +87,7 @@ bool types::isAcceptedByClang(ID Id) {
   case TY_ObjCHeader: case TY_PP_ObjCHeader:
   case TY_CXXHeader: case TY_PP_CXXHeader:
   case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
-  case TY_AST:
+  case TY_AST: case TY_ModuleFile:
   case TY_LLVM_IR: case TY_LLVM_BC:
     return true;
   }
@@ -164,6 +164,7 @@ types::ID types::lookupTypeForExtension(const char *Ext) {
            .Case("F90", TY_Fortran)
            .Case("F95", TY_Fortran)
            .Case("mii", TY_PP_ObjCXX)
+           .Case("pcm", TY_ModuleFile)
            .Default(TY_INVALID);
 }
 
index 2d945b5b0445dcc427b1721e08d9dd808474ebdb..0fb8e58b3d56d351af667ffd37d6216368b77460 100644 (file)
@@ -644,6 +644,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
       Opts.ProgramAction = frontend::InitOnly; break;
     case OPT_fsyntax_only:
       Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
+    case OPT_module_file_info:
+      Opts.ProgramAction = frontend::ModuleFileInfo; break;
     case OPT_print_decl_contexts:
       Opts.ProgramAction = frontend::PrintDeclContext; break;
     case OPT_print_preamble:
@@ -779,7 +781,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
       .Case("objective-c-header", IK_ObjC)
       .Case("c++-header", IK_CXX)
       .Case("objective-c++-header", IK_ObjCXX)
-      .Case("ast", IK_AST)
+      .Cases("ast", "pcm", IK_AST)
       .Case("ir", IK_LLVM_IR)
       .Default(IK_None);
     if (DashX == IK_None)
@@ -1465,6 +1467,7 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
   case frontend::GeneratePCH:
   case frontend::GeneratePTH:
   case frontend::ParseSyntaxOnly:
+  case frontend::ModuleFileInfo:
   case frontend::PluginAction:
   case frontend::PrintDeclContext:
   case frontend::RewriteObjC:
@@ -1627,6 +1630,8 @@ llvm::APInt ModuleSignature::getAsInteger() const {
 }
 
 std::string CompilerInvocation::getModuleHash() const {
+  // Note: For QoI reasons, the things we use as a hash here should all be
+  // dumped via the -module-info flag.
   using llvm::hash_code;
   using llvm::hash_value;
   using llvm::hash_combine;
index f3466f02342c4055721f13d8d3b86be3cf4152c4..5c7567fa8c02f335befd1168df68c1a569649303 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/Lex/Pragma.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Parse/Parser.h"
+#include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/Support/FileSystem.h"
@@ -316,6 +317,130 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
   return new ASTConsumer();
 }
 
+ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
+                                                     StringRef InFile) {
+  return new ASTConsumer();
+}
+
+namespace {
+  /// \brief AST reader listener that dumps module information for a module
+  /// file.
+  class DumpModuleInfoListener : public ASTReaderListener {
+    llvm::raw_ostream &Out;
+
+  public:
+    DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
+
+#define DUMP_BOOLEAN(Value, Text)                       \
+    Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
+
+    virtual bool ReadFullVersionInformation(StringRef FullVersion) {
+      Out.indent(2)
+        << "Generated by "
+        << (FullVersion == getClangFullRepositoryVersion()? "this"
+                                                          : "a different")
+        << " Clang: " << FullVersion << "\n";
+      return ASTReaderListener::ReadFullVersionInformation(FullVersion);
+    }
+
+    virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
+                                     bool Complain) {
+      Out.indent(2) << "Language options:\n";
+#define LANGOPT(Name, Bits, Default, Description) \
+      DUMP_BOOLEAN(LangOpts.Name, Description);
+#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
+      Out.indent(4) << Description << ": "                   \
+                    << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
+#define VALUE_LANGOPT(Name, Bits, Default, Description) \
+      Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
+#define BENIGN_LANGOPT(Name, Bits, Default, Description)
+#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
+#include "clang/Basic/LangOptions.def"
+      return false;
+    }
+
+    virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
+                                   bool Complain) {
+      Out.indent(2) << "Target options:\n";
+      Out.indent(4) << "  Triple: " << TargetOpts.Triple << "\n";
+      Out.indent(4) << "  CPU: " << TargetOpts.CPU << "\n";
+      Out.indent(4) << "  ABI: " << TargetOpts.ABI << "\n";
+      Out.indent(4) << "  C++ ABI: " << TargetOpts.CXXABI << "\n";
+      Out.indent(4) << "  Linker version: " << TargetOpts.LinkerVersion << "\n";
+
+      if (!TargetOpts.FeaturesAsWritten.empty()) {
+        Out.indent(4) << "Target features:\n";
+        for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
+             I != N; ++I) {
+          Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
+        }
+      }
+
+      return false;
+    }
+
+    virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
+                                         bool Complain) {
+      Out.indent(2) << "Header search options:\n";
+      Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
+      DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
+                   "Use builtin include directories [-nobuiltininc]");
+      DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
+                   "Use standard system include directories [-nostdinc]");
+      DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
+                   "Use standard C++ include directories [-nostdinc++]");
+      DUMP_BOOLEAN(HSOpts.UseLibcxx,
+                   "Use libc++ (rather than libstdc++) [-stdlib=]");
+      return false;
+    }
+
+    virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
+                                         bool Complain,
+                                         std::string &SuggestedPredefines) {
+      Out.indent(2) << "Preprocessor options:\n";
+      DUMP_BOOLEAN(PPOpts.UsePredefines,
+                   "Uses compiler/target-specific predefines [-undef]");
+      DUMP_BOOLEAN(PPOpts.DetailedRecord,
+                   "Uses detailed preprocessing record (for indexing)");
+
+      if (!PPOpts.Macros.empty()) {
+        Out.indent(4) << "Predefined macros:\n";
+      }
+
+      for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
+             I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
+           I != IEnd; ++I) {
+        Out.indent(6);
+        if (I->second)
+          Out << "-U";
+        else
+          Out << "-D";
+        Out << I->first << "\n";
+      }
+      return false;
+    }
+#undef DUMP_BOOLEAN
+  };
+}
+
+void DumpModuleInfoAction::ExecuteAction() {
+  // Set up the output file.
+  llvm::OwningPtr<llvm::raw_fd_ostream> OutFile;
+  StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
+  if (!OutputFileName.empty() && OutputFileName != "-") {
+    std::string ErrorInfo;
+    OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str().c_str(),
+                                           ErrorInfo));
+  }
+  llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
+
+  Out << "Information for module file '" << getCurrentFile() << "':\n";
+  DumpModuleInfoListener Listener(Out);
+  ASTReader::readASTFileControlBlock(getCurrentFile(),
+                                     getCompilerInstance().getFileManager(),
+                                     Listener);
+}
+
 //===----------------------------------------------------------------------===//
 // Preprocessor Actions
 //===----------------------------------------------------------------------===//
index ea4005f7c96028e5a6dce6c1220ed50adaa9eae8..f1823c69e96cdf0c73601d91b0ee716cc1e481b0 100644 (file)
@@ -13,7 +13,7 @@ using namespace clang;
 
 InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
   return llvm::StringSwitch<InputKind>(Extension)
-    .Case("ast", IK_AST)
+    .Cases("ast", "pcm", IK_AST)
     .Case("c", IK_C)
     .Cases("S", "s", IK_Asm)
     .Case("i", IK_PreprocessedC)
index ad8eb04768bcb5aa86545ca36756be78b014bb55..b0d76da33425ccd28892064595f723102ce8e385 100644 (file)
@@ -62,6 +62,7 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
   case GeneratePTH:            return new GeneratePTHAction();
   case InitOnly:               return new InitOnlyAction();
   case ParseSyntaxOnly:        return new SyntaxOnlyAction();
+  case ModuleFileInfo:         return new DumpModuleInfoAction();
 
   case PluginAction: {
     for (FrontendPluginRegistry::iterator it =
index 55e333a17b6972103de76de9bc6941da06e5b832..4c2d2197e498a3b1dce0315978ce94fcb58720ec 100644 (file)
@@ -3487,10 +3487,9 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
       if (Record[0] != VERSION_MAJOR)
         return true;
 
-      const std::string &CurBranch = getClangFullRepositoryVersion();
-      if (StringRef(CurBranch) != Blob)
+      if (Listener.ReadFullVersionInformation(Blob))
         return true;
-
+      
       break;
     }
     case LANGUAGE_OPTIONS:
index 193a38b97384e7f1aa91899774f141bb61c7f717..f3d53adafa521bcaaca2ce250cd85f13751f81d0 100644 (file)
@@ -29,7 +29,19 @@ using namespace serialization;
 ModuleFile *ModuleManager::lookup(StringRef Name) {
   const FileEntry *Entry = FileMgr.getFile(Name, /*openFile=*/false,
                                            /*cacheFailure=*/false);
-  return Modules[Entry];
+  if (Entry)
+    return lookup(Entry);
+
+  return 0;
+}
+
+ModuleFile *ModuleManager::lookup(const FileEntry *File) {
+  llvm::DenseMap<const FileEntry *, ModuleFile *>::iterator Known
+    = Modules.find(File);
+  if (Known == Modules.end())
+    return 0;
+
+  return Known->second;
 }
 
 llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
diff --git a/test/Modules/module_file_info.m b/test/Modules/module_file_info.m
new file mode 100644 (file)
index 0000000..09319d6
--- /dev/null
@@ -0,0 +1,34 @@
+
+@import DependsOnModule;
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -w -fmodules -fdisable-module-hash -fmodules-cache-path=%t -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE %s
+// RUN: %clang_cc1 -module-file-info %t/DependsOnModule.pcm | FileCheck %s
+
+// CHECK: Generated by this Clang:
+
+// CHECK: Language options:
+// CHECK:   C99: Yes
+// CHECK:   Objective-C 1: Yes
+// CHECK:   modules extension to C: Yes
+
+// CHECK: Target options:
+// CHECK:     Triple:
+// CHECK:     CPU: 
+// CHECK:     ABI: 
+// CHECK:     C++ ABI: 
+// CHECK:     Linker version: 
+
+// CHECK: Header search options:
+// CHECK:   System root [-isysroot=]: '/'
+// CHECK:   Use builtin include directories [-nobuiltininc]: Yes
+// CHECK:   Use standard system include directories [-nostdinc]: Yes
+// CHECK:   Use standard C++ include directories [-nostdinc++]: Yes
+// CHECK:   Use libc++ (rather than libstdc++) [-stdlib=]:
+
+// CHECK: Preprocessor options:
+// CHECK:   Uses compiler/target-specific predefines [-undef]: Yes
+// CHECK:   Uses detailed preprocessing record (for indexing): No
+// CHECK:   Predefined macros:
+// CHECK:     -DBLARG
+// CHECK:     -DWIBBLE=WOBBLE