1//===- Pragma.h - Pragma registration and handling --------------*- 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the PragmaHandler and PragmaTable interfaces.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_LEX_PRAGMA_H
14#define LLVM_CLANG_LEX_PRAGMA_H
15
16#include "clang/Basic/LLVM.h"
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include <string>
20
21namespace clang {
22
23class PragmaNamespace;
24class Preprocessor;
25class Token;
26
27 /**
28 * Describes how the pragma was introduced, e.g., with \#pragma,
29 * _Pragma, or __pragma.
30 */
31 enum PragmaIntroducerKind {
32 /**
33 * The pragma was introduced via \#pragma.
34 */
35 PIK_HashPragma,
36
37 /**
38 * The pragma was introduced via the C99 _Pragma(string-literal).
39 */
40 PIK__Pragma,
41
42 /**
43 * The pragma was introduced via the Microsoft
44 * __pragma(token-string).
45 */
46 PIK___pragma
47 };
48
49/// PragmaHandler - Instances of this interface defined to handle the various
50/// pragmas that the language front-end uses. Each handler optionally has a
51/// name (e.g. "pack") and the HandlePragma method is invoked when a pragma with
52/// that identifier is found. If a handler does not match any of the declared
53/// pragmas the handler with a null identifier is invoked, if it exists.
54///
55/// Note that the PragmaNamespace class can be used to subdivide pragmas, e.g.
56/// we treat "\#pragma STDC" and "\#pragma GCC" as namespaces that contain other
57/// pragmas.
58class PragmaHandler {
59 std::string Name;
60
61public:
62 PragmaHandler() = default;
63 explicit PragmaHandler(StringRef name) : Name(name) {}
64 virtual ~PragmaHandler();
65
66 StringRef getName() const { return Name; }
67 virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
68 Token &FirstToken) = 0;
69
70 /// getIfNamespace - If this is a namespace, return it. This is equivalent to
71 /// using a dynamic_cast, but doesn't require RTTI.
72 virtual PragmaNamespace *getIfNamespace() { return nullptr; }
73};
74
75/// EmptyPragmaHandler - A pragma handler which takes no action, which can be
76/// used to ignore particular pragmas.
77class EmptyPragmaHandler : public PragmaHandler {
78public:
79 explicit EmptyPragmaHandler(StringRef Name = StringRef());
80
81 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
83};
84
85/// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas,
86/// allowing hierarchical pragmas to be defined. Common examples of namespaces
87/// are "\#pragma GCC", "\#pragma STDC", and "\#pragma omp", but any namespaces
88/// may be (potentially recursively) defined.
89class PragmaNamespace : public PragmaHandler {
90 /// Handlers - This is a map of the handlers in this namespace with their name
91 /// as key.
92 llvm::StringMap<PragmaHandler *> Handlers;
93
94public:
95 explicit PragmaNamespace(StringRef Name) : PragmaHandler(Name) {}
96 ~PragmaNamespace() override;
97
98 /// FindHandler - Check to see if there is already a handler for the
99 /// specified name. If not, return the handler for the null name if it
100 /// exists, otherwise return null. If IgnoreNull is true (the default) then
101 /// the null handler isn't returned on failure to match.
102 PragmaHandler *FindHandler(StringRef Name,
103 bool IgnoreNull = true) const;
104
105 /// AddPragma - Add a pragma to this namespace.
106 void AddPragma(PragmaHandler *Handler);
107
108 /// RemovePragmaHandler - Remove the given handler from the
109 /// namespace.
110 void RemovePragmaHandler(PragmaHandler *Handler);
111
112 bool IsEmpty() const { return Handlers.empty(); }
113
114 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
115 Token &Tok) override;
116
117 PragmaNamespace *getIfNamespace() override { return this; }
118};
119
120} // namespace clang
121
122#endif // LLVM_CLANG_LEX_PRAGMA_H
123