//===--- MacroInfo.h - Information about #defined identifiers ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LEX_MACROINFO_H
#define LLVM_CLANG_LEX_MACROINFO_H

#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include <cassert>

namespace clang {
class Module;
class ModuleMacro;
class Preprocessor;

/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
///
/// There's an instance of this class for every #define.
class MacroInfo {
  //===--------------------------------------------------------------------===//
  // State set when the macro is defined.

  /// \brief The location the macro is defined.
  SourceLocation Location;
  /// \brief The location of the last token in the macro.
  SourceLocation EndLocation;

  /// \brief The list of arguments for a function-like macro.
  ///
  /// ParameterList points to the first of NumParameters pointers.
  ///
  /// This can be empty, for, e.g. "#define X()".  In a C99-style variadic
  /// macro, this includes the \c __VA_ARGS__ identifier on the list.
  IdentifierInfo **ParameterList;

  /// \see ParameterList
  unsigned NumParameters;

  /// \brief This is the list of tokens that the macro is defined to.
  SmallVector<Token, 8> ReplacementTokens;

  /// \brief Length in characters of the macro definition.
  mutable unsigned DefinitionLength;
  mutable bool IsDefinitionLengthCached : 1;

  /// \brief True if this macro is function-like, false if it is object-like.
  bool IsFunctionLike : 1;

  /// \brief True if this macro is of the form "#define X(...)" or
  /// "#define X(Y,Z,...)".
  ///
  /// The __VA_ARGS__ token should be replaced with the contents of "..." in an
  /// invocation.
  bool IsC99Varargs : 1;

  /// \brief True if this macro is of the form "#define X(a...)".
  ///
  /// The "a" identifier in the replacement list will be replaced with all
  /// arguments of the macro starting with the specified one.
  bool IsGNUVarargs : 1;

  /// \brief True if this macro requires processing before expansion.
  ///
  /// This is the case for builtin macros such as __LINE__, so long as they have
  /// not been redefined, but not for regular predefined macros from the
  /// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
  bool IsBuiltinMacro : 1;

  /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__"
  bool HasCommaPasting : 1;

  //===--------------------------------------------------------------------===//
  // State that changes as the macro is used.

  /// \brief True if we have started an expansion of this macro already.
  ///
  /// This disables recursive expansion, which would be quite bad for things
  /// like \#define A A.
  bool IsDisabled : 1;

  /// \brief True if this macro is either defined in the main file and has
  /// been used, or if it is not defined in the main file.
  ///
  /// This is used to emit -Wunused-macros diagnostics.
  bool IsUsed : 1;

  /// \brief True if this macro can be redefined without emitting a warning.
  bool IsAllowRedefinitionsWithoutWarning : 1;

  /// \brief Must warn if the macro is unused at the end of translation unit.
  bool IsWarnIfUnused : 1;

  /// \brief Whether this macro was used as header guard.
  bool UsedForHeaderGuard : 1;

  // Only the Preprocessor gets to create and destroy these.
  MacroInfo(SourceLocation DefLoc);
  ~MacroInfo() = default;

public:
  /// \brief Return the location that the macro was defined at.
  SourceLocation getDefinitionLoc() const { return Location; }

  /// \brief Set the location of the last token in the macro.
  void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; }

  /// \brief Return the location of the last token in the macro.
  SourceLocation getDefinitionEndLoc() const { return EndLocation; }

  /// \brief Get length in characters of the macro definition.
  unsigned getDefinitionLength(const SourceManager &SM) const {
    if (IsDefinitionLengthCached)
      return DefinitionLength;
    return getDefinitionLengthSlow(SM);
  }

