// Copyright 2010 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.


#ifndef _WIN32
#include <dirent.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#else
#include "config_win.h"
#endif
#ifdef __FreeBSD__
#include <sys/param.h>
#endif

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "absl/strings/match.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "autolock_timer.h"
#include "clang_modules/modulemap/cache.h"
#include "clang_tidy_flags.h"
#include "compiler_flags.h"
#include "compiler_info.h"
#include "content.h"
#include "counterz.h"
#include "cpp_directive.h"
#include "cpp_directive_parser.h"
#include "cpp_include_processor.h"
#include "cpp_parser.h"
#include "directive_filter.h"
#include "env_flags.h"
#include "file_dir.h"
#include "filesystem.h"
#include "flag_parser.h"
#include "gcc_flags.h"
#include "glog/logging.h"
#include "glog/stl_logging.h"
#include "glog/vlog_is_on.h"
#include "include_cache.h"
#include "include_file_utils.h"
#include "ioutil.h"
#include "list_dir_cache.h"
#include "lockhelper.h"
#include "path.h"
#include "path_resolver.h"
#include "scoped_fd.h"
#include "util.h"
#include "vc_flags.h"

#ifdef _WIN32
#include "path_resolver.h"
#include "posix_helper_win.h"
#endif

using std::string;

namespace devtools_goma {

namespace {

// Reads content from |filepath| and set |next_current_directory|.
// If |file_stat_cache| has a FileStat for |filepath|, we use it.
// Otherwise we take FileStat for |filepath| and stores it to |file_stat_cache|.
// We don't take |file_stat_cache| ownership.
IncludeItem TryInclude(const string& cwd,
                       const string& filepath,
                       string* next_current_directory,
                       FileStatCache* file_stat_cache) {
  GOMA_COUNTERZ("TryInclude");

  const string abs_filepath = file::JoinPathRespectAbsolute(cwd, filepath);
  FileStat file_stat(file_stat_cache->Get(abs_filepath));
  if (!file_stat.IsValid()) {
    return IncludeItem();
  }

  if (file_stat.is_directory) {
    VLOG(2) << "TryInclude but dir:" << abs_filepath;
    return IncludeItem();
  }

  CHECK(IncludeCache::IsEnabled())
      << "IncludeCache is not enabled. "
      << "You forget to call IncludeCache::Init()?";

  *next_current_directory = string(file::Dirname(filepath));
  return IncludeCache::instance()->GetIncludeItem(abs_filepath, file_stat);
}

}  // anonymous namespace

class IncludePathsObserver : public CppParser::IncludeObserver {
 public:
  IncludePathsObserver(std::string cwd,
                       CppParser* parser,
                       std::set<string>* shared_include_files,
                       FileStatCache* file_stat_cache,
                       IncludeFileFinder* include_file_finder)
      : cwd_(std::move(cwd)),
        parser_(parser),
        shared_include_files_(shared_include_files),
        file_stat_cache_(file_stat_cache),
        include_file_finder_(include_file_finder) {
    CHECK(parser_);
    CHECK(shared_include_files_);
    CHECK(file_stat_cache_);
  }

