Refactor frontend InputKind to prepare for treating module maps as a distinct kind of input.

No functionality change intended.

llvm-svn: 301442
diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp
index 2acdc64..32ee9d3 100644
--- a/clang/lib/Frontend/ASTUnit.cpp
+++ b/clang/lib/Frontend/ASTUnit.cpp
@@ -1076,9 +1076,11 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
+             InputKind::Source &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
+             InputKind::LLVM_IR &&
          "IR inputs not support here!");
 
   // Configure the various subsystems.
@@ -1552,9 +1554,11 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
+             InputKind::Source &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
+             InputKind::LLVM_IR &&
          "IR inputs not support here!");
   
   // Clear out old caches and data.
@@ -1810,10 +1814,12 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
+             InputKind::Source &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
-         "IR inputs not supported here!");
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
+             InputKind::LLVM_IR &&
+         "IR inputs not support here!");
 
   // Configure the various subsystems.
   AST->TheSema.reset();
@@ -2399,11 +2405,12 @@
   
   assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
          "Invocation must have exactly one source file!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==
+             InputKind::Source &&
          "FIXME: AST inputs not yet supported here!");
-  assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR &&
+  assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=
+             InputKind::LLVM_IR &&
          "IR inputs not support here!");
-
   
   // Use the source and file managers that we were given.
   Clang->setFileManager(&FileMgr);
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 8b4b169..dc30983 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1015,14 +1015,14 @@
 
 /// \brief Determine the appropriate source input kind based on language
 /// options.
-static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) {
+static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) {
   if (LangOpts.OpenCL)
-    return IK_OpenCL;
+    return InputKind::OpenCL;
   if (LangOpts.CUDA)
-    return IK_CUDA;
+    return InputKind::CUDA;
   if (LangOpts.ObjC1)
-    return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC;
-  return LangOpts.CPlusPlus? IK_CXX : IK_C;
+    return LangOpts.CPlusPlus ? InputKind::ObjCXX : InputKind::ObjC;
+  return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C;
 }
 
 /// \brief Compile a module file for the given module, using the options 
@@ -1082,7 +1082,8 @@
   // Force implicitly-built modules to hash the content of the module file.
   HSOpts.ModulesHashContent = true;
   FrontendOpts.Inputs.clear();
-  InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
+  InputKind IK(getLanguageFromOptions(*Invocation->getLangOpts()),
+               InputKind::ModuleMap);
 
   // Don't free the remapped file buffers; they are owned by our caller.
   PPOpts.RetainRemappedFileBuffers = true;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 8cdb829..d74c659 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -81,7 +81,7 @@
 static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
                                      DiagnosticsEngine &Diags) {
   unsigned DefaultOpt = 0;
-  if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable))
+  if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
     DefaultOpt = 2;
 
   if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
@@ -652,7 +652,7 @@
   Opts.EmitSummaryIndex = A && A->containsValue("thin");
   Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false);
   if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) {
-    if (IK != IK_LLVM_IR)
+    if (IK.getLanguage() != InputKind::LLVM_IR)
       Diags.Report(diag::err_drv_argument_only_allowed_with)
           << A->getAsString(Args) << "-x ir";
     Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ);
@@ -1347,42 +1347,33 @@
       << "ARC migration" << "ObjC migration";
   }
 
