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) 77 : 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 81 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. 100 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. 107 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. 112 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. 118 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. 123 virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; } 124 125 /// Check if this attribute is allowed when compiling for the given target. 126 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. 130 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 137 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. 143 virtual bool isParamExpr(size_t N) const { return false; } 144 /// Populate Rules with the match rules of this attribute. 145 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. 153 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