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