  /// \brief Return true if the specified macro definition is equal to
  /// this macro in spelling, arguments, and whitespace.
  ///
  /// \param Syntactically if true, the macro definitions can be identical even
  /// if they use different identifiers for the function macro parameters.
  /// Otherwise the comparison is lexical and this implements the rules in
  /// C99 6.10.3.
  bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP,
                     bool Syntactically) const;

  /// \brief Set or clear the isBuiltinMacro flag.
  void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }

  /// \brief Set the value of the IsUsed flag.
  void setIsUsed(bool Val) { IsUsed = Val; }

  /// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag.
  void setIsAllowRedefinitionsWithoutWarning(bool Val) {
    IsAllowRedefinitionsWithoutWarning = Val;
  }

  /// \brief Set the value of the IsWarnIfUnused flag.
  void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }

  /// \brief Set the specified list of identifiers as the parameter list for
  /// this macro.
  void setParameterList(ArrayRef<IdentifierInfo *> List,
                       llvm::BumpPtrAllocator &PPAllocator) {
    assert(ParameterList == nullptr && NumParameters == 0 &&
           "Parameter list already set!");
    if (List.empty())
      return;

    NumParameters = List.size();
    ParameterList = PPAllocator.Allocate<IdentifierInfo *>(List.size());
    std::copy(List.begin(), List.end(), ParameterList);
  }

  /// Parameters - The list of parameters for a function-like macro.  This can 
  /// be empty, for, e.g. "#define X()".
  typedef IdentifierInfo *const *param_iterator;
  bool param_empty() const { return NumParameters == 0; }
  param_iterator param_begin() const { return ParameterList; }
  param_iterator param_end() const { return ParameterList + NumParameters; }
  unsigned getNumParams() const { return NumParameters; }
  ArrayRef<const IdentifierInfo *> params() const {
    return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters);
  }

  /// \brief Return the parameter number of the specified identifier,
  /// or -1 if the identifier is not a formal parameter identifier.
  int getParameterNum(const IdentifierInfo *Arg) const {
    for (param_iterator I = param_begin(), E = param_end(); I != E; ++I)
      if (*I == Arg)
        return I - param_begin();
    return -1;
  }

  /// Function/Object-likeness.  Keep track of whether this macro has formal
  /// parameters.
  void setIsFunctionLike() { IsFunctionLike = true; }
  bool isFunctionLike() const { return IsFunctionLike; }
  bool isObjectLike() const { return !IsFunctionLike; }

  /// Varargs querying methods.  This can only be set for function-like macros.
  void setIsC99Varargs() { IsC99Varargs = true; }
  void setIsGNUVarargs() { IsGNUVarargs = true; }
  bool isC99Varargs() const { return IsC99Varargs; }
  bool isGNUVarargs() const { return IsGNUVarargs; }
  bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }

  /// \brief Return true if this macro requires processing before expansion.
  ///
  /// This is true only for builtin macro, such as \__LINE__, whose values
  /// are not given by fixed textual expansions.  Regular predefined macros
  /// from the "<built-in>" buffer are not reported as builtins by this
  /// function.
  bool isBuiltinMacro() const { return IsBuiltinMacro; }

  bool hasCommaPasting() const { return HasCommaPasting; }
  void setHasCommaPasting() { HasCommaPasting = true; }

  /// \brief Return false if this macro is defined in the main file and has
  /// not yet been used.
  bool isUsed() const { return IsUsed; }

  /// \brief Return true if this macro can be redefined without warning.
  bool isAllowRedefinitionsWithoutWarning() const {
    return IsAllowRedefinitionsWithoutWarning;
  }

  /// \brief Return true if we should emit a warning if the macro is unused.
  bool isWarnIfUnused() const { return IsWarnIfUnused; }

  /// \brief Return the number of tokens that this macro expands to.
  ///
  unsigned getNumTokens() const { return ReplacementTokens.size(); }

  const Token &getReplacementToken(unsigned Tok) const {
    assert(Tok < ReplacementTokens.size() && "Invalid token #");
    return ReplacementTokens[Tok];
  }

  typedef SmallVectorImpl<Token>::const_iterator tokens_iterator;
  tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
  tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
  bool tokens_empty() const { return ReplacementTokens.empty(); }
  ArrayRef<Token> tokens() const { return ReplacementTokens; }

  /// \brief Add the specified token to the replacement text for the macro.
  void AddTokenToBody(const Token &Tok) {
    assert(
        !IsDefinitionLengthCached &&
        "Changing replacement tokens after definition length got calculated");
    ReplacementTokens.push_back(Tok);
  }

  /// \brief Return true if this macro is enabled.
  ///
  /// In other words, that we are not currently in an expansion of this macro.
  bool isEnabled() const { return !IsDisabled; }

  void EnableMacro() {
    assert(IsDisabled && "Cannot enable an already-enabled macro!");
    IsDisabled = false;
  }

  void DisableMacro() {
    assert(!IsDisabled && "Cannot disable an already-disabled macro!");
    IsDisabled = true;
  }

  /// \brief Determine whether this macro was used for a header guard.
  bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; }

  void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; }

  void dump() const;

private:
  unsigned getDefinitionLengthSlow(const SourceManager &SM) const;

  friend class Preprocessor;
};

class DefMacroDirective;

/// \brief Encapsulates changes to the "macros namespace" (the location where
/// the macro name became active, the location where it was undefined, etc.).
///
/// MacroDirectives, associated with an identifier, are used to model the macro
/// history. Usually a macro definition (MacroInfo) is where a macro name
/// becomes active (MacroDirective) but #pragma push_macro / pop_macro can
/// create additional DefMacroDirectives for the same MacroInfo.
class MacroDirective {
public:
  enum Kind { MD_Define, MD_Undefine, MD_Visibility };

protected:
  /// \brief Previous macro directive for the same identifier, or NULL.
  MacroDirective *Previous;

