Extract the (InputKind, std::string) pair used to describe inputs to
the front end into its own class, FrontendInputFile, to make it easier
to introduce new per-input data. No functionality change.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148546 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h
index 48c5130..b05dd4c 100644
--- a/include/clang/ARCMigrate/ARCMT.h
+++ b/include/clang/ARCMigrate/ARCMT.h
@@ -37,7 +37,7 @@
 ///
 /// \returns false if no error is produced, true otherwise.
 bool checkForManualIssues(CompilerInvocation &CI,
-                          StringRef Filename, InputKind Kind,
+                          const FrontendInputFile &Input,
                           DiagnosticConsumer *DiagClient,
                           bool emitPremigrationARCErrors = false,
                           StringRef plistOut = StringRef());
@@ -47,7 +47,7 @@
 ///
 /// \returns false if no error is produced, true otherwise.
 bool applyTransformations(CompilerInvocation &origCI,
-                          StringRef Filename, InputKind Kind,
+                          const FrontendInputFile &Input,
                           DiagnosticConsumer *DiagClient);
 
 /// \brief Applies automatic modifications and produces temporary files
@@ -62,7 +62,7 @@
 ///
 /// \returns false if no error is produced, true otherwise.
 bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
-                               StringRef Filename, InputKind Kind,
+                               const FrontendInputFile &Input,
                                DiagnosticConsumer *DiagClient,
                                StringRef outputDir,
                                bool emitPremigrationARCErrors,
diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h
index b6ef9a5..041c1d3 100644
--- a/include/clang/Frontend/FrontendAction.h
+++ b/include/clang/Frontend/FrontendAction.h
@@ -12,6 +12,7 @@
 
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Frontend/FrontendOptions.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/OwningPtr.h"
 #include <string>
@@ -23,29 +24,10 @@
 class ASTUnit;
 class CompilerInstance;
 
-enum InputKind {
-  IK_None,
-  IK_Asm,
-  IK_C,
-  IK_CXX,
-  IK_ObjC,
-  IK_ObjCXX,
-  IK_PreprocessedC,
-  IK_PreprocessedCXX,
-  IK_PreprocessedObjC,
-  IK_PreprocessedObjCXX,
-  IK_OpenCL,
-  IK_CUDA,
-  IK_AST,
-  IK_LLVM_IR
-};
-
-
 /// FrontendAction - Abstract base class for actions which can be performed by
 /// the frontend.
 class FrontendAction {
-  std::string CurrentFile;
-  InputKind CurrentFileKind;
+  FrontendInputFile CurrentInput;
   llvm::OwningPtr<ASTUnit> CurrentASTUnit;
   CompilerInstance *Instance;
   friend class ASTMergeAction;
@@ -127,18 +109,22 @@
   /// @{
 
   bool isCurrentFileAST() const {
-    assert(!CurrentFile.empty() && "No current file!");
+    assert(!CurrentInput.File.empty() && "No current file!");
     return CurrentASTUnit != 0;
   }
 
+  const FrontendInputFile &getCurrentInput() const {
+    return CurrentInput;
+  }
+  
   const std::string &getCurrentFile() const {
-    assert(!CurrentFile.empty() && "No current file!");
-    return CurrentFile;
+    assert(!CurrentInput.File.empty() && "No current file!");
+    return CurrentInput.File;
   }
 
   InputKind getCurrentFileKind() const {
-    assert(!CurrentFile.empty() && "No current file!");
-    return CurrentFileKind;
+    assert(!CurrentInput.File.empty() && "No current file!");
+    return CurrentInput.Kind;
   }
 
   ASTUnit &getCurrentASTUnit() const {
@@ -150,7 +136,7 @@
     return CurrentASTUnit.take();
   }
 
-  void setCurrentFile(StringRef Value, InputKind Kind, ASTUnit *AST = 0);
+  void setCurrentInput(const FrontendInputFile &CurrentInput, ASTUnit *AST = 0);
 
   /// @}
   /// @name Supported Modes
@@ -189,10 +175,7 @@
   /// action may store and use this object up until the matching EndSourceFile
   /// action.
   ///
-  /// \param Filename - The input filename, which will be made available to
-  /// clients via \see getCurrentFile().
-  ///
-  /// \param InputKind - The type of input. Some input kinds are handled
+  /// \param Input - The input filename and kind. Some input kinds are handled
   /// specially, for example AST inputs, since the AST file itself contains
   /// several objects which would normally be owned by the
   /// CompilerInstance. When processing AST input files, these objects should
@@ -202,8 +185,7 @@
   ///
   /// \return True on success; the compilation of this file should be aborted
   /// and neither Execute nor EndSourceFile should be called.
-  bool BeginSourceFile(CompilerInstance &CI, StringRef Filename,
-                       InputKind Kind);
+  bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input);
 
   /// Execute - Set the source managers main input file, and run the action.
   void Execute();
diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h
index fa6d044..637ceff 100644
--- a/include/clang/Frontend/FrontendOptions.h
+++ b/include/clang/Frontend/FrontendOptions.h
@@ -11,7 +11,6 @@
 #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
 
 #include "clang/Frontend/CommandLineSourceLoc.h"
-#include "clang/Frontend/FrontendAction.h"
 #include "llvm/ADT/StringRef.h"
 #include <string>
 #include <vector>
@@ -51,6 +50,37 @@
   };
 }
 
+enum InputKind {
+  IK_None,
+  IK_Asm,
+  IK_C,
+  IK_CXX,
+  IK_ObjC,
+  IK_ObjCXX,
+  IK_PreprocessedC,
+  IK_PreprocessedCXX,
+  IK_PreprocessedObjC,
+  IK_PreprocessedObjCXX,
+  IK_OpenCL,
+  IK_CUDA,
+  IK_AST,
+  IK_LLVM_IR
+};
+
+  
+/// \brief An input file for the front end.
+struct FrontendInputFile {
+  /// \brief The file name, or "-" to read from standard input.
+  std::string File;
+
+  /// \brief The kind of input, e.g., C source, AST file, LLVM IR.
+  InputKind Kind;
+
+  FrontendInputFile() : Kind(IK_None) { }
+  FrontendInputFile(StringRef File, InputKind Kind)
+    : File(File.str()), Kind(Kind) { }
+};
+  
 /// FrontendOptions - Options for controlling the behavior of the frontend.
 class FrontendOptions {
 public:
@@ -86,7 +116,7 @@
   std::string ARCMTMigrateReportOut;
 
   /// The input files and their types.
-  std::vector<std::pair<InputKind, std::string> > Inputs;
+  std::vector<FrontendInputFile> Inputs;
 
   /// The output file, if any.
   std::string OutputFile;
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp
index 9985160..9a07245 100644
--- a/lib/ARCMigrate/ARCMT.cpp
+++ b/lib/ARCMigrate/ARCMT.cpp
@@ -10,6 +10,7 @@
 #include "Internals.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/AST/ASTConsumer.h"
@@ -220,7 +221,7 @@
 //===----------------------------------------------------------------------===//
 
 bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
-                                 StringRef Filename, InputKind Kind,
+                                 const FrontendInputFile &Input,
                                  DiagnosticConsumer *DiagClient,
                                  bool emitPremigrationARCErrors,
                                  StringRef plistOut) {
@@ -235,7 +236,7 @@
   llvm::OwningPtr<CompilerInvocation> CInvok;
   CInvok.reset(createInvocationForMigration(origCI));
   CInvok->getFrontendOpts().Inputs.clear();
-  CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
+  CInvok->getFrontendOpts().Inputs.push_back(Input);
 
   CapturedDiagList capturedDiags;
 
@@ -311,7 +312,7 @@
 //===----------------------------------------------------------------------===//
 
 static bool applyTransforms(CompilerInvocation &origCI,
-                            StringRef Filename, InputKind Kind,
+                            const FrontendInputFile &Input,
                             DiagnosticConsumer *DiagClient,
                             StringRef outputDir,
                             bool emitPremigrationARCErrors,
@@ -323,13 +324,13 @@
 
   // Make sure checking is successful first.
   CompilerInvocation CInvokForCheck(origCI);
-  if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient,
+  if (arcmt::checkForManualIssues(CInvokForCheck, Input, DiagClient,
                                   emitPremigrationARCErrors, plistOut))
     return true;
 
   CompilerInvocation CInvok(origCI);
   CInvok.getFrontendOpts().Inputs.clear();
-  CInvok.getFrontendOpts().Inputs.push_back(std::make_pair(Kind, Filename));
+  CInvok.getFrontendOpts().Inputs.push_back(Input);
   
   MigrationProcess migration(CInvok, DiagClient, outputDir);
 
@@ -357,20 +358,20 @@
 }
 
 bool arcmt::applyTransformations(CompilerInvocation &origCI,
-                                 StringRef Filename, InputKind Kind,
+                                 const FrontendInputFile &Input,
                                  DiagnosticConsumer *DiagClient) {
-  return applyTransforms(origCI, Filename, Kind, DiagClient,
+  return applyTransforms(origCI, Input, DiagClient,
                          StringRef(), false, StringRef());
 }
 
 bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
-                                      StringRef Filename, InputKind Kind,
+                                      const FrontendInputFile &Input,
                                       DiagnosticConsumer *DiagClient,
                                       StringRef outputDir,
                                       bool emitPremigrationARCErrors,
                                       StringRef plistOut) {
   assert(!outputDir.empty() && "Expected output directory path");
-  return applyTransforms(origCI, Filename, Kind, DiagClient,
+  return applyTransforms(origCI, Input, DiagClient,
                          outputDir, emitPremigrationARCErrors, plistOut);
 }
 
diff --git a/lib/ARCMigrate/ARCMTActions.cpp b/lib/ARCMigrate/ARCMTActions.cpp
index dea867a..0ed36dd 100644
--- a/lib/ARCMigrate/ARCMTActions.cpp
+++ b/lib/ARCMigrate/ARCMTActions.cpp
@@ -15,8 +15,7 @@
 using namespace arcmt;
 
 bool CheckAction::BeginInvocation(CompilerInstance &CI) {
-  if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentFile(),
-                                  getCurrentFileKind(),
+  if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(),
                                   CI.getDiagnostics().getClient()))
     return false; // errors, stop the action.
 
@@ -29,8 +28,7 @@
   : WrapperFrontendAction(WrappedAction) {}
 
 bool ModifyAction::BeginInvocation(CompilerInstance &CI) {
-  return !arcmt::applyTransformations(CI.getInvocation(),
-                                      getCurrentFile(), getCurrentFileKind(),
+  return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(),
                                       CI.getDiagnostics().getClient());
 }
 
@@ -39,12 +37,11 @@
 
 bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
   if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
-                                           getCurrentFile(),
-                                           getCurrentFileKind(),
-                                           CI.getDiagnostics().getClient(),
-                                           MigrateDir,
-                                           EmitPremigrationARCErros,
-                                           PlistOut))
+                                       getCurrentInput(),
+                                       CI.getDiagnostics().getClient(),
+                                       MigrateDir,
+                                       EmitPremigrationARCErros,
+                                       PlistOut))
     return false; // errors, stop the action.
 
   // We only want to see diagnostics emitted by migrateWithTemporaryFiles.
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index cb195d1..a410411 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -26,8 +26,7 @@
   // FIXME: This is a hack. We need a better way to communicate the
   // AST file, compiler instance, and file name than member variables
   // of FrontendAction.