-  InputKind DashX = IK_None;
+  InputKind DashX(InputKind::Unknown);
   if (const Arg *A = Args.getLastArg(OPT_x)) {
-    DashX = llvm::StringSwitch<InputKind>(A->getValue())
-      .Case("c", IK_C)
-      .Case("cl", IK_OpenCL)
-      .Case("cuda", IK_CUDA)
-      .Case("c++", IK_CXX)
-      .Case("objective-c", IK_ObjC)
-      .Case("objective-c++", IK_ObjCXX)
-      .Case("cpp-output", IK_PreprocessedC)
-      .Case("assembler-with-cpp", IK_Asm)
-      .Case("c++-cpp-output", IK_PreprocessedCXX)
-      .Case("cuda-cpp-output", IK_PreprocessedCuda)
-      .Case("objective-c-cpp-output", IK_PreprocessedObjC)
-      .Case("objc-cpp-output", IK_PreprocessedObjC)
-      .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX)
-      .Case("objc++-cpp-output", IK_PreprocessedObjCXX)
-      .Case("c-header", IK_C)
-      .Case("cl-header", IK_OpenCL)
-      .Case("objective-c-header", IK_ObjC)
-      .Case("c++-header", IK_CXX)
-      .Case("objective-c++-header", IK_ObjCXX)
-      .Cases("ast", "pcm", IK_AST)
-      .Case("ir", IK_LLVM_IR)
-      .Case("renderscript", IK_RenderScript)
-      .Default(IK_None);
-    if (DashX == IK_None)
+    StringRef XValue = A->getValue();
+    DashX = llvm::StringSwitch<InputKind>(XValue)
+      .Cases("c", "c-header", "cpp-output", InputKind::C)
+      .Cases("cl", "cl-header", InputKind::OpenCL)
+      .Cases("cuda", "cuda-cpp-output", InputKind::CUDA)
+      .Cases("c++", "c++-header", "c++-cpp-output", InputKind::CXX)
+      .Cases("objective-c", "objective-c-header",
+             "objective-c-cpp-output", "objc-cpp-output",
+             InputKind::ObjC)
+      .Cases("objective-c++", "objective-c++-header",
+             "objective-c++-cpp-output", "objc++-cpp-output",
+             InputKind::ObjCXX)
+      .Case("renderscript", InputKind::RenderScript)
+      .Case("assembler-with-cpp", InputKind::Asm)
+      .Cases("ast", "pcm",
+             InputKind(InputKind::Unknown, InputKind::Precompiled))
+      .Case("ir", InputKind::LLVM_IR)
+      .Default(InputKind::Unknown);
+    if (DashX.isUnknown())
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << A->getValue();
-    IsHeaderFile = llvm::StringSwitch<bool>(A->getValue())
-      .Case("c-header", true)
-      .Case("cl-header", true)
-      .Case("objective-c-header", true)
-      .Case("c++-header", true)
-      .Case("objective-c++-header", true)
-      .Default(false);
+
+    if (XValue.endswith("cpp-output"))
+      DashX = DashX.getPreprocessed();
+    IsHeaderFile = XValue.endswith("-header");
   }
 
   // '-' is the default input if none is given.
@@ -1392,9 +1383,12 @@
     Inputs.push_back("-");
   for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
     InputKind IK = DashX;
