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