//===- PreprocessingRecord.h - Record of Preprocessing ----------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
//  This file defines the PreprocessingRecord class, which maintains a record
//  of what occurred during preprocessing.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
#define LLVM_CLANG_LEX_PREPROCESSINGRECORD_H

#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/PPCallbacks.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <cstddef>
#include <iterator>
#include <optional>
#include <utility>
#include <vector>

namespace clang {

class PreprocessingRecord;

} // namespace clang

/// Allocates memory within a Clang preprocessing record.
void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
                   unsigned alignment = 8) noexcept;

/// Frees memory allocated in a Clang preprocessing record.
void operator delete(void *ptr, clang::PreprocessingRecord &PR,
                     unsigned) noexcept;

namespace clang {

class IdentifierInfo;
class MacroInfo;
class SourceManager;
class Token;

  /// Base class that describes a preprocessed entity, which may be a
  /// preprocessor directive or macro expansion.
  class PreprocessedEntity {
  public:
    /// The kind of preprocessed entity an object describes.
    enum EntityKind {
      /// Indicates a problem trying to load the preprocessed entity.
      InvalidKind,

      /// A macro expansion.
      MacroExpansionKind,

      /// \defgroup Preprocessing directives
      /// @{

      /// A macro definition.
      MacroDefinitionKind,

      /// An inclusion directive, such as \c \#include, \c
      /// \#import, or \c \#include_next.
      InclusionDirectiveKind,

      /// @}

      FirstPreprocessingDirective = MacroDefinitionKind,
      LastPreprocessingDirective = InclusionDirectiveKind
    };

  private:
    /// The kind of preprocessed entity that this object describes.
    EntityKind Kind;

    /// The source range that covers this preprocessed entity.
    SourceRange Range;

  protected:
    friend class PreprocessingRecord;

    PreprocessedEntity(EntityKind Kind, SourceRange Range)
        : Kind(Kind), Range(Range) {}

  public:
    /// Retrieve the kind of preprocessed entity stored in this object.
    EntityKind getKind() const { return Kind; }

    /// Retrieve the source range that covers this entire preprocessed
    /// entity.
    SourceRange getSourceRange() const LLVM_READONLY { return Range; }

    /// Returns true if there was a problem loading the preprocessed
    /// entity.
    bool isInvalid() const { return Kind == InvalidKind; }

    // Only allow allocation of preprocessed entities using the allocator
    // in PreprocessingRecord or by doing a placement new.
    void *operator new(size_t bytes, PreprocessingRecord &PR,
                       unsigned alignment = 8) noexcept {
      return ::operator new(bytes, PR, alignment);
    }

    void *operator new(size_t bytes, void *mem) noexcept { return mem; }

    void operator delete(void *ptr, PreprocessingRecord &PR,
                         unsigned alignment) noexcept {
      return ::operator delete(ptr, PR, alignment);
    }

    void operator delete(void *, std::size_t) noexcept {}
    void operator delete(void *, void *) noexcept {}

  private:
    // Make vanilla 'new' and 'delete' illegal for preprocessed entities.
    void *operator new(size_t bytes) noexcept;
    void operator delete(void *data) noexcept;
  };

  /// Records the presence of a preprocessor directive.
  class PreprocessingDirective : public PreprocessedEntity {
  public:
    PreprocessingDirective(EntityKind Kind, SourceRange Range)
        : PreprocessedEntity(Kind, Range) {}

    // Implement isa/cast/dyncast/etc.
    static bool classof(const PreprocessedEntity *PD) {
      return PD->getKind() >= FirstPreprocessingDirective &&
             PD->getKind() <= LastPreprocessingDirective;
    }
  };

  /// Record the location of a macro definition.
  class MacroDefinitionRecord : public PreprocessingDirective {
    /// The name of the macro being defined.
    const IdentifierInfo *Name;

  public:
    explicit MacroDefinitionRecord(const IdentifierInfo *Name,
                                   SourceRange Range)
        : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {}

    /// Retrieve the name of the macro being defined.
    const IdentifierInfo *getName() const { return Name; }

    /// Retrieve the location of the macro name in the definition.
    SourceLocation getLocation() const { return getSourceRange().getBegin(); }

    // Implement isa/cast/dyncast/etc.
    static bool classof(const PreprocessedEntity *PE) {
      return PE->getKind() == MacroDefinitionKind;
    }
  };

  /// Records the location of a macro expansion.
  class MacroExpansion : public PreprocessedEntity {
    /// The definition of this macro or the name of the macro if it is
    /// a builtin macro.
    llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef;