  bool HandleInclude(const string& path,
                     const string& current_directory,
                     const string& current_filepath,
                     char quote_char,  // '"' or '<'
                     int include_dir_index) override {
    // shared_include_files_ contains a set of include files for compilers.
    // It's output variables of IncludePathsObserver.

    // parser_->IsProcessedFile(filepath) indicates filepath was already parsed
    // and no need to parse it again.
    // So, if it returns true, shared_include_files_ must have filepath.
    // In other words, there is a case shared_include_files_ have the filepath,
    // but parser_->IsProcessedFile(filepath) returns false.  It means
    // the filepath once parsed, but it needs to parse it again (for example
    // macro changed).

    // parser_->AddFileInput should be called to let parser_ parse the file.

    // include_dir_index is an index to start searching from.
    //
    // for #include "...", include_dir_index is current dir index of
    // the file that is including the path.  note that include_dir_index
    // would not be kCurrentDirIncludeDirIndex, since CppParser needs
    // to keep dir index for include file. i.e. an included file will have
    // the same include dir index as file that includes the file.
    //
    // for #include <...>, it is bracket_include_dir_index.
    //
    // for #include_next, it will be next include dir index of file
    // that is including the path. (always quote_char=='<').

    CHECK(!path.empty()) << current_filepath;

    VLOG(2) << current_filepath << ": including " << quote_char << path
            << " dir:" << current_directory
            << " include_dir_index:" << include_dir_index;

    string next_current_directory;
    string filepath;

    if (quote_char == '"') {
      // Look for current directory.
      if (HandleIncludeInDir(current_directory, path, include_dir_index,
                             &next_current_directory)) {
        return true;
      }
      VLOG(2) << "not found in curdir:" << current_directory;

      // If not found in current directory, try all include paths.
      include_dir_index = CppParser::kIncludeDirIndexStarting;
    }

    // Look for include dirs from |include_dir_index|.
    int dir_index = include_dir_index;
    if (!include_file_finder_->Lookup(path, &filepath, &dir_index) &&
        !include_file_finder_->LookupSubframework(path, current_directory,
                                                  &filepath)) {
      VLOG(2) << "Not found: " << path;
      return false;
    }

    VLOG(3) << "Lookup => " << filepath << " dir_index=" << dir_index;

    if (parser_->IsProcessedFile(filepath, include_dir_index)) {
      VLOG(2) << "Already processed:" << quote_char << filepath;
      return true;
    }

    IncludeItem include_item =
        TryInclude(cwd_, filepath, &next_current_directory, file_stat_cache_);
    if (include_item.IsValid()) {
      if (IncludeFileFinder::gch_hack_enabled() &&
          absl::EndsWith(filepath, GOMA_GCH_SUFFIX) &&
          !absl::EndsWith(path, GOMA_GCH_SUFFIX)) {
        VLOG(2) << "Found a precompiled header: " << filepath;
        shared_include_files_->insert(filepath);
        return true;
      }

      VLOG(2) << "Looking into " << filepath << " index=" << dir_index;
      shared_include_files_->insert(filepath);
      parser_->AddFileInput(std::move(include_item), filepath,
                            next_current_directory, dir_index);
      return true;
    }
    VLOG(2) << "include file not found in dir_cache?";
    return false;
  }

  bool HasInclude(const string& path,
                  const string& current_directory,
                  const string& current_filepath,
                  char quote_char,  // '"' or '<'
                  int include_dir_index) override {
    CHECK(!path.empty()) << current_filepath;

    string next_current_directory;
    string filepath;

    if (quote_char == '"') {
      if (HasIncludeInDir(current_directory, path, current_filepath)) {
        return true;
      }
      include_dir_index = CppParser::kIncludeDirIndexStarting;
    }

    int dir_index = include_dir_index;
    if (!include_file_finder_->Lookup(path, &filepath, &dir_index)) {
      VLOG(2) << "Not found: " << path;
      return false;
    }
    std::string abs_filepath =
        file::JoinPathRespectAbsolute(cwd_, filepath);
    if (shared_include_files_->count(filepath) ||
        access(abs_filepath.c_str(), R_OK) == 0) {
      DCHECK(!file::IsDirectory(abs_filepath, file::Defaults()).ok())
          << abs_filepath;
      shared_include_files_->insert(std::move(filepath));
      return true;
    }
    return false;
  }

 private:
  bool CanPruneWithTopPathComponent(const string& dir, const string& path) {
    // we don't need to care about case ignoreness here.
    // we'll access filesystem, so filesystem would handle case senstiveness.
    const std::string& dir_with_top_path_component = file::JoinPath(
        dir, IncludeFileFinder::TopPathComponent(path, false));
    return !file_stat_cache_->Get(dir_with_top_path_component).IsValid();
  }

