llvm/clang/lib/Frontend/ASTUnit.cpp

//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// ASTUnit Implementation.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
#include "clang/Frontend/PrecompiledPreamble.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Token.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/CodeCompleteOptions.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCodeCompletion.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/PCHContainerOperations.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <atomic>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

usingnamespaceclang;

TimeRecord;

namespace {

  class SimpleTimer {};

} // namespace

template <class T>
static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) {}

template <class T>
static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) {}

/// Get a source buffer for \p MainFilePath, handling all file-to-file
/// and file-to-buffer remappings inside \p Invocation.
static std::unique_ptr<llvm::MemoryBuffer>
getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation,
                                  llvm::vfs::FileSystem *VFS,
                                  StringRef FilePath, bool isVolatile) {}

struct ASTUnit::ASTWriterData {};

void ASTUnit::clearFileLevelDecls() {}

/// After failing to build a precompiled preamble (due to
/// errors in the source that occurs in the preamble), the number of
/// reparses during which we'll skip even trying to precompile the
/// preamble.
const unsigned DefaultPreambleRebuildInterval =;

/// Tracks the number of ASTUnit objects that are currently active.
///
/// Used for debugging purposes only.
static std::atomic<unsigned> ActiveASTUnitObjects;

ASTUnit::ASTUnit(bool _MainFileIsAST)
    :{}

ASTUnit::~ASTUnit() {}

void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) {}

void ASTUnit::enableSourceFileDiagnostics() {}

/// Determine the set of code-completion contexts in which this
/// declaration should be shown.
static uint64_t getDeclShowContexts(const NamedDecl *ND,
                                    const LangOptions &LangOpts,
                                    bool &IsNestedNameSpecifier) {}

void ASTUnit::CacheCodeCompletionResults() {}

void ASTUnit::ClearCachedCompletionResults() {}

namespace {

/// Gathers information from ASTReader that will be used to initialize
/// a Preprocessor.
class ASTInfoCollector : public ASTReaderListener {};

/// Diagnostic consumer that saves each diagnostic it is given.
class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer {};

/// RAII object that optionally captures and filters diagnostics, if
/// there is no diagnostic client to capture them already.
class CaptureDroppedDiagnostics {};

} // namespace

static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
                         const StoredDiagnostic &InDiag);

static bool isInMainFile(const clang::Diagnostic &D) {}

void FilterAndStoreDiagnosticConsumer::HandleDiagnostic(
    DiagnosticsEngine::Level Level, const Diagnostic &Info) {}

IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const {}

ASTMutationListener *ASTUnit::getASTMutationListener() {}

ASTDeserializationListener *ASTUnit::getDeserializationListener() {}

std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {}

/// Configure the diagnostics object for use with ASTUnit.
void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                             ASTUnit &AST,
                             CaptureDiagsKind CaptureDiagnostics) {}

std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
    StringRef Filename, const PCHContainerReader &PCHContainerRdr,
    WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
    const FileSystemOptions &FileSystemOpts,
    std::shared_ptr<HeaderSearchOptions> HSOpts,
    std::shared_ptr<LangOptions> LangOpts, bool OnlyLocalDecls,
    CaptureDiagsKind CaptureDiagnostics, bool AllowASTWithCompilerErrors,
    bool UserFilesAreVolatile, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {}

/// Add the given macro to the hash of all top-level entities.
static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) {}

namespace {

/// Preprocessor callback class that updates a hash value with the names
/// of all macros that have been defined by the translation unit.
class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {};

} // namespace

/// Add the given declaration to the hash of all top-level entities.
static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {}

namespace {

class TopLevelDeclTrackerConsumer : public ASTConsumer {};

class TopLevelDeclTrackerAction : public ASTFrontendAction {};

class ASTUnitPreambleCallbacks : public PreambleCallbacks {};

} // namespace

static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {}

static void
checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) {}

static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
                                                              StoredDiagnostics,
                                  SourceManager &SM) {}

/// Parse the source file into a translation unit using the given compiler
/// invocation, replacing the current translation unit.
///
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
                    std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer,
                    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {}

static std::pair<unsigned, unsigned>
makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
                    const LangOptions &LangOpts) {}

static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,
                                                    const LangOptions &LangOpts,
                                                    const FixItHint &InFix) {}

static ASTUnit::StandaloneDiagnostic
makeStandaloneDiagnostic(const LangOptions &LangOpts,
                         const StoredDiagnostic &InDiag) {}

/// Attempt to build or re-use a precompiled preamble when (re-)parsing
/// the source file.
///
/// This routine will compute the preamble of the main source file. If a
/// non-trivial preamble is found, it will precompile that preamble into a
/// precompiled header so that the precompiled preamble can be used to reduce
/// reparsing time. If a precompiled preamble has already been constructed,
/// this routine will determine if it is still valid and, if so, avoid
/// rebuilding the precompiled preamble.
///
/// \param AllowRebuild When true (the default), this routine is
/// allowed to rebuild the precompiled preamble if it is found to be
/// out-of-date.
///
/// \param MaxLines When non-zero, the maximum number of lines that
/// can occur within the preamble.
///
/// \returns If the precompiled preamble can be used, returns a newly-allocated
/// buffer that should be used in place of the main file when doing so.
/// Otherwise, returns a NULL pointer.
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    CompilerInvocation &PreambleInvocationIn,
    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, bool AllowRebuild,
    unsigned MaxLines) {}

