xref: /llvm-project/clang/include/clang/Basic/ParsedAttrInfo.h (revision b735c66da9c9ae752b88941d466895a0b696c75e)
1 //===- ParsedAttrInfo.h - Info needed to parse an attribute -----*- 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 ParsedAttrInfo class, which dictates how to
10 // parse an attribute. This class is the one that plugins derive to
11 // define a new attribute.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_BASIC_PARSEDATTRINFO_H
16 #define LLVM_CLANG_BASIC_PARSEDATTRINFO_H
17 
18 #include "clang/Basic/AttrSubjectMatchRules.h"
19 #include "clang/Basic/AttributeCommonInfo.h"
20 #include "clang/Support/Compiler.h"
21 #include "llvm/ADT/ArrayRef.h"
22 #include "llvm/Support/Registry.h"
23 #include <climits>
24 #include <list>
25 
26 namespace clang {
27 
28 class Attr;
29 class Decl;
30 class LangOptions;
31 class ParsedAttr;
32 class Sema;
33 class Stmt;
34 class TargetInfo;
35 
36 struct ParsedAttrInfo {
37   /// Corresponds to the Kind enum.
38   LLVM_PREFERRED_TYPE(AttributeCommonInfo::Kind)
39   unsigned AttrKind : 16;
40   /// The number of required arguments of this attribute.
41   unsigned NumArgs : 4;
42   /// The number of optional arguments of this attributes.
43   unsigned OptArgs : 4;
44   /// The number of non-fake arguments specified in the attribute definition.
45   unsigned NumArgMembers : 4;
46   /// True if the parsing does not match the semantic content.
47   LLVM_PREFERRED_TYPE(bool)
48   unsigned HasCustomParsing : 1;
49   // True if this attribute accepts expression parameter pack expansions.
50   LLVM_PREFERRED_TYPE(bool)
51   unsigned AcceptsExprPack : 1;
52   /// True if this attribute is only available for certain targets.
53   LLVM_PREFERRED_TYPE(bool)
54   unsigned IsTargetSpecific : 1;
55   /// True if this attribute applies to types.
56   LLVM_PREFERRED_TYPE(bool)
57   unsigned IsType : 1;
58   /// True if this attribute applies to statements.
59   LLVM_PREFERRED_TYPE(bool)
60   unsigned IsStmt : 1;
61   /// True if this attribute has any spellings that are known to gcc.
62   LLVM_PREFERRED_TYPE(bool)
63   unsigned IsKnownToGCC : 1;
64   /// True if this attribute is supported by #pragma clang attribute.
65   LLVM_PREFERRED_TYPE(bool)
66   unsigned IsSupportedByPragmaAttribute : 1;
67   /// The syntaxes supported by this attribute and how they're spelled.
68   struct Spelling {
69     AttributeCommonInfo::Syntax Syntax;
70     const char *NormalizedFullName;
71   };
72   ArrayRef<Spelling> Spellings;
73   // The names of the known arguments of this attribute.
74   ArrayRef<const char *> ArgNames;
75 
76 protected:
77   constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind =
78                                AttributeCommonInfo::NoSemaHandlerAttribute)
79       : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0),
80         HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0),
81         IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {}
82 
83   constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs,
84                            unsigned OptArgs, unsigned NumArgMembers,
85                            unsigned HasCustomParsing, unsigned AcceptsExprPack,
86                            unsigned IsTargetSpecific, unsigned IsType,
87                            unsigned IsStmt, unsigned IsKnownToGCC,
88                            unsigned IsSupportedByPragmaAttribute,
89                            ArrayRef<Spelling> Spellings,
90                            ArrayRef<const char *> ArgNames)
91       : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs),
92         NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing),
93         AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific),
94         IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC),
95         IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute),
96         Spellings(Spellings), ArgNames(ArgNames) {}
97 
98 public:
99   virtual ~ParsedAttrInfo() = default;
100 
101   /// Check if this attribute has specified spelling.
102   bool hasSpelling(AttributeCommonInfo::Syntax Syntax, StringRef Name) const {
103     return llvm::any_of(Spellings, [&](const Spelling &S) {
104       return (S.Syntax == Syntax && S.NormalizedFullName == Name);
105     });
106   }
107 
108   /// Check if this attribute appertains to D, and issue a diagnostic if not.
109   virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,
110                                     const Decl *D) const {
111     return true;
112   }
113   /// Check if this attribute appertains to St, and issue a diagnostic if not.
114   virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr,
115                                     const Stmt *St) const {
116     return true;
117   }
118   /// Check if the given attribute is mutually exclusive with other attributes
119   /// already applied to the given declaration.
120   virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A,
121                                    const Decl *D) const {
122     return true;
123   }
124   /// Check if this attribute is allowed by the language we are compiling.
125   virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; }
126 
127   /// Check if this attribute is allowed when compiling for the given target.
128   virtual bool existsInTarget(const TargetInfo &Target) const { return true; }
129 
130   /// Check if this attribute's spelling is allowed when compiling for the given
131   /// target.
132   virtual bool spellingExistsInTarget(const TargetInfo &Target,
133                                       const unsigned SpellingListIndex) const {
134     return true;
135   }
136 
137   /// Convert the spelling index of Attr to a semantic spelling enum value.
138   virtual unsigned
139   spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const {
140     return UINT_MAX;
141   }
142   /// Returns true if the specified parameter index for this attribute in
143   /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof;
144   /// returns false otherwise.
145   virtual bool isParamExpr(size_t N) const { return false; }
146   /// Populate Rules with the match rules of this attribute.
147   virtual void getPragmaAttributeMatchRules(
148       llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
149       const LangOptions &LangOpts) const {}
150 
151   enum AttrHandling { NotHandled, AttributeApplied, AttributeNotApplied };
152   /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this
153   /// Decl then do so and return either AttributeApplied if it was applied or
154   /// AttributeNotApplied if it wasn't. Otherwise return NotHandled.
155   virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D,
156                                            const ParsedAttr &Attr) const {
157     return NotHandled;
158   }
159   /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this
160   /// Stmt then do so (referencing the resulting Attr in Result) and return
161   /// either AttributeApplied if it was applied or AttributeNotApplied if it
162   /// wasn't. Otherwise return NotHandled.
163   virtual AttrHandling handleStmtAttribute(Sema &S, Stmt *St,
164                                            const ParsedAttr &Attr,
165                                            class Attr *&Result) const {
166     return NotHandled;
167   }
168 
169   static const ParsedAttrInfo &get(const AttributeCommonInfo &A);
170   static ArrayRef<const ParsedAttrInfo *> getAllBuiltin();
171 };
172 
173 typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry;
174 
175 const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances();
176 
177 } // namespace clang
178 
179 namespace llvm {
180 extern template class CLANG_TEMPLATE_ABI Registry<clang::ParsedAttrInfo>;
181 } // namespace llvm
182 
183 #endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H
184