-    if (IK == IK_None) {
+    if (IK.isUnknown()) {
       IK = FrontendOptions::getInputKindForExtension(
         StringRef(Inputs[i]).rsplit('.').second);
+      // FIXME: Warn on this?
+      if (IK.isUnknown())
+        IK = InputKind::C;
       // FIXME: Remove this hack.
       if (i == 0)
         DashX = IK;
@@ -1564,53 +1558,48 @@
   // Set some properties which depend solely on the input kind; it would be nice
   // to move these to the language standard, and have the driver resolve the
   // input kind + language standard.
-  if (IK == IK_Asm) {
+  //
+  // FIXME: Perhaps a better model would be for a single source file to have
+  // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std)
+  // simultaneously active?
+  if (IK.getLanguage() == InputKind::Asm) {
     Opts.AsmPreprocessor = 1;
-  } else if (IK == IK_ObjC ||
-             IK == IK_ObjCXX ||
-             IK == IK_PreprocessedObjC ||
-             IK == IK_PreprocessedObjCXX) {
+  } else if (IK.isObjectiveC()) {
     Opts.ObjC1 = Opts.ObjC2 = 1;
   }
 
   if (LangStd == LangStandard::lang_unspecified) {
     // Based on the base language, pick one.
-    switch (IK) {
-    case IK_None:
-    case IK_AST:
-    case IK_LLVM_IR:
+    switch (IK.getLanguage()) {
+    case InputKind::Unknown:
+    case InputKind::LLVM_IR:
       llvm_unreachable("Invalid input kind!");
-    case IK_OpenCL:
+    case InputKind::OpenCL:
       LangStd = LangStandard::lang_opencl;
       break;
-    case IK_CUDA:
-    case IK_PreprocessedCuda:
+    case InputKind::CUDA:
       LangStd = LangStandard::lang_cuda;
       break;
-    case IK_Asm:
-    case IK_C:
-    case IK_PreprocessedC:
+    case InputKind::Asm:
+    case InputKind::C:
       // The PS4 uses C99 as the default C standard.
       if (T.isPS4())
         LangStd = LangStandard::lang_gnu99;
       else
         LangStd = LangStandard::lang_gnu11;
       break;
-    case IK_ObjC:
-    case IK_PreprocessedObjC:
+    case InputKind::ObjC:
       LangStd = LangStandard::lang_gnu11;
       break;
-    case IK_CXX:
-    case IK_PreprocessedCXX:
-    case IK_ObjCXX:
-    case IK_PreprocessedObjCXX:
+    case InputKind::CXX:
+    case InputKind::ObjCXX:
       // The PS4 uses C++11 as the default C++ standard.
       if (T.isPS4())
         LangStd = LangStandard::lang_gnucxx11;
       else
         LangStd = LangStandard::lang_gnucxx98;
       break;
-    case IK_RenderScript:
+    case InputKind::RenderScript:
       LangStd = LangStandard::lang_c99;
       break;
     }
@@ -1631,7 +1620,7 @@
   Opts.ImplicitInt = Std.hasImplicitInt();
 
   // Set OpenCL Version.
-  Opts.OpenCL = Std.isOpenCL() || IK == IK_OpenCL;
+  Opts.OpenCL = Std.isOpenCL() || IK.getLanguage() == InputKind::OpenCL;
   if (LangStd == LangStandard::lang_opencl)
     Opts.OpenCLVersion = 100;
   else if (LangStd == LangStandard::lang_opencl11)
@@ -1655,13 +1644,13 @@
     }
   }
 
-  Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda ||
+  Opts.CUDA = IK.getLanguage() == InputKind::CUDA ||
               LangStd == LangStandard::lang_cuda;
   if (Opts.CUDA)
     // Set default FP_CONTRACT to FAST.
     Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
 
-  Opts.RenderScript = IK == IK_RenderScript;
+  Opts.RenderScript = IK.getLanguage() == InputKind::RenderScript;
   if (Opts.RenderScript) {
     Opts.NativeHalfType = 1;
     Opts.NativeHalfArgsAndReturns = 1;
@@ -1705,55 +1694,57 @@
 /// Check if input file kind and language standard are compatible.
 static bool IsInputCompatibleWithStandard(InputKind IK,
                                           const LangStandard &S) {
-  switch (IK) {
-  case IK_C:
-  case IK_ObjC:
-  case IK_PreprocessedC:
-  case IK_PreprocessedObjC:
-    if (S.isC89() || S.isC99())
-      return true;
-    break;
-  case IK_CXX:
-  case IK_ObjCXX:
-  case IK_PreprocessedCXX:
-  case IK_PreprocessedObjCXX:
-    if (S.isCPlusPlus())
-      return true;
-    break;
-  case IK_OpenCL:
-    if (S.isOpenCL())
-      return true;
-    break;
-  case IK_CUDA:
-  case IK_PreprocessedCuda:
-    if (S.isCPlusPlus())
-      return true;
-    break;
-  default:
-    // For other inputs, accept (and ignore) all -std= values.
+  switch (IK.getLanguage()) {
+  case InputKind::Unknown:
+  case InputKind::LLVM_IR:
+    llvm_unreachable("should not parse language flags for this input");
+
+  case InputKind::C:
+  case InputKind::ObjC:
+    // FIXME: Should this really allow OpenCL standards?
+    return S.isC89() || S.isC99();
+
+  case InputKind::OpenCL:
+    return S.isOpenCL();
+
+  case InputKind::RenderScript:
+    // FIXME: Should this really allow -std=c++98 etc?
+    return true;
+
+  case InputKind::CXX:
+  case InputKind::ObjCXX:
+    // FIXME: Should this really allow -std=cuda?
+    return S.isCPlusPlus();
+
+  case InputKind::CUDA:
+    return S.isCPlusPlus();
+
+  case InputKind::Asm:
+    // Accept (and ignore) all -std= values.
+    // FIXME: The -std= value is not ignored; it affects the tokenization
+    // and preprocessing rules if we're preprocessing this asm input.
     return true;
   }
-  return false;
+
+  llvm_unreachable("unexpected input language");
 }
 
 /// Get language name for given input kind.
 static const StringRef GetInputKindName(InputKind IK) {
-  switch (IK) {
-  case IK_C:
-  case IK_ObjC:
-  case IK_PreprocessedC:
-  case IK_PreprocessedObjC:
+  switch (IK.getLanguage()) {
+  case InputKind::C:
+  case InputKind::ObjC:
+    // FIXME: Don't lump these together.
     return "C/ObjC";
-  case IK_CXX:
-  case IK_ObjCXX:
-  case IK_PreprocessedCXX:
-  case IK_PreprocessedObjCXX:
+  case InputKind::CXX:
+  case InputKind::ObjCXX:
+    // FIXME: Don't lump these together.
     return "C++/ObjC++";
-  case IK_OpenCL:
+  case InputKind::OpenCL:
     return "OpenCL";
-  case IK_CUDA:
-  case IK_PreprocessedCuda:
+  case InputKind::CUDA:
     return "CUDA";
+    // FIXME: Include names for other options, and make this switch exhaustive.
   default:
     llvm_unreachable("Cannot decide on name for InputKind!");
   }
@@ -2533,7 +2524,8 @@
                               Res.getTargetOpts());
   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args,
                         Res.getFileSystemOpts().WorkingDir);
-  if (DashX == IK_AST || DashX == IK_LLVM_IR) {
+  if (DashX.getFormat() == InputKind::Precompiled ||
+      DashX.getLanguage() == InputKind::LLVM_IR) {
     // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the
     // PassManager in BackendUtil.cpp. They need to be initializd no matter
     // what the input type is.
@@ -2547,8 +2539,9 @@
                         Diags, LangOpts.Sanitize);
   } else {
     // Other LangOpts are only initialzed when the input is not AST or LLVM IR.
+    // FIXME: Should we really be calling this for an InputKind::Asm input?
     ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
-      Res.getPreprocessorOpts(), Diags);
+                  Res.getPreprocessorOpts(), Diags);
     if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
       LangOpts.ObjCExceptions = 1;
   }
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index 0dd07d9..9b1d60d 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -238,7 +238,8 @@
 
   // AST files follow a very different path, since they share objects via the
   // AST unit.
-  if (Input.getKind() == IK_AST) {
+  if (Input.getKind().getFormat() == InputKind::Precompiled) {
+    // FIXME: We should not be asserting on bad command-line arguments.
     assert(!usesPreprocessorOnly() &&
            "Attempt to pass AST file to preprocessor only action!");
     assert(hasASTFileSupport() &&
@@ -297,7 +298,7 @@
     CI.createSourceManager(CI.getFileManager());
 
   // IR files bypass the rest of initialization.
-  if (Input.getKind() == IK_LLVM_IR) {
+  if (Input.getKind().getLanguage() == InputKind::LLVM_IR) {
     assert(hasIRSupport() &&
            "This action does not have IR file support!");
 
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index e818038..1fce1e5 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -777,29 +777,27 @@
 }
 
 void PrintPreambleAction::ExecuteAction() {
-  switch (getCurrentFileKind()) {
-  case IK_C:
-  case IK_CXX:
-  case IK_ObjC:
-  case IK_ObjCXX:
-  case IK_OpenCL:
-  case IK_CUDA:
+  switch (getCurrentFileKind().getLanguage()) {
+  case InputKind::C:
+  case InputKind::CXX:
+  case InputKind::ObjC:
+  case InputKind::ObjCXX:
+  case InputKind::OpenCL:
+  case InputKind::CUDA:
     break;
       
-  case IK_None:
-  case IK_Asm:
-  case IK_PreprocessedC:
-  case IK_PreprocessedCuda:
-  case IK_PreprocessedCXX:
-  case IK_PreprocessedObjC:
-  case IK_PreprocessedObjCXX:
-  case IK_AST:
-  case IK_LLVM_IR:
-  case IK_RenderScript:
+  case InputKind::Unknown:
+  case InputKind::Asm:
+  case InputKind::LLVM_IR:
+  case InputKind::RenderScript:
     // We can't do anything with these.
     return;
   }
 
+  // We don't expect to find any #include directives in a preprocessed input.
+  if (getCurrentFileKind().isPreprocessed())
+    return;
+
   CompilerInstance &CI = getCompilerInstance();
   auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
   if (Buffer) {
diff --git a/clang/lib/Frontend/FrontendOptions.cpp b/clang/lib/Frontend/FrontendOptions.cpp
index 6a82084..eec2410 100644
--- a/clang/lib/Frontend/FrontendOptions.cpp
+++ b/clang/lib/Frontend/FrontendOptions.cpp
@@ -13,22 +13,22 @@
 
 InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) {
   return llvm::StringSwitch<InputKind>(Extension)
-    .Cases("ast", "pcm", IK_AST)
-    .Case("c", IK_C)
-    .Cases("S", "s", IK_Asm)
-    .Case("i", IK_PreprocessedC)
-    .Case("ii", IK_PreprocessedCXX)
-    .Case("cui", IK_PreprocessedCuda)
-    .Case("m", IK_ObjC)
-    .Case("mi", IK_PreprocessedObjC)
-    .Cases("mm", "M", IK_ObjCXX)
-    .Case("mii", IK_PreprocessedObjCXX)
-    .Cases("C", "cc", "cp", IK_CXX)
-    .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX)
-    .Case("cppm", IK_CXX)
-    .Case("iim", IK_PreprocessedCXX)
-    .Case("cl", IK_OpenCL)
-    .Case("cu", IK_CUDA)
-    .Cases("ll", "bc", IK_LLVM_IR)
-    .Default(IK_C);
+    .Cases("ast", "pcm", InputKind(InputKind::Unknown, InputKind::Precompiled))
+    .Case("c", InputKind::C)
+    .Cases("S", "s", InputKind::Asm)
+    .Case("i", InputKind(InputKind::C, true))
+    .Case("ii", InputKind(InputKind::CXX, true))
+    .Case("cui", InputKind(InputKind::CUDA, true))
+    .Case("m", InputKind::ObjC)
+    .Case("mi", InputKind(InputKind::ObjC, true))
+    .Cases("mm", "M", InputKind::ObjCXX)
+    .Case("mii", InputKind(InputKind::ObjCXX, true))
+    .Cases("C", "cc", "cp", InputKind::CXX)
+    .Cases("cpp", "CPP", "c++", "cxx", "hpp", InputKind::CXX)
+    .Case("cppm", InputKind::CXX)
+    .Case("iim", InputKind(InputKind::CXX, true))
+    .Case("cl", InputKind::OpenCL)
+    .Case("cu", InputKind::CUDA)
+    .Cases("ll", "bc", InputKind::LLVM_IR)
+    .Default(InputKind::Unknown);
 }
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 0dd04e8..9257dca 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -1041,6 +1041,8 @@
 
   // Install things like __POWERPC__, __GNUC__, etc into the macro table.
   if (InitOpts.UsePredefines) {
+    // FIXME: This will create multiple definitions for most of the predefined
+    // macros. This is not the right way to handle this.
     if (LangOpts.CUDA && PP.getAuxTargetInfo())
       InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts,
                                  Builder);