-  AdaptedAction->setCurrentFile(getCurrentFile(), getCurrentFileKind(),
-                                takeCurrentASTUnit());
+  AdaptedAction->setCurrentInput(getCurrentInput(), takeCurrentASTUnit());
   AdaptedAction->setCompilerInstance(&CI);
   return AdaptedAction->BeginSourceFileAction(CI, Filename);
 }
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index e31bf55..c23c644 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -1003,7 +1003,7 @@
     CCInvocation(new CompilerInvocation(*Invocation));
 
   Clang->setInvocation(CCInvocation.getPtr());
-  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
+  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
     
   // Set up diagnostics, capturing any diagnostics that would
   // otherwise be dropped.
@@ -1026,9 +1026,9 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
          "IR inputs not support here!");
 
   // Configure the various subsystems.
@@ -1095,8 +1095,7 @@
   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
     ActCleanup(Act.get());
 
-  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
-                            Clang->getFrontendOpts().Inputs[0].first))
+  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
     goto error;
 
   if (OverrideMainBuffer) {
@@ -1182,7 +1181,7 @@
   // command line (to another file) or directly through the compiler invocation
   // (to a memory buffer).
   llvm::MemoryBuffer *Buffer = 0;
-  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
   if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
     // Check whether there is a file-file remapping of the main file
     for (PreprocessorOptions::remapped_file_iterator
@@ -1232,7 +1231,7 @@
   
   // If the main source file was not remapped, load it now.
   if (!Buffer) {
-    Buffer = getBufferForFile(FrontendOpts.Inputs[0].second);
+    Buffer = getBufferForFile(FrontendOpts.Inputs[0].File);
     if (!Buffer)
       return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));    
     
@@ -1394,7 +1393,7 @@
         // buffer size we reserved when creating the preamble.
         return CreatePaddedMainFileBuffer(NewPreamble.first, 
                                           PreambleReservedSize,
-                                          FrontendOpts.Inputs[0].second);
+                                          FrontendOpts.Inputs[0].File);
       }
     }
 
