//===- Pragma.h - Pragma registration and handling --------------*- 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 PragmaHandler and PragmaTable interfaces.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_LEX_PRAGMA_H
 
#define LLVM_CLANG_LEX_PRAGMA_H
 
 
 
#include "clang/Basic/LLVM.h"
 
#include "clang/Basic/SourceLocation.h"
 
#include "llvm/ADT/StringMap.h"
 
#include "llvm/ADT/StringRef.h"
 
#include <string>
 
 
 
namespace clang {
 
 
 
class PragmaNamespace;
 
class Preprocessor;
 
class Token;
 
 
 
  /**
 
   * Describes how the pragma was introduced, e.g., with \#pragma,
 
   * _Pragma, or __pragma.
 
   */
 
  enum PragmaIntroducerKind {
 
    /**
 
     * The pragma was introduced via \#pragma.
 
     */
 
    PIK_HashPragma,
 
 
 
    /**
 
     * The pragma was introduced via the C99 _Pragma(string-literal).
 
     */
 
    PIK__Pragma,
 
 
 
    /**
 
     * The pragma was introduced via the Microsoft
 
     * __pragma(token-string).
 
     */
 
    PIK___pragma
 
  };
 
 
 
  /// Describes how and where the pragma was introduced.
 
  struct PragmaIntroducer {
 
    PragmaIntroducerKind Kind;
 
    SourceLocation Loc;
 
  };
 
 
 
/// PragmaHandler - Instances of this interface defined to handle the various
 
/// pragmas that the language front-end uses.  Each handler optionally has a
 
/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
 
/// that identifier is found.  If a handler does not match any of the declared
 
/// pragmas the handler with a null identifier is invoked, if it exists.
 
///
 
/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
 
/// we treat "\#pragma STDC" and "\#pragma GCC" as namespaces that contain other
 
/// pragmas.
 
class PragmaHandler {
 
  std::string Name;
 
 
 
public:
 
  PragmaHandler() = default;
 
  explicit PragmaHandler(StringRef name) : Name(name) {}
 
  virtual ~PragmaHandler();
 
 
 
  StringRef getName() const { return Name; }
 
  virtual void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
 
                            Token &FirstToken) = 0;
 
 
 
  /// getIfNamespace - If this is a namespace, return it.  This is equivalent to
 
  /// using a dynamic_cast, but doesn't require RTTI.
 
  virtual PragmaNamespace *getIfNamespace() { return nullptr; }
 
};
 
 
 
/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
 
/// used to ignore particular pragmas.
 
class EmptyPragmaHandler : public PragmaHandler {
 
public:
 
  explicit EmptyPragmaHandler(StringRef Name = StringRef());
 
 
 
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
 
                    Token &FirstToken) override;
 
};
 
 
 
/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
 
/// allowing hierarchical pragmas to be defined.  Common examples of namespaces
 
/// are "\#pragma GCC", "\#pragma STDC", and "\#pragma omp", but any namespaces
 
/// may be (potentially recursively) defined.
 
class PragmaNamespace : public PragmaHandler {
 
  /// Handlers - This is a map of the handlers in this namespace with their name
 
  /// as key.
 
  llvm::StringMap<std::unique_ptr<PragmaHandler>> Handlers;
 
 
 
public:
 
  explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {}
 
 
 
  /// FindHandler - Check to see if there is already a handler for the
 
  /// specified name.  If not, return the handler for the null name if it
 
  /// exists, otherwise return null.  If IgnoreNull is true (the default) then
 
  /// the null handler isn't returned on failure to match.
 
  PragmaHandler *FindHandler(StringRef Name,
 
                             bool IgnoreNull = true) const;
 
 
 
  /// AddPragma - Add a pragma to this namespace.
 
  void AddPragma(PragmaHandler *Handler);
 
 
 
  /// RemovePragmaHandler - Remove the given handler from the
 
  /// namespace.
 
  void RemovePragmaHandler(PragmaHandler *Handler);
 
 
 
  bool IsEmpty() const { return Handlers.empty(); }
 
 
 
  void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
 
                    Token &Tok) override;
 
 
 
  PragmaNamespace *getIfNamespace() override { return this; }
 
};
 
 
 
} // namespace clang
 
 
 
#endif // LLVM_CLANG_LEX_PRAGMA_H