  SourceLocation Loc;

  /// \brief MacroDirective kind.
  unsigned MDKind : 2;

  /// \brief True if the macro directive was loaded from a PCH file.
  unsigned IsFromPCH : 1;

  // Used by VisibilityMacroDirective ----------------------------------------//

  /// \brief Whether the macro has public visibility (when described in a
  /// module).
  unsigned IsPublic : 1;

  MacroDirective(Kind K, SourceLocation Loc)
      : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false),
        IsPublic(true) {}

public:
  Kind getKind() const { return Kind(MDKind); }

  SourceLocation getLocation() const { return Loc; }

  /// \brief Set previous definition of the macro with the same name.
  void setPrevious(MacroDirective *Prev) { Previous = Prev; }

  /// \brief Get previous definition of the macro with the same name.
  const MacroDirective *getPrevious() const { return Previous; }

  /// \brief Get previous definition of the macro with the same name.
  MacroDirective *getPrevious() { return Previous; }

  /// \brief Return true if the macro directive was loaded from a PCH file.
  bool isFromPCH() const { return IsFromPCH; }

  void setIsFromPCH() { IsFromPCH = true; }

  class DefInfo {
    DefMacroDirective *DefDirective;
    SourceLocation UndefLoc;
    bool IsPublic;

  public:
    DefInfo() : DefDirective(nullptr), IsPublic(true) {}

    DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
            bool isPublic)
        : DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}

    const DefMacroDirective *getDirective() const { return DefDirective; }
    DefMacroDirective *getDirective() { return DefDirective; }

    inline SourceLocation getLocation() const;
    inline MacroInfo *getMacroInfo();
    const MacroInfo *getMacroInfo() const {
      return const_cast<DefInfo *>(this)->getMacroInfo();
    }

    SourceLocation getUndefLocation() const { return UndefLoc; }
    bool isUndefined() const { return UndefLoc.isValid(); }

    bool isPublic() const { return IsPublic; }

    bool isValid() const { return DefDirective != nullptr; }
    bool isInvalid() const { return !isValid(); }

    explicit operator bool() const { return isValid(); }

    inline DefInfo getPreviousDefinition();
    const DefInfo getPreviousDefinition() const {
      return const_cast<DefInfo *>(this)->getPreviousDefinition();
    }
  };

  /// \brief Traverses the macro directives history and returns the next
  /// macro definition directive along with info about its undefined location
  /// (if there is one) and if it is public or private.
  DefInfo getDefinition();
  const DefInfo getDefinition() const {
    return const_cast<MacroDirective *>(this)->getDefinition();
  }

  bool isDefined() const {
    if (const DefInfo Def = getDefinition())
      return !Def.isUndefined();
    return false;
  }

  const MacroInfo *getMacroInfo() const {
    return getDefinition().getMacroInfo();
  }
  MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }

  /// \brief Find macro definition active in the specified source location. If
  /// this macro was not defined there, return NULL.
  const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const;

  void dump() const;

  static bool classof(const MacroDirective *) { return true; }
};

/// \brief A directive for a defined macro or a macro imported from a module.
class DefMacroDirective : public MacroDirective {
  MacroInfo *Info;

public:
  DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
      : MacroDirective(MD_Define, Loc), Info(MI) {
    assert(MI && "MacroInfo is null");
  }
  explicit DefMacroDirective(MacroInfo *MI)
      : DefMacroDirective(MI, MI->getDefinitionLoc()) {}

  /// \brief The data for the macro definition.
  const MacroInfo *getInfo() const { return Info; }
  MacroInfo *getInfo() { return Info; }

  static bool classof(const MacroDirective *MD) {
    return MD->getKind() == MD_Define;
  }
  static bool classof(const DefMacroDirective *) { return true; }
};

/// \brief A directive for an undefined macro.
class UndefMacroDirective : public MacroDirective {
public:
  explicit UndefMacroDirective(SourceLocation UndefLoc)
      : MacroDirective(MD_Undefine, UndefLoc) {
    assert(UndefLoc.isValid() && "Invalid UndefLoc!");
  }

  static bool classof(const MacroDirective *MD) {
    return MD->getKind() == MD_Undefine;
  }
  static bool classof(const UndefMacroDirective *) { return true; }
};

/// \brief A directive for setting the module visibility of a macro.
class VisibilityMacroDirective : public MacroDirective {
public:
  explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
      : MacroDirective(MD_Visibility, Loc) {
    IsPublic = Public;
  }