@@ -1447,7 +1446,7 @@
 
   // Save the preamble text for later; we'll need to compare against it for
   // subsequent reparses.
-  StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].second;
+  StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].File;
   Preamble.assign(FileMgr->getFile(MainFilename),
                   NewPreamble.first->getBufferStart(), 
                   NewPreamble.first->getBufferStart() 
@@ -1457,7 +1456,7 @@
   delete PreambleBuffer;
   PreambleBuffer
     = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
-                                                FrontendOpts.Inputs[0].second);
+                                                FrontendOpts.Inputs[0].File);
   memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()), 
          NewPreamble.first->getBufferStart(), Preamble.size());
   memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(), 
@@ -1465,7 +1464,7 @@
   const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';  
   
   // Remap the main source file to the preamble buffer.
-  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
+  llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].File);
   PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
   
   // Tell the compiler invocation to generate a temporary precompiled header.
@@ -1483,7 +1482,7 @@
     CICleanup(Clang.get());
 
   Clang->setInvocation(&*PreambleInvocation);
-  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
+  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
   
   // Set up diagnostics, capturing all of the diagnostics produced.
   Clang->setDiagnostics(&getDiagnostics());
@@ -1509,9 +1508,9 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
          "IR inputs not support here!");
   
   // Clear out old caches and data.
@@ -1530,8 +1529,7 @@
   
   llvm::OwningPtr<PrecompilePreambleAction> Act;
   Act.reset(new PrecompilePreambleAction(*this));
-  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
-                            Clang->getFrontendOpts().Inputs[0].first)) {
+  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
     llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
     Preamble.clear();
     PreambleRebuildCounter = DefaultPreambleRebuildInterval;
@@ -1599,7 +1597,7 @@
   
   return CreatePaddedMainFileBuffer(NewPreamble.first, 
                                     PreambleReservedSize,
-                                    FrontendOpts.Inputs[0].second);
+                                    FrontendOpts.Inputs[0].File);
 }
 
 void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
@@ -1618,7 +1616,7 @@
 }
 
 StringRef ASTUnit::getMainFileName() const {
-  return Invocation->getFrontendOpts().Inputs[0].second;
+  return Invocation->getFrontendOpts().Inputs[0].File;
 }
 
 ASTUnit *ASTUnit::create(CompilerInvocation *CI,
@@ -1690,7 +1688,7 @@
     CICleanup(Clang.get());
 
   Clang->setInvocation(CI);
-  AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
+  AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
     
   // Set up diagnostics, capturing any diagnostics that would
   // otherwise be dropped.
@@ -1711,9 +1709,9 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
          "IR inputs not supported here!");
 
   // Configure the various subsystems.
@@ -1740,9 +1738,7 @@
   llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
     ActCleanup(TrackerAct.get());
 
-  if (!Act->BeginSourceFile(*Clang.get(),
-                            Clang->getFrontendOpts().Inputs[0].second,
-                            Clang->getFrontendOpts().Inputs[0].first))
+  if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
     return 0;
 
   if (Persistent && !TrackerAct) {
@@ -2255,7 +2251,7 @@
     CICleanup(Clang.get());
 
   Clang->setInvocation(&*CCInvocation);
-  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
+  OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].File;
     
   // Set up diagnostics, capturing any diagnostics produced.
   Clang->setDiagnostics(&Diag);
@@ -2281,9 +2277,9 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_AST &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].Kind != IK_LLVM_IR &&
          "IR inputs not support here!");
 
   
@@ -2358,8 +2354,7 @@
   
   llvm::OwningPtr<SyntaxOnlyAction> Act;
   Act.reset(new SyntaxOnlyAction);