  bool HandleIncludeInDir(const string& dir,
                          const string& path,
                          int include_dir_index,
                          string* next_current_directory) {
    GOMA_COUNTERZ("handle include try");
    if (CanPruneWithTopPathComponent(file::JoinPathRespectAbsolute(cwd_, dir),
                                     path)) {
      VLOG(2) << "can prune with top path component:"
              << " cwd=" << cwd_
              << " dir=" << dir
              << " path=" << path;
      GOMA_COUNTERZ("handle include pruned");
      return false;
    }

    string filepath =
        PathResolver::PlatformConvert(file::JoinPathRespectAbsolute(dir, path));

    VLOG(2) << "handle include in dir: " << filepath;

    if (IncludeFileFinder::gch_hack_enabled()) {
      const string& gchpath = filepath + GOMA_GCH_SUFFIX;
      IncludeItem include_item(
          TryInclude(cwd_, gchpath, next_current_directory, file_stat_cache_));
      if (include_item.IsValid()) {
        VLOG(2) << "Found a pre-compiled header: " << gchpath;
        shared_include_files_->insert(gchpath);
        // We should not check the content of pre-compiled headers.
        return true;
      }
    }

    if (parser_->IsProcessedFile(filepath, include_dir_index)) {
      VLOG(2) << "Already processed: \"" << filepath << "\"";
      return true;
    }
    IncludeItem include_item =
        TryInclude(cwd_, filepath, next_current_directory, file_stat_cache_);
    if (include_item.IsValid()) {
      shared_include_files_->insert(filepath);
      parser_->AddFileInput(std::move(include_item), filepath,
                            *next_current_directory, include_dir_index);
      return true;
    }
    VLOG(2) << "include file not found in current directoy? filepath="
            << filepath;
    return false;
  }

  bool HasIncludeInDir(const string& dir,
                       const string& path,
                       const string& current_filepath) {
    std::string filepath = file::JoinPathRespectAbsolute(dir, path);
    string abs_filepath = file::JoinPathRespectAbsolute(cwd_, filepath);
    string abs_current_filepath =
        file::JoinPathRespectAbsolute(cwd_, current_filepath);
    abs_filepath = PathResolver::ResolvePath(abs_filepath);
    bool is_current = (abs_filepath == abs_current_filepath);
    if (is_current) {
      shared_include_files_->insert(std::move(filepath));
      return true;
    }
    if (!file::IsDirectory(abs_filepath, file::Defaults()).ok()) {
      if (shared_include_files_->count(filepath)) {
        return true;
      }
      if (access(abs_filepath.c_str(), R_OK) == 0) {
        shared_include_files_->insert(std::move(filepath));
        return true;
      }
      if (IncludeFileFinder::gch_hack_enabled() &&
          access((abs_filepath + GOMA_GCH_SUFFIX).c_str(), R_OK) == 0) {
        shared_include_files_->insert(filepath + GOMA_GCH_SUFFIX);
        return true;
      }
    }
    return false;
  }

  const std::string cwd_;
  CppParser* parser_;
  std::set<string>* shared_include_files_;
  FileStatCache* file_stat_cache_;

  IncludeFileFinder* include_file_finder_;

  DISALLOW_COPY_AND_ASSIGN(IncludePathsObserver);
};

class IncludeErrorObserver : public CppParser::ErrorObserver {
 public:
  IncludeErrorObserver() {}

