kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/extractor/path_utils.cc (about)

     1  /*
     2   * Copyright 2015 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #include "kythe/cxx/extractor/path_utils.h"
    18  
    19  #include <cstdio>
    20  #include <optional>
    21  
    22  #include "absl/strings/str_format.h"
    23  #include "clang/Basic/FileEntry.h"
    24  #include "clang/Basic/TokenKinds.h"
    25  #include "clang/Lex/HeaderSearch.h"
    26  #include "clang/Lex/Preprocessor.h"
    27  #include "clang/Lex/Token.h"
    28  #include "llvm/ADT/SmallVector.h"
    29  #include "llvm/ADT/StringRef.h"
    30  #include "llvm/Support/Path.h"
    31  
    32  namespace kythe {
    33  namespace cxx_extractor {
    34  
    35  clang::OptionalFileEntryRef LookupFileForIncludePragma(
    36      clang::Preprocessor* preprocessor, llvm::SmallVectorImpl<char>* search_path,
    37      llvm::SmallVectorImpl<char>* relative_path,
    38      llvm::SmallVectorImpl<char>* result_filename) {
    39    clang::Token filename_token;
    40    if (preprocessor->LexHeaderName(filename_token)) {
    41      return std::nullopt;
    42    }
    43    if (!filename_token.isOneOf(clang::tok::header_name,
    44                                clang::tok::string_literal)) {
    45      return std::nullopt;
    46    }
    47    llvm::SmallString<128> filename_buffer;
    48    llvm::StringRef filename =
    49        preprocessor->getSpelling(filename_token, filename_buffer);
    50    bool is_angled = preprocessor->GetIncludeFilenameSpelling(
    51        filename_token.getLocation(), filename);
    52    if (filename.empty()) {
    53      preprocessor->DiscardUntilEndOfDirective();
    54      return std::nullopt;
    55    }
    56    preprocessor->CheckEndOfDirective("pragma", true);
    57    if (preprocessor->getHeaderSearchInfo().HasIncludeAliasMap()) {
    58      auto mapped =
    59          preprocessor->getHeaderSearchInfo().MapHeaderToIncludeAlias(filename);
    60      if (!mapped.empty()) {
    61        filename = mapped;
    62      }
    63    }
    64    llvm::SmallString<1024> normalized_path;
    65    if (preprocessor->getLangOpts().MSVCCompat) {
    66      normalized_path = filename.str();
    67  #ifndef LLVM_ON_WIN32
    68      llvm::sys::path::native(normalized_path);
    69  #endif
    70      *result_filename = normalized_path;
    71    } else {
    72      result_filename->append(filename.begin(), filename.end());
    73    }
    74    clang::OptionalFileEntryRef file = preprocessor->LookupFile(
    75        filename_token.getLocation(),
    76        preprocessor->getLangOpts().MSVCCompat ? normalized_path.c_str()
    77                                               : filename,
    78        is_angled, nullptr /* FromDir */, nullptr /* FromFile */,
    79        nullptr /* CurDir */, search_path, relative_path,
    80        nullptr /* SuggestedModule */, nullptr /* IsMapped */,
    81        nullptr /* IsFrameworkFound */, false /* SkipCache */);
    82    if (!file) {
    83      absl::FPrintF(stderr, "Missing required file %s.\n", filename.str());
    84    }
    85    return file;
    86  }
    87  
    88  }  // namespace cxx_extractor
    89  }  // namespace kythe