-  if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
-                           Clang->getFrontendOpts().Inputs[0].first)) {
+  if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) {
     if (OverrideMainBuffer) {
       std::string ModName = getPreambleFile(this);
       TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index f1aa8a1..9694bc0 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -63,7 +63,7 @@
   assert(!includes.empty() && "No '-chain-include' in options!");
 
   llvm::OwningPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
-  InputKind IK = CI.getFrontendOpts().Inputs[0].first;
+  InputKind IK = CI.getFrontendOpts().Inputs[0].Kind;
 
   SmallVector<llvm::MemoryBuffer *, 4> serialBufs;
   SmallVector<std::string, 4> serialBufNames;
@@ -82,7 +82,8 @@
     CInvok->getPreprocessorOpts().Macros.clear();
     
     CInvok->getFrontendOpts().Inputs.clear();
-    CInvok->getFrontendOpts().Inputs.push_back(std::make_pair(IK, includes[i]));
+    CInvok->getFrontendOpts().Inputs.push_back(FrontendInputFile(includes[i],
+                                                                 IK));
 
     TextDiagnosticPrinter *DiagClient =
       new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 1f0d87c..c3f3e37 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -648,13 +648,11 @@
     llvm::EnableStatistics();
 
   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
-    const std::string &InFile = getFrontendOpts().Inputs[i].second;
-
     // Reset the ID tables if we are reusing the SourceManager.
     if (hasSourceManager())
       getSourceManager().clearIDTables();
 
-    if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
+    if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) {
       Act.Execute();
       Act.EndSourceFile();
     }
@@ -1019,7 +1017,8 @@
   if (const FileEntry *ModuleMapFile
                                   = ModMap.getContainingModuleMapFile(Module)) {
     // Use the module map where this module resides.
-    FrontendOpts.Inputs.push_back(std::make_pair(IK, ModuleMapFile->getName()));
+    FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), 
+                                                    IK));
   } else {
     // Create a temporary module map file.
     TempModuleMapFileName = Module->Name;
@@ -1037,7 +1036,7 @@
     llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
     Module->print(OS);
     FrontendOpts.Inputs.push_back(
-      std::make_pair(IK, TempModuleMapFileName.str().str()));
+      FrontendInputFile(TempModuleMapFileName.str().str(), IK));
   }
 
   // Don't free the remapped file buffers; they are owned by our caller.
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 60e3442..a64b8cf 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -492,17 +492,17 @@
 
   bool NeedLang = false;
   for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
-    if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
-        Opts.Inputs[i].first)
+    if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].File) !=
+        Opts.Inputs[i].Kind)
       NeedLang = true;
   if (NeedLang) {
     Res.push_back("-x");
-    Res.push_back(getInputKindName(Opts.Inputs[0].first));
+    Res.push_back(getInputKindName(Opts.Inputs[0].Kind));
   }
   for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
-    assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
+    assert((!NeedLang || Opts.Inputs[i].Kind == Opts.Inputs[0].Kind) &&
            "Unable to represent this input vector!");
-    Res.push_back(Opts.Inputs[i].second);
+    Res.push_back(Opts.Inputs[i].File);
   }
 
   if (!Opts.OutputFile.empty()) {
@@ -1463,7 +1463,7 @@
       if (i == 0)
         DashX = IK;
     }
-    Opts.Inputs.push_back(std::make_pair(IK, Inputs[i]));
+    Opts.Inputs.push_back(FrontendInputFile(Inputs[i], IK));
   }
 
   return DashX;
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 7e4ae02..42ba4d5 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -115,10 +115,9 @@
 
 FrontendAction::~FrontendAction() {}
 
-void FrontendAction::setCurrentFile(StringRef Value, InputKind Kind,
-                                    ASTUnit *AST) {
-  CurrentFile = Value;
-  CurrentFileKind = Kind;
+void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
+                                     ASTUnit *AST) {
+  this->CurrentInput = CurrentInput;
   CurrentASTUnit.reset(AST);
 }
 
@@ -156,11 +155,10 @@
 }
 
 bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