  public:
    MacroExpansion(IdentifierInfo *BuiltinName, SourceRange Range)
        : PreprocessedEntity(MacroExpansionKind, Range),
          NameOrDef(BuiltinName) {}

    MacroExpansion(MacroDefinitionRecord *Definition, SourceRange Range)
        : PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) {
    }

    /// True if it is a builtin macro.
    bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); }

    /// The name of the macro being expanded.
    const IdentifierInfo *getName() const {
      if (MacroDefinitionRecord *Def = getDefinition())
        return Def->getName();
      return NameOrDef.get<IdentifierInfo *>();
    }

    /// The definition of the macro being expanded. May return null if
    /// this is a builtin macro.
    MacroDefinitionRecord *getDefinition() const {
      return NameOrDef.dyn_cast<MacroDefinitionRecord *>();
    }

    // Implement isa/cast/dyncast/etc.
    static bool classof(const PreprocessedEntity *PE) {
      return PE->getKind() == MacroExpansionKind;
    }
  };

  /// Record the location of an inclusion directive, such as an
  /// \c \#include or \c \#import statement.
  class InclusionDirective : public PreprocessingDirective {
  public:
    /// The kind of inclusion directives known to the
    /// preprocessor.
    enum InclusionKind {
      /// An \c \#include directive.
      Include,

      /// An Objective-C \c \#import directive.
      Import,

      /// A GNU \c \#include_next directive.
      IncludeNext,

      /// A Clang \c \#__include_macros directive.
      IncludeMacros
    };

  private:
    /// The name of the file that was included, as written in
    /// the source.
    StringRef FileName;

    /// Whether the file name was in quotation marks; otherwise, it was
    /// in angle brackets.
    LLVM_PREFERRED_TYPE(bool)
    unsigned InQuotes : 1;

    /// The kind of inclusion directive we have.
    ///
    /// This is a value of type InclusionKind.
    LLVM_PREFERRED_TYPE(InclusionKind)
    unsigned Kind : 2;

    /// Whether the inclusion directive was automatically turned into
    /// a module import.
    LLVM_PREFERRED_TYPE(bool)
    unsigned ImportedModule : 1;

    /// The file that was included.
    OptionalFileEntryRef File;

  public:
    InclusionDirective(PreprocessingRecord &PPRec, InclusionKind Kind,
                       StringRef FileName, bool InQuotes, bool ImportedModule,
                       OptionalFileEntryRef File, SourceRange Range);

    /// Determine what kind of inclusion directive this is.
    InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); }

    /// Retrieve the included file name as it was written in the source.
    StringRef getFileName() const { return FileName; }

    /// Determine whether the included file name was written in quotes;
    /// otherwise, it was written in angle brackets.
    bool wasInQuotes() const { return InQuotes; }

    /// Determine whether the inclusion directive was automatically
    /// turned into a module import.
    bool importedModule() const { return ImportedModule; }

    /// Retrieve the file entry for the actual file that was included
    /// by this directive.
    OptionalFileEntryRef getFile() const { return File; }

    // Implement isa/cast/dyncast/etc.
    static bool classof(const PreprocessedEntity *PE) {
      return PE->getKind() == InclusionDirectiveKind;
    }
  };

  /// An abstract class that should be subclassed by any external source
  /// of preprocessing record entries.
  class ExternalPreprocessingRecordSource {
  public:
    virtual ~ExternalPreprocessingRecordSource();

    /// Read a preallocated preprocessed entity from the external source.
    ///
    /// \returns null if an error occurred that prevented the preprocessed
    /// entity from being loaded.
    virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0;

    /// Returns a pair of [Begin, End) indices of preallocated
    /// preprocessed entities that \p Range encompasses.
    virtual std::pair<unsigned, unsigned>
        findPreprocessedEntitiesInRange(SourceRange Range) = 0;

    /// Optionally returns true or false if the preallocated preprocessed
    /// entity with index \p Index came from file \p FID.
    virtual std::optional<bool> isPreprocessedEntityInFileID(unsigned Index,
                                                             FileID FID) {
      return std::nullopt;
    }

    /// Read a preallocated skipped range from the external source.
    virtual SourceRange ReadSkippedRange(unsigned Index) = 0;
  };

  /// A record of the steps taken while preprocessing a source file,
  /// including the various preprocessing directives processed, macros
  /// expanded, etc.
  class PreprocessingRecord : public PPCallbacks {
    SourceManager &SourceMgr;

    /// Allocator used to store preprocessing objects.
    llvm::BumpPtrAllocator BumpAlloc;

    /// The set of preprocessed entities in this record, in order they
    /// were seen.
    std::vector<PreprocessedEntity *> PreprocessedEntities;

    /// The set of preprocessed entities in this record that have been
    /// loaded from external sources.
    ///
    /// The entries in this vector are loaded lazily from the external source,
    /// and are referenced by the iterator using negative indices.
    std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;

    /// The set of ranges that were skipped by the preprocessor,
    std::vector<SourceRange> SkippedRanges;

    bool SkippedRangesAllLoaded = true;

    /// Global (loaded or local) ID for a preprocessed entity.
    /// Negative values are used to indicate preprocessed entities
    /// loaded from the external source while non-negative values are used to
    /// indicate preprocessed entities introduced by the current preprocessor.
    /// Value -1 corresponds to element 0 in the loaded entities vector,
    /// value -2 corresponds to element 1 in the loaded entities vector, etc.
    /// Value 0 is an invalid value, the index to local entities is 1-based,
    /// value 1 corresponds to element 0 in the local entities vector,
    /// value 2 corresponds to element 1 in the local entities vector, etc.
    class PPEntityID {
      friend class PreprocessingRecord;

      int ID = 0;

      explicit PPEntityID(int ID) : ID(ID) {}

    public:
      PPEntityID() = default;
    };

    static PPEntityID getPPEntityID(unsigned Index, bool isLoaded) {
      return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1);
    }

    /// Mapping from MacroInfo structures to their definitions.
    llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions;

    /// External source of preprocessed entities.
    ExternalPreprocessingRecordSource *ExternalSource = nullptr;

    /// Retrieve the preprocessed entity at the given ID.
    PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID);

    /// Retrieve the loaded preprocessed entity at the given index.
    PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index);

    /// Determine the number of preprocessed entities that were
    /// loaded (or can be loaded) from an external source.
    unsigned getNumLoadedPreprocessedEntities() const {
      return LoadedPreprocessedEntities.size();
    }

    /// Returns a pair of [Begin, End) indices of local preprocessed
    /// entities that \p Range encompasses.
    std::pair<unsigned, unsigned>
      findLocalPreprocessedEntitiesInRange(SourceRange Range) const;
    unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const;
    unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const;

    /// Allocate space for a new set of loaded preprocessed entities.
    ///
    /// \returns The index into the set of loaded preprocessed entities, which
    /// corresponds to the first newly-allocated entity.
    unsigned allocateLoadedEntities(unsigned NumEntities);

    /// Allocate space for a new set of loaded preprocessed skipped
    /// ranges.
    ///
    /// \returns The index into the set of loaded preprocessed ranges, which
    /// corresponds to the first newly-allocated range.
    unsigned allocateSkippedRanges(unsigned NumRanges);

    /// Ensures that all external skipped ranges have been loaded.
    void ensureSkippedRangesLoaded();

    /// Register a new macro definition.
    void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);

  public:
    /// Construct a new preprocessing record.
    explicit PreprocessingRecord(SourceManager &SM);

    /// Allocate memory in the preprocessing record.
    void *Allocate(unsigned Size, unsigned Align = 8) {
      return BumpAlloc.Allocate(Size, Align);
    }

    /// Deallocate memory in the preprocessing record.
    void Deallocate(void *Ptr) {}

    size_t getTotalMemory() const;

    SourceManager &getSourceManager() const { return SourceMgr; }

    /// Iteration over the preprocessed entities.
    ///
    /// In a complete iteration, the iterator walks the range [-M, N),
    /// where negative values are used to indicate preprocessed entities
    /// loaded from the external source while non-negative values are used to
    /// indicate preprocessed entities introduced by the current preprocessor.
    /// However, to provide iteration in source order (for, e.g., chained
    /// precompiled headers), dereferencing the iterator flips the negative
    /// values (corresponding to loaded entities), so that position -M
    /// corresponds to element 0 in the loaded entities vector, position -M+1
    /// corresponds to element 1 in the loaded entities vector, etc. This
    /// gives us a reasonably efficient, source-order walk.
    ///
    /// We define this as a wrapping iterator around an int. The
    /// iterator_adaptor_base class forwards the iterator methods to basic
    /// integer arithmetic.
    class iterator : public llvm::iterator_adaptor_base<
                         iterator, int, std::random_access_iterator_tag,
                         PreprocessedEntity *, int, PreprocessedEntity *,
                         PreprocessedEntity *> {
      friend class PreprocessingRecord;

      PreprocessingRecord *Self;

      iterator(PreprocessingRecord *Self, int Position)
          : iterator::iterator_adaptor_base(Position), Self(Self) {}

    public:
      iterator() : iterator(nullptr, 0) {}

      PreprocessedEntity *operator*() const {
        bool isLoaded = this->I < 0;
        unsigned Index = isLoaded ?
            Self->LoadedPreprocessedEntities.size() + this->I : this->I;
        PPEntityID ID = Self->getPPEntityID(Index, isLoaded);
        return Self->getPreprocessedEntity(ID);
      }
      PreprocessedEntity *operator->() const { return **this; }
    };

    /// Begin iterator for all preprocessed entities.
    iterator begin() {
      return iterator(this, -(int)LoadedPreprocessedEntities.size());
    }

    /// End iterator for all preprocessed entities.
    iterator end() {
      return iterator(this, PreprocessedEntities.size());
    }

    /// Begin iterator for local, non-loaded, preprocessed entities.
    iterator local_begin() {
      return iterator(this, 0);
    }

    /// End iterator for local, non-loaded, preprocessed entities.
    iterator local_end() {
      return iterator(this, PreprocessedEntities.size());
    }

    /// iterator range for the given range of loaded
    /// preprocessed entities.
    llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start,
                                                              unsigned count) {
      unsigned end = start + count;
      assert(end <= LoadedPreprocessedEntities.size());
      return llvm::make_range(
          iterator(this, int(start) - LoadedPreprocessedEntities.size()),
          iterator(this, int(end) - LoadedPreprocessedEntities.size()));
    }

    /// Returns a range of preprocessed entities that source range \p R
    /// encompasses.
    ///
    /// \param R the range to look for preprocessed entities.
    llvm::iterator_range<iterator>
    getPreprocessedEntitiesInRange(SourceRange R);

    /// Returns true if the preprocessed entity that \p PPEI iterator
    /// points to is coming from the file \p FID.
    ///
    /// Can be used to avoid implicit deserializations of preallocated
    /// preprocessed entities if we only care about entities of a specific file
    /// and not from files \#included in the range given at
    /// \see getPreprocessedEntitiesInRange.
    bool isEntityInFileID(iterator PPEI, FileID FID);

    /// Add a new preprocessed entity to this record.
    PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity);

    /// Set the external source for preprocessed entities.
    void SetExternalSource(ExternalPreprocessingRecordSource &Source);

    /// Retrieve the external source for preprocessed entities.
    ExternalPreprocessingRecordSource *getExternalSource() const {
      return ExternalSource;
    }

    /// Retrieve the macro definition that corresponds to the given
    /// \c MacroInfo.
    MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);

    /// Retrieve all ranges that got skipped while preprocessing.
    const std::vector<SourceRange> &getSkippedRanges() {
      ensureSkippedRangesLoaded();
      return SkippedRanges;
    }

  private:
    friend class ASTReader;
    friend class ASTWriter;

    void MacroExpands(const Token &Id, const MacroDefinition &MD,
                      SourceRange Range, const MacroArgs *Args) override;
    void MacroDefined(const Token &Id, const MacroDirective *MD) override;
    void MacroUndefined(const Token &Id, const MacroDefinition &MD,
                        const MacroDirective *Undef) override;
    void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
                            StringRef FileName, bool IsAngled,
                            CharSourceRange FilenameRange,
                            OptionalFileEntryRef File, StringRef SearchPath,
                            StringRef RelativePath,
                            const Module *SuggestedModule, bool ModuleImported,
                            SrcMgr::CharacteristicKind FileType) override;
    void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
               const MacroDefinition &MD) override;
    void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
                const MacroDefinition &MD) override;

    using PPCallbacks::Elifdef;
    using PPCallbacks::Elifndef;
    void Elifdef(SourceLocation Loc, const Token &MacroNameTok,
                 const MacroDefinition &MD) override;
    void Elifndef(SourceLocation Loc, const Token &MacroNameTok,
                  const MacroDefinition &MD) override;

    /// Hook called whenever the 'defined' operator is seen.
    void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
                 SourceRange Range) override;

    void SourceRangeSkipped(SourceRange Range,
                            SourceLocation EndifLoc) override;

    void addMacroExpansion(const Token &Id, const MacroInfo *MI,
                           SourceRange Range);

    /// Cached result of the last \see getPreprocessedEntitiesInRange
    /// query.
    struct {
      SourceRange Range;
      std::pair<int, int> Result;
    } CachedRangeQuery;

    std::pair<int, int> getPreprocessedEntitiesInRangeSlow(SourceRange R);
  };

} // namespace clang

inline void *operator new(size_t bytes, clang::PreprocessingRecord &PR,
                          unsigned alignment) noexcept {
  return PR.Allocate(bytes, alignment);
}

inline void operator delete(void *ptr, clang::PreprocessingRecord &PR,
                            unsigned) noexcept {
  PR.Deallocate(ptr);
}

#endif // LLVM_CLANG_LEX_PREPROCESSINGRECORD_H