  /// \brief Determine whether this macro is part of the public API of its
  /// module.
  bool isPublic() const { return IsPublic; }

  static bool classof(const MacroDirective *MD) {
    return MD->getKind() == MD_Visibility;
  }
  static bool classof(const VisibilityMacroDirective *) { return true; }
};

inline SourceLocation MacroDirective::DefInfo::getLocation() const {
  if (isInvalid())
    return SourceLocation();
  return DefDirective->getLocation();
}

inline MacroInfo *MacroDirective::DefInfo::getMacroInfo() {
  if (isInvalid())
    return nullptr;
  return DefDirective->getInfo();
}

inline MacroDirective::DefInfo
MacroDirective::DefInfo::getPreviousDefinition() {
  if (isInvalid() || DefDirective->getPrevious() == nullptr)
    return DefInfo();
  return DefDirective->getPrevious()->getDefinition();
}

/// \brief Represents a macro directive exported by a module.
///
/// There's an instance of this class for every macro #define or #undef that is
/// the final directive for a macro name within a module. These entities also
/// represent the macro override graph.
///
/// These are stored in a FoldingSet in the preprocessor.
class ModuleMacro : public llvm::FoldingSetNode {
  /// The name defined by the macro.
  IdentifierInfo *II;
  /// The body of the #define, or nullptr if this is a #undef.
  MacroInfo *Macro;
  /// The module that exports this macro.
  Module *OwningModule;
  /// The number of module macros that override this one.
  unsigned NumOverriddenBy;
  /// The number of modules whose macros are directly overridden by this one.
  unsigned NumOverrides;
  // ModuleMacro *OverriddenMacros[NumOverrides];

  friend class Preprocessor;

  ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
              ArrayRef<ModuleMacro *> Overrides)
      : II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0),
        NumOverrides(Overrides.size()) {
    std::copy(Overrides.begin(), Overrides.end(),
              reinterpret_cast<ModuleMacro **>(this + 1));
  }

public:
  static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
                             IdentifierInfo *II, MacroInfo *Macro,
                             ArrayRef<ModuleMacro *> Overrides);

  void Profile(llvm::FoldingSetNodeID &ID) const {
    return Profile(ID, OwningModule, II);
  }
  static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
                      IdentifierInfo *II) {
    ID.AddPointer(OwningModule);
    ID.AddPointer(II);
  }

  /// Get the name of the macro.
  IdentifierInfo *getName() const { return II; }

  /// Get the ID of the module that exports this macro.
  Module *getOwningModule() const { return OwningModule; }

  /// Get definition for this exported #define, or nullptr if this
  /// represents a #undef.
  MacroInfo *getMacroInfo() const { return Macro; }

  /// Iterators over the overridden module IDs.
  /// \{
  typedef ModuleMacro *const *overrides_iterator;
  overrides_iterator overrides_begin() const {
    return reinterpret_cast<overrides_iterator>(this + 1);
  }
  overrides_iterator overrides_end() const {
    return overrides_begin() + NumOverrides;
  }
  ArrayRef<ModuleMacro *> overrides() const {
    return llvm::makeArrayRef(overrides_begin(), overrides_end());
  }
  /// \}

  /// Get the number of macros that override this one.
  unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
};

/// \brief A description of the current definition of a macro.
///
/// The definition of a macro comprises a set of (at least one) defining
/// entities, which are either local MacroDirectives or imported ModuleMacros.
class MacroDefinition {
  llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
  ArrayRef<ModuleMacro *> ModuleMacros;

public:
  MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {}
  MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
                  bool IsAmbiguous)
      : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}

  /// \brief Determine whether there is a definition of this macro.
  explicit operator bool() const {
    return getLocalDirective() || !ModuleMacros.empty();
  }

  /// \brief Get the MacroInfo that should be used for this definition.
  MacroInfo *getMacroInfo() const {
    if (!ModuleMacros.empty())
      return ModuleMacros.back()->getMacroInfo();
    if (auto *MD = getLocalDirective())
      return MD->getMacroInfo();
    return nullptr;
  }

  /// \brief \c true if the definition is ambiguous, \c false otherwise.
  bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }

  /// \brief Get the latest non-imported, non-\#undef'd macro definition
  /// for this macro.
  DefMacroDirective *getLocalDirective() const {
    return LatestLocalAndAmbiguous.getPointer();
  }

  /// \brief Get the active module macros for this macro.
  ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }

  template <typename Fn> void forAllDefinitions(Fn F) const {
    if (auto *MD = getLocalDirective())
      F(MD->getMacroInfo());
    for (auto *MM : getModuleMacros())
      F(MM->getMacroInfo());
  }
};

} // end namespace clang

#endif
