112 lines · c
1//===--- StdLib.h - Index the C and C++ standard library ---------*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8// Eagerly indexing the standard library gives a much friendlier "warm start"9// with working code completion in a standalone file or small project.10//11// We act as if we saw a file which included the whole standard library:12// #include <array>13// #include <bitset>14// #include <chrono>15// ...16// We index this TU and feed the result into the dynamic index.17//18// This happens within the context of some particular open file, and we reuse19// its CompilerInvocation. Matching its include path, LangOpts etc ensures that20// we see the standard library and configuration that matches the project.21//===----------------------------------------------------------------------===//22 23#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_STDLIB_H24#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_STDLIB_H25 26#include "index/Symbol.h"27#include "support/ThreadsafeFS.h"28#include "llvm/ADT/StringRef.h"29#include <optional>30#include <string>31 32namespace clang {33class CompilerInvocation;34class LangOptions;35class HeaderSearch;36namespace clangd {37 38// The filesystem location where a standard library was found.39//40// This is the directory containing <vector> or <stdio.h>.41// It's used to ensure we only index files that are in the standard library.42//43// The paths are canonicalized (FS "real path" with symlinks resolved).44// This allows them to be easily compared against paths the indexer returns.45struct StdLibLocation {46 llvm::SmallVector<std::string> Paths;47};48 49// Tracks the state of standard library indexing within a particular index.50//51// In general, we don't want to index the standard library multiple times.52// In most cases, this class just acts as a flag to ensure we only do it once.53//54// However, if we first open a C++11 file, and then a C++20 file, we *do*55// want the index to be upgraded to include the extra symbols.56// Similarly, the C and C++ standard library can coexist.57class StdLibSet {58 std::atomic<int> Best[2] = {{-1}, {-1}};59 60public:61 // Determines if we should index the standard library in a configuration.62 //63 // This is true if:64 // - standard library indexing is enabled for the file65 // - the language version is higher than any previous add() for the language66 // - the standard library headers exist on the search path67 // Returns the location where the standard library was found.68 //69 // This function is threadsafe.70 std::optional<StdLibLocation> add(const LangOptions &, const HeaderSearch &);71 72 // Indicates whether a built index should be used.73 // It should not be used if a newer version has subsequently been added.74 //75 // Intended pattern is:76 // if (add()) {77 // symbols = indexStandardLibrary();78 // if (isBest())79 // index.update(symbols);80 // }81 //82 // This is still technically racy: we could return true here, then another83 // thread could add->index->update a better library before we can update.84 // We'd then overwrite it with the older version.85 // However, it's very unlikely: indexing takes a long time.86 bool isBest(const LangOptions &) const;87};88 89// Index a standard library and return the discovered symbols.90//91// The compiler invocation should describe the file whose config we're reusing.92// We overwrite its virtual buffer with a lot of #include statements.93SymbolSlab indexStandardLibrary(std::unique_ptr<CompilerInvocation> Invocation,94 const StdLibLocation &Loc,95 const ThreadsafeFS &TFS);96 97// Variant that allows the umbrella header source to be specified.98// Exposed for testing.99SymbolSlab indexStandardLibrary(llvm::StringRef HeaderSources,100 std::unique_ptr<CompilerInvocation> CI,101 const StdLibLocation &Loc,102 const ThreadsafeFS &TFS);103 104// Generate header containing #includes for all standard library headers.105// Exposed for testing.106llvm::StringRef getStdlibUmbrellaHeader(const LangOptions &);107 108} // namespace clangd109} // namespace clang110 111#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_STDLIB_H112