void ASTUnit::RealizeTopLevelDeclsFromPreamble() {}

void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {}

StringRef ASTUnit::getMainFileName() const {}

StringRef ASTUnit::getASTFileName() const {}

std::unique_ptr<ASTUnit>
ASTUnit::create(std::shared_ptr<CompilerInvocation> CI,
                IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
                CaptureDiagsKind CaptureDiagnostics,
                bool UserFilesAreVolatile) {}

ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
    std::shared_ptr<CompilerInvocation> CI,
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action,
    ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
    bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
    unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults,
    bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {}

bool ASTUnit::LoadFromCompilerInvocation(
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    unsigned PrecompilePreambleAfterNParses,
    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {}

std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
    std::shared_ptr<CompilerInvocation> CI,
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr,
    bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
    unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
    bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
    bool UserFilesAreVolatile) {}

std::unique_ptr<ASTUnit> ASTUnit::LoadFromCommandLine(
    const char **ArgBegin, const char **ArgEnd,
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
    bool StorePreamblesInMemory, StringRef PreambleStoragePath,
    bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics,
    ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
    unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind,
    bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
    bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies,
    bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization,
    bool RetainExcludedConditionalBlocks, std::optional<StringRef> ModuleFormat,
    std::unique_ptr<ASTUnit> *ErrAST,
    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {}

bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
                      ArrayRef<RemappedFile> RemappedFiles,
                      IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {}

void ASTUnit::ResetForParse() {}

//----------------------------------------------------------------------------//
// Code completion
//----------------------------------------------------------------------------//

namespace {

  /// Code completion consumer that combines the cached code-completion
  /// results from an ASTUnit with the code-completion results provided to it,
  /// then passes the result on to
  class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {};

} // namespace

/// Helper function that computes which global names are hidden by the
/// local code-completion results.
static void CalculateHiddenNames(const CodeCompletionContext &Context,
                                 CodeCompletionResult *Results,
                                 unsigned NumResults,
                                 ASTContext &Ctx,
                          llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){}

void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
                                            CodeCompletionContext Context,
                                            CodeCompletionResult *Results,
                                            unsigned NumResults) {}

void ASTUnit::CodeComplete(
    StringRef File, unsigned Line, unsigned Column,
    ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
    bool IncludeCodePatterns, bool IncludeBriefComments,
    CodeCompleteConsumer &Consumer,
    std::shared_ptr<PCHContainerOperations> PCHContainerOps,
    DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
    FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
    SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers,
    std::unique_ptr<SyntaxOnlyAction> Act) {}

bool ASTUnit::Save(StringRef File) {}

static bool serializeUnit(ASTWriter &Writer, SmallVectorImpl<char> &Buffer,
                          Sema &S, raw_ostream &OS) {}

bool ASTUnit::serialize(raw_ostream &OS) {}

void ASTUnit::TranslateStoredDiagnostics(
                          FileManager &FileMgr,
                          SourceManager &SrcMgr,
                          const SmallVectorImpl<StandaloneDiagnostic> &Diags,
                          SmallVectorImpl<StoredDiagnostic> &Out) {}

void ASTUnit::addFileLevelDecl(Decl *D) {}

void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length,
                                  SmallVectorImpl<Decl *> &Decls) {}

SourceLocation ASTUnit::getLocation(const FileEntry *File,
                                    unsigned Line, unsigned Col) const {}

SourceLocation ASTUnit::getLocation(const FileEntry *File,
                                    unsigned Offset) const {}

/// If \arg Loc is a loaded location from the preamble, returns
/// the corresponding local location of the main file, otherwise it returns
/// \arg Loc.
SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const {}

/// If \arg Loc is a local location of the main file but inside the
/// preamble chunk, returns the corresponding loaded location from the
/// preamble, otherwise it returns \arg Loc.
SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const {}

bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const {}

bool ASTUnit::isInMainFileID(SourceLocation Loc) const {}

SourceLocation ASTUnit::getEndOfPreambleFileID() const {}

SourceLocation ASTUnit::getStartOfMainFileID() const {}

llvm::iterator_range<PreprocessingRecord::iterator>
ASTUnit::getLocalPreprocessingEntities() const {}

bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) {}

OptionalFileEntryRef ASTUnit::getPCHFile() {}

bool ASTUnit::isModuleFile() const {}

InputKind ASTUnit::getInputKind() const {}

#ifndef NDEBUG
ASTUnit::ConcurrencyState::ConcurrencyState() {
  Mutex = new std::recursive_mutex;
}

ASTUnit::ConcurrencyState::~ConcurrencyState() {
  delete static_cast<std::recursive_mutex *>(Mutex);
}

void ASTUnit::ConcurrencyState::start() {
  bool acquired = static_cast<std::recursive_mutex *>(Mutex)->try_lock();
  assert(acquired && "Concurrent access to ASTUnit!");
}

void ASTUnit::ConcurrencyState::finish() {
  static_cast<std::recursive_mutex *>(Mutex)->unlock();
}

#else // NDEBUG

ASTUnit::ConcurrencyState::ConcurrencyState() {}
ASTUnit::ConcurrencyState::~ConcurrencyState() {}
void ASTUnit::ConcurrencyState::start() {}
void ASTUnit::ConcurrencyState::finish() {}

#endif // NDEBUG