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