-                                     StringRef Filename,
-                                     InputKind InputKind) {
+                                     const FrontendInputFile &Input) {
   assert(!Instance && "Already processing a source file!");
-  assert(!Filename.empty() && "Unexpected empty filename!");
-  setCurrentFile(Filename, InputKind);
+  assert(!Input.File.empty() && "Unexpected empty filename!");
+  setCurrentInput(Input);
   setCompilerInstance(&CI);
 
   if (!BeginInvocation(CI))
@@ -168,7 +166,7 @@
 
   // AST files follow a very different path, since they share objects via the
   // AST unit.
-  if (InputKind == IK_AST) {
+  if (Input.Kind == IK_AST) {
     assert(!usesPreprocessorOnly() &&
            "Attempt to pass AST file to preprocessor only action!");
     assert(hasASTFileSupport() &&
@@ -176,12 +174,12 @@
 
     llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
     std::string Error;
-    ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags,
+    ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags,
                                             CI.getFileSystemOpts());
     if (!AST)
       goto failure;
 
-    setCurrentFile(Filename, InputKind, AST);
+    setCurrentInput(Input, AST);
 
     // Set the shared objects, these are reset when we finish processing the
     // file, otherwise the CompilerInstance will happily destroy them.
@@ -191,11 +189,11 @@
     CI.setASTContext(&AST->getASTContext());
 
     // Initialize the action.
-    if (!BeginSourceFileAction(CI, Filename))
+    if (!BeginSourceFileAction(CI, Input.File))
       goto failure;
 
     /// Create the AST consumer.
-    CI.setASTConsumer(CreateWrappedASTConsumer(CI, Filename));
+    CI.setASTConsumer(CreateWrappedASTConsumer(CI, Input.File));
     if (!CI.hasASTConsumer())
       goto failure;
 
@@ -209,7 +207,7 @@
     CI.createSourceManager(CI.getFileManager());
 
   // IR files bypass the rest of initialization.
-  if (InputKind == IK_LLVM_IR) {
+  if (Input.Kind == IK_LLVM_IR) {
     assert(hasIRSupport() &&
            "This action does not have IR file support!");
 
@@ -217,7 +215,7 @@
     CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0);
 
     // Initialize the action.
-    if (!BeginSourceFileAction(CI, Filename))
+    if (!BeginSourceFileAction(CI, Input.File))
       goto failure;
 
     return true;
@@ -231,7 +229,7 @@
                                            &CI.getPreprocessor());
 
   // Initialize the action.
-  if (!BeginSourceFileAction(CI, Filename))
+  if (!BeginSourceFileAction(CI, Input.File))
     goto failure;
 
   /// Create the AST context and consumer unless this is a preprocessor only
@@ -240,7 +238,7 @@
     CI.createASTContext();
 
     llvm::OwningPtr<ASTConsumer> Consumer(
-        CreateWrappedASTConsumer(CI, Filename));
+                                   CreateWrappedASTConsumer(CI, Input.File));
     if (!Consumer)
       goto failure;
 
@@ -300,7 +298,7 @@
   }
 
   CI.getDiagnosticClient().EndSourceFile();
-  setCurrentFile("", IK_None);
+  setCurrentInput(FrontendInputFile());
   setCompilerInstance(0);
   return false;
 }
@@ -375,7 +373,7 @@
   }
 
   setCompilerInstance(0);
-  setCurrentFile("", IK_None);
+  setCurrentInput(FrontendInputFile());
 }
 
 //===----------------------------------------------------------------------===//
@@ -419,7 +417,7 @@
 }
 bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI,
                                                   StringRef Filename) {
-  WrappedAction->setCurrentFile(getCurrentFile(), getCurrentFileKind());
+  WrappedAction->setCurrentInput(getCurrentInput());
   WrappedAction->setCompilerInstance(&CI);
   return WrappedAction->BeginSourceFileAction(CI, Filename);
 }
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 2261b30..272474c 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -255,7 +255,8 @@
   if (UmbrellaHeader && HeaderContents.empty()) {
     // Simple case: we have an umbrella header and there are no additional
     // includes, we can just parse the umbrella header directly.
-    setCurrentFile(UmbrellaHeader->getName(), getCurrentFileKind());
+    setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
+                                      getCurrentFileKind()));
     return true;
   }
   
@@ -311,9 +312,8 @@
                                                        ModTime);
   llvm::MemoryBuffer *HeaderContentsBuf
     = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
-  CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
-  
-  setCurrentFile(HeaderName, getCurrentFileKind());
+  CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);  
+  setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind()));
   return true;
 }
 
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 88e36ad..c8d6be6 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -40,7 +40,7 @@
 // DiagnosticConsumer interface.
 
 void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
-                                             const Preprocessor *PP) {
+                                               const Preprocessor *PP) {
   // FIXME: Const hack, we screw up the preprocessor but in practice its ok
   // because it doesn't get reused. It would be better if we could make a copy
   // though.
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp
index 3dc4c11..9523ebc 100644
--- a/tools/arcmt-test/arcmt-test.cpp
+++ b/tools/arcmt-test/arcmt-test.cpp
@@ -129,9 +129,7 @@
   if (!CI.getLangOpts()->ObjC1)
     return false;
 
-  arcmt::checkForManualIssues(CI,
-                              CI.getFrontendOpts().Inputs[0].second,
-                              CI.getFrontendOpts().Inputs[0].first,
+  arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], 
                               Diags->getClient());
   return Diags->getClient()->getNumErrors() > 0;
 }
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index 6bffc6b..c42ef23 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -18,6 +18,7 @@
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendAction.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "clang/AST/ASTConsumer.h"