  void HandleError(const string& error) override {
    // Note that we don't set this error observer if VLOG_IS_ON(1) is false.
    // If you need to change this code, make sure you'll modify
    // set_error_observer call in CppIncludeProcessor::GetIncludeFiles()
    // to be consistent with here.
    VLOG(1) << error;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IncludeErrorObserver);
};

static void CopyIncludeDirs(const std::vector<string>& input_dirs,
                            const string& toolchain_root,
                            std::vector<string>* output_dirs) {
  for (const auto& input_dir : input_dirs) {
    const string& dir = file::JoinPath(
        toolchain_root, PathResolver::PlatformConvert(input_dir));
    output_dirs->push_back(dir);
  }
}

#ifndef _WIN32
static void CopyOriginalFileFromHashCriteria(const string& filepath) {
  static Lock mu;

  if (access(filepath.c_str(), R_OK) == 0) {
    return;
  }

  // Only one thread can copy the GCH.
  AUTOLOCK(lock, &mu);
  if (access(filepath.c_str(), R_OK) == 0) {
    return;
  }

  const string& hash_criteria_filepath = filepath + ".gch.hash-criteria";
  std::ifstream ifs(hash_criteria_filepath.c_str());
  if (!ifs) {
    return;
  }

  string line;
  getline(ifs, line);
  const char* expected_prefix = "Contents of ";
  if (!absl::StartsWith(line, expected_prefix)) {
    return;
  }

  const string& original_filepath = line.substr(strlen(expected_prefix));
  VLOG(1) << "hash criteria file found. original filepath: "
          << original_filepath;

  const string tmp_filepath = filepath + ".tmp";
  file::Copy(original_filepath, tmp_filepath, file::Overwrite());
  rename(tmp_filepath.c_str(), filepath.c_str());
}
#endif

static bool NormalizePath(const string& path_to_normalize,
                          string* normalized_path) {
// TODO: Can't we remove this ifdef? Maybe we have make a code
//                    that is platform independent?
//                    Do we need to resolve symlink on Unix?
#ifndef _WIN32
  std::unique_ptr<char[], decltype(&free)> path_buf(
      realpath(path_to_normalize.c_str(), nullptr), free);
  if (path_buf.get() == nullptr)
    return false;
  normalized_path->assign(path_buf.get());
#else
  *normalized_path = PathResolver::ResolvePath(
      PathResolver::PlatformConvert(path_to_normalize));
  if (normalized_path->empty() ||
      (GetFileAttributesA(normalized_path->c_str()) ==
       INVALID_FILE_ATTRIBUTES)) {
    return false;
  }
#endif
  return true;
}

static void MergeDirs(const std::string cwd,
                      const std::vector<string>& dirs,
                      std::vector<string>* include_dirs,
                      std::set<string>* seen_include_dir_set) {
  for (const auto& dir : dirs) {
    std::string abs_dir = file::JoinPathRespectAbsolute(cwd, dir);
    string normalized_dir;
    if (!NormalizePath(abs_dir, &normalized_dir)) {
      continue;
    }
    // Remove duplicated dirs.
    if (!seen_include_dir_set->insert(normalized_dir).second) {
      continue;
    }
    include_dirs->push_back(dir);
  }
}

static void MergeIncludeDirs(const std::string& cwd,
                             const std::vector<string>& nonsystem_include_dirs,
                             const std::vector<string>& system_include_dirs,
                             std::vector<string>* include_dirs) {
  std::set<string> seen_include_dir_set;

  // We check system include paths first because we should give more
  // priority to system paths than non-system paths when we check
  // duplicates of them. We will push back the system include paths
  // into include_paths later because the order of include paths
  // should be non-system path first.
  std::vector<string> unique_system_include_dirs;
  MergeDirs(cwd, system_include_dirs, &unique_system_include_dirs,
            &seen_include_dir_set);

  MergeDirs(cwd, nonsystem_include_dirs, include_dirs, &seen_include_dir_set);

  copy(unique_system_include_dirs.begin(), unique_system_include_dirs.end(),
       back_inserter(*include_dirs));
}

bool CppIncludeProcessor::GetIncludeFiles(const string& filename,
                                          const string& current_directory,
                                          const CompilerFlags& compiler_flags,
                                          const CxxCompilerInfo& compiler_info,
                                          std::set<string>* include_files,
                                          FileStatCache* file_stat_cache) {
  DCHECK(!current_directory.empty());
  DCHECK(file::IsAbsolutePath(current_directory)) << current_directory;

  std::vector<string> non_system_include_dirs;
  std::vector<string> root_includes;
  std::vector<string> user_framework_dirs;
  std::vector<std::pair<string, bool>> commandline_macros;
#if _WIN32
  bool ignore_case = true;
#else
  bool ignore_case = false;
#endif

  if (compiler_flags.type() == CompilerFlagType::Gcc) {
    const GCCFlags& flags = static_cast<const GCCFlags&>(compiler_flags);
    non_system_include_dirs = flags.non_system_include_dirs();
    root_includes = flags.root_includes();
    user_framework_dirs = flags.framework_dirs();
    commandline_macros = flags.commandline_macros();

    // -Xclang -emit-module is not supported yet. Do fallback.
    // b/24956317
    if (flags.has_emit_module()) {
      LOG(INFO) << "-Xclang -emit-module is not supported yet; force fallback";
      return false;
    }
  } else if (compiler_flags.type() == CompilerFlagType::Clexe) {
    const VCFlags& flags = static_cast<const VCFlags&>(compiler_flags);
    non_system_include_dirs = flags.include_dirs();
    root_includes = flags.root_includes();
    commandline_macros = flags.commandline_macros();
    // in chromium, clang-cl on linux
    // https://chromium.googlesource.com/chromium/src/+/lkcr/docs/win_cross.md
    // it is expected to use ciopfs for win_sdk, but not for chromium source.
    // (depot_tools configured it so)
    ignore_case = true;
  } else if (compiler_flags.type() == CompilerFlagType::ClangTidy) {
    const ClangTidyFlags& flags =
        static_cast<const ClangTidyFlags&>(compiler_flags);
    non_system_include_dirs = flags.non_system_include_dirs();
    root_includes = flags.root_includes();
    user_framework_dirs = flags.framework_dirs();
    commandline_macros = flags.commandline_macros();
  } else {
    LOG(FATAL) << "Bad compiler_flags for CppIncludeProcessor: "
               << compiler_flags.DebugString();
  }
  VLOG(3) << "non_system_include_dirs=" << non_system_include_dirs;
  VLOG(3) << "root_includes=" << root_includes;
  VLOG(3) << "user_framework_dirs=" << user_framework_dirs;
  VLOG(3) << "commandline_macros=" << commandline_macros;

  for (const auto& include_dir : non_system_include_dirs) {
    // TODO: Ideally, we should not add .hmap file if this
    //               file doesn't exist.
    if (absl::EndsWith(include_dir, ".hmap")) {
      include_files->insert(include_dir);
    }
  }

  std::vector<string> quote_dirs;
  CopyIncludeDirs(compiler_info.quote_include_paths(), "", &quote_dirs);

  std::vector<string> all_system_include_dirs;
  if (compiler_info.lang().find("c++") != string::npos) {
    CopyIncludeDirs(compiler_info.cxx_system_include_paths(),
                    compiler_info.toolchain_root(), &all_system_include_dirs);
  } else {
    CopyIncludeDirs(compiler_info.system_include_paths(),
                    compiler_info.toolchain_root(), &all_system_include_dirs);
  }

  // The first element of include_dirs.include_dirs represents the current input
  // directory. It's not specified by -I, but we need to handle it when
  // including file with #include "".
  std::vector<std::string> include_dirs;
  std::vector<std::string> framework_dirs;
  include_dirs.push_back(current_directory);
  copy(quote_dirs.begin(), quote_dirs.end(), back_inserter(include_dirs));

  cpp_parser_.set_bracket_include_dir_index(include_dirs.size());
  VLOG(2) << "bracket include dir index=" << include_dirs.size();
  MergeIncludeDirs(current_directory, non_system_include_dirs,
                   all_system_include_dirs, &include_dirs);

#ifndef _WIN32
  std::vector<string> abs_user_framework_dirs;
  CopyIncludeDirs(user_framework_dirs, "", &abs_user_framework_dirs);
  std::vector<string> system_framework_dirs;
  CopyIncludeDirs(compiler_info.system_framework_paths(),
                  compiler_info.toolchain_root(), &system_framework_dirs);
  MergeIncludeDirs(current_directory, abs_user_framework_dirs,
                   system_framework_dirs, &framework_dirs);
#else
  CHECK(compiler_info.system_framework_paths().empty());
#endif

  // TODO: cleanup paths (// -> /, /./ -> /) in include_dirs
  // Note that we should not use ResolvePath for these dirs.
  IncludeFileFinder include_file_finder(current_directory, ignore_case,
                                        &include_dirs, &framework_dirs,
                                        file_stat_cache);

  std::vector<std::pair<string, int>> root_includes_with_index =
      CalculateRootIncludesWithIncludeDirIndex(
          root_includes, current_directory, compiler_flags,
          &include_file_finder, include_files);
  root_includes_with_index.emplace_back(PathResolver::PlatformConvert(filename),
                                        CppParser::kCurrentDirIncludeDirIndex);

  IncludePathsObserver include_observer(current_directory,
                                        &cpp_parser_, include_files,
                                        file_stat_cache, &include_file_finder);
  IncludeErrorObserver error_observer;
  cpp_parser_.set_include_observer(&include_observer);
  if (VLOG_IS_ON(1))
    cpp_parser_.set_error_observer(&error_observer);
  cpp_parser_.SetCompilerInfo(&compiler_info);
  if (compiler_flags.type() == CompilerFlagType::Clexe) {
    cpp_parser_.set_is_vc();
  }

  // True if the compiler is gcc-like and we are building in hosted mode.
  bool gcc_like_hosted = false;
  if (compiler_flags.type() == CompilerFlagType::Gcc) {
    const GCCFlags& flags = static_cast<const GCCFlags&>(compiler_flags);
    gcc_like_hosted = !(flags.has_ffreestanding() || flags.has_fno_hosted());
  }

  if (gcc_like_hosted) {
    // CompilerInfo was generated with -ffreestanding, and set
    // __STDC_HOSTED__=0 - we must override this.
    cpp_parser_.DeleteMacro("__STDC_HOSTED__");
    cpp_parser_.AddMacroByString("__STDC_HOSTED__", "1");
  }

  for (const auto& commandline_macro : commandline_macros) {
    const string& macro = commandline_macro.first;
    if (commandline_macro.second) {
      size_t found = macro.find('=');
      if (found == string::npos) {
        // https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html
        // -D name
        //   Predefine name as a macro, with definition 1.
        cpp_parser_.AddMacroByString(macro, "1");
        continue;
      }
      const string& key = macro.substr(0, found);
      const string& value = macro.substr(found + 1, macro.size() - (found + 1));
      cpp_parser_.AddMacroByString(key, value);
    } else {
      cpp_parser_.DeleteMacro(macro);
    }
  }

  if (gcc_like_hosted) {
    // From GCC 4.8, stdc-predef.h is automatically included without
    // -ffreestanding. Also, -fno-hosted is equivalent to -ffreestanding.
    // See also: https://gcc.gnu.org/gcc-4.8/porting_to.html
    if (!absl::StrContains(compiler_info.name(), "clang")) {
      // Note: this requires that the compiler macros were extracted with
      // -ffreestanding, otherwise stdc-predef.h's header guard will be
      // defined and this will be a no-op.

      // Some environment might not have stdc-predef.h (e.g. android).
      // If cpp_parser tries including a missing file, it is considered as
      // a hard error. So, we have to check it exists or not.
      // gcc-4 does not have __has_include (it's from gcc-5, IIRC,
      // see https://gcc.gnu.org/gcc-5/changes.html#c-family),
      // but we have to try to include stdc-predef.h.
      // So, here, we try to include stdc-predef.h anyway, and clear the error
      // if an error has occured.
      // See b/124756380.
      const string stdc_predef_input(
          "#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)\n"
          "#include <stdc-predef.h>\n"
          "#endif\n");
      cpp_parser_.AddStringInput(stdc_predef_input, "(stdc-predef)");
      bool prev_disabled = cpp_parser_.disabled();
      if (!cpp_parser_.ProcessDirectives()) {
        LOG(WARNING) << "failed to handle stdc-predef";
        if (!prev_disabled) {
          cpp_parser_.ClearDisabled();
        }
      }
      // Since base_file_ will be updated in the last AddStringInput, we need
      // to clear it. Otherwise, test will fail.
      cpp_parser_.ClearBaseFile();
    }
  }

  for (const auto& input_index : root_includes_with_index) {
    const string& input = input_index.first;
    const int dir_index = input_index.second;

    const std::string& abs_input =
        file::JoinPathRespectAbsolute(current_directory, input);
    std::unique_ptr<Content> content(Content::CreateFromFile(abs_input));
    if (!content) {
      LOG(ERROR) << "root include:" << abs_input << " not found";
      return false;
    }

    // TODO: To mitigate b/78094849, let me run directive filter for
    // sources, too.
    SharedCppDirectives directives(CppDirectiveParser::ParseFromContent(
        *DirectiveFilter::MakeFilteredContent(*content), abs_input));
    if (!directives) {
      LOG(ERROR) << "failed to parse directives: " << abs_input;
      return false;
    }
    VLOG(2) << "Looking into " << abs_input;

    string input_basedir = string(file::Dirname(input));

    cpp_parser_.AddFileInput(IncludeItem(std::move(directives), ""), input,
                             input_basedir, dir_index);
    if (!cpp_parser_.ProcessDirectives()) {
      LOG(ERROR) << "cpp parser fatal error in " << abs_input;
      return false;
    }
  }

  if (compiler_flags.type() == CompilerFlagType::Gcc) {
    const GCCFlags& flags = static_cast<const GCCFlags&>(compiler_flags);
    if (flags.has_fmodules()) {
      if (!AddClangModulesFiles(flags, current_directory, include_files,
                                file_stat_cache)) {
        return false;
      }
    }
  }

  return true;
}

std::vector<std::pair<string, int>>
CppIncludeProcessor::CalculateRootIncludesWithIncludeDirIndex(
    const std::vector<string>& root_includes,
    const string& current_directory,
    const CompilerFlags& compiler_flags,
    IncludeFileFinder* include_file_finder,
    std::set<string>* include_files) {
  std::vector<std::pair<string, int>> result;
  for (const auto& root_include : root_includes) {
    string abs_filepath = PathResolver::PlatformConvert(
        file::JoinPathRespectAbsolute(current_directory, root_include));

// TODO: this does not seem to apply to Windows. Need verify.
#ifndef _WIN32
    if (IncludeFileFinder::gch_hack_enabled()) {
      // If there is the precompiled header for this header, we'll send
      // the precompiled header. Note that we don't need to check its content.
      string gch_filepath = abs_filepath + GOMA_GCH_SUFFIX;
      ScopedFd fd(ScopedFd::OpenForRead(gch_filepath));
      if (fd.valid()) {
        fd.Close();
        VLOG(1) << "precompiled header found: " << gch_filepath;
        include_files->insert(root_include + GOMA_GCH_SUFFIX);
        continue;
      }
    }
#endif

    if (access(abs_filepath.c_str(), R_OK) == 0) {
#ifndef _WIN32
      // we don't support *.gch on Win32.
      CopyOriginalFileFromHashCriteria(abs_filepath);
#endif

      // -include can be used twice. So we need to keep it in result
      // if it's duplicated.
      include_files->insert(root_include);
      result.emplace_back(root_include, CppParser::kCurrentDirIncludeDirIndex);
      continue;
    }

    std::string filepath;
    int dir_index = CppParser::kIncludeDirIndexStarting;
    if (!include_file_finder->Lookup(root_include, &filepath, &dir_index)) {
      LOG(INFO) << (compiler_flags.type() == CompilerFlagType::Clexe
                        ? "/FI"
                        : "-include")
                << " not found: " << root_include;
      result.emplace_back(root_include, CppParser::kCurrentDirIncludeDirIndex);
      continue;
    }

    if (IncludeFileFinder::gch_hack_enabled() &&
        absl::EndsWith(filepath, GOMA_GCH_SUFFIX)) {
      VLOG(1) << "precompiled header found: " << filepath;
      include_files->insert(filepath);
      continue;
    }

    // -include can be used twice. So we need to keep it in result
    // if it's duplicated.
    include_files->insert(filepath);
    result.emplace_back(filepath, dir_index);
  }

  return result;
}

bool CppIncludeProcessor::AddClangModulesFiles(
    const GCCFlags& flags,
    const string& current_directory,
    std::set<string>* include_files,
    FileStatCache* file_stat_cache) const {
  // TODO: experiment support of clang modules.
  // In this implementation, we don't read the content of module file.
  // We just add it as an input.
  // We assume -fmodules does not affect a list of include files.
  // This will be 99% fine, but we might see problems if a user
  // totally depend on clang modules behavior.

  DCHECK(flags.has_fmodules());

  // module-file (not module-map-file).
  if (!flags.clang_module_file().second.empty()) {
    string abs_path = file::JoinPathRespectAbsolute(
        current_directory, flags.clang_module_file().second);
    FileStat fs = file_stat_cache->Get(abs_path);
    if (!fs.IsValid()) {
      LOG(WARNING) << "module file not found: " << abs_path;
      return false;
    }
    if (fs.is_directory) {
      LOG(WARNING) << "directory is specified to module file: " << abs_path;
      return false;
    }
    include_files->insert(flags.clang_module_file().second);
  }

  // module-map-file
  if (!flags.clang_module_map_file().empty()) {
    if (!modulemap::Cache::instance()->AddModuleMapFileAndDependents(
            flags.clang_module_map_file(), current_directory, include_files,
            file_stat_cache)) {
      LOG(WARNING) << "failed to add a module map: "
                   << flags.clang_module_map_file();
      return false;
    }
  }

  // module.modulemap is parsed only if flags.has_fimplicit_module_maps() is
  // true.
  if (flags.has_fimplicit_module_maps()) {
    std::vector<string> dirs;
    for (const auto& file : *include_files) {
      dirs.emplace_back(file::Dirname(file));
    }
    std::sort(dirs.begin(), dirs.end());
    dirs.erase(std::unique(dirs.begin(), dirs.end()), dirs.end());
    for (const auto& d : dirs) {
      // Check both module.modulemap and module.map. The latter is an older
      // form.
      for (const auto& name : {"module.modulemap", "module.map"}) {
        string rel_path = file::JoinPath(d, name);
        string abs_path =
            file::JoinPathRespectAbsolute(current_directory, rel_path);
        FileStat fs = file_stat_cache->Get(abs_path);
        if (fs.IsValid() && !fs.is_directory) {
          if (!modulemap::Cache::instance()->AddModuleMapFileAndDependents(
                  rel_path, current_directory, include_files,
                  file_stat_cache)) {
            return false;
          }
        }
      }
    }
  }

  return true;
}

int CppIncludeProcessor::total_files() const {
  return cpp_parser_.total_files();
}

int CppIncludeProcessor::skipped_files() const {
  return cpp_parser_.skipped_files();
}

}  // namespace devtools_goma
