ParsedAttr.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //======- ParsedAttr.cpp --------------------------------------------------===//
  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 ParsedAttr class implementation
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "clang/Sema/ParsedAttr.h"
  13. #include "clang/AST/ASTContext.h"
  14. #include "clang/Basic/AttrSubjectMatchRules.h"
  15. #include "clang/Basic/IdentifierTable.h"
  16. #include "clang/Basic/TargetInfo.h"
  17. #include "clang/Sema/SemaInternal.h"
  18. #include "llvm/ADT/SmallString.h"
  19. #include "llvm/ADT/SmallVector.h"
  20. #include "llvm/ADT/StringRef.h"
  21. #include "llvm/Support/ManagedStatic.h"
  22. #include <cassert>
  23. #include <cstddef>
  24. #include <utility>
  25. using namespace clang;
  26. LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
  27. IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
  28. IdentifierInfo *Ident) {
  29. IdentifierLoc *Result = new (Ctx) IdentifierLoc;
  30. Result->Loc = Loc;
  31. Result->Ident = Ident;
  32. return Result;
  33. }
  34. size_t ParsedAttr::allocated_size() const {
  35. if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
  36. else if (IsTypeTagForDatatype)
  37. return AttributeFactory::TypeTagForDatatypeAllocSize;
  38. else if (IsProperty)
  39. return AttributeFactory::PropertyAllocSize;
  40. else if (HasParsedType)
  41. return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
  42. detail::TypeTagForDatatypeData, ParsedType,
  43. detail::PropertyData>(0, 0, 0, 1, 0);
  44. return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
  45. detail::TypeTagForDatatypeData, ParsedType,
  46. detail::PropertyData>(NumArgs, 0, 0, 0, 0);
  47. }
  48. AttributeFactory::AttributeFactory() {
  49. // Go ahead and configure all the inline capacity. This is just a memset.
  50. FreeLists.resize(InlineFreeListsCapacity);
  51. }
  52. AttributeFactory::~AttributeFactory() = default;
  53. static size_t getFreeListIndexForSize(size_t size) {
  54. assert(size >= sizeof(ParsedAttr));
  55. assert((size % sizeof(void*)) == 0);
  56. return ((size - sizeof(ParsedAttr)) / sizeof(void *));
  57. }
  58. void *AttributeFactory::allocate(size_t size) {
  59. // Check for a previously reclaimed attribute.
  60. size_t index = getFreeListIndexForSize(size);
  61. if (index < FreeLists.size() && !FreeLists[index].empty()) {
  62. ParsedAttr *attr = FreeLists[index].back();
  63. FreeLists[index].pop_back();
  64. return attr;
  65. }
  66. // Otherwise, allocate something new.
  67. return Alloc.Allocate(size, alignof(AttributeFactory));
  68. }
  69. void AttributeFactory::deallocate(ParsedAttr *Attr) {
  70. size_t size = Attr->allocated_size();
  71. size_t freeListIndex = getFreeListIndexForSize(size);
  72. // Expand FreeLists to the appropriate size, if required.
  73. if (freeListIndex >= FreeLists.size())
  74. FreeLists.resize(freeListIndex + 1);
  75. #ifndef NDEBUG
  76. // In debug mode, zero out the attribute to help find memory overwriting.
  77. memset(Attr, 0, size);
  78. #endif
  79. // Add 'Attr' to the appropriate free-list.
  80. FreeLists[freeListIndex].push_back(Attr);
  81. }
  82. void AttributeFactory::reclaimPool(AttributePool &cur) {
  83. for (ParsedAttr *AL : cur.Attrs)
  84. deallocate(AL);
  85. }
  86. void AttributePool::takePool(AttributePool &pool) {
  87. Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
  88. pool.Attrs.clear();
  89. }
  90. namespace {
  91. #include "clang/Sema/AttrParsedAttrImpl.inc"
  92. } // namespace
  93. const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
  94. // If we have a ParsedAttrInfo for this ParsedAttr then return that.
  95. if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
  96. return *AttrInfoMap[A.getParsedKind()];
  97. // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
  98. static const ParsedAttrInfo IgnoredParsedAttrInfo(
  99. AttributeCommonInfo::IgnoredAttribute);
  100. if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
  101. return IgnoredParsedAttrInfo;
  102. // Otherwise this may be an attribute defined by a plugin. First instantiate
  103. // all plugin attributes if we haven't already done so.
  104. static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
  105. PluginAttrInstances;
  106. if (PluginAttrInstances->empty())
  107. for (auto It : ParsedAttrInfoRegistry::entries())
  108. PluginAttrInstances->emplace_back(It.instantiate());
  109. // Search for a ParsedAttrInfo whose name and syntax match.
  110. std::string FullName = A.getNormalizedFullName();
  111. AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
  112. if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
  113. SyntaxUsed = AttributeCommonInfo::AS_Keyword;
  114. for (auto &Ptr : *PluginAttrInstances)
  115. for (auto &S : Ptr->Spellings)
  116. if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
  117. return *Ptr;
  118. // If we failed to find a match then return a default ParsedAttrInfo.
  119. static const ParsedAttrInfo DefaultParsedAttrInfo(
  120. AttributeCommonInfo::UnknownAttribute);
  121. return DefaultParsedAttrInfo;
  122. }
  123. ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
  124. return llvm::ArrayRef(AttrInfoMap);
  125. }
  126. unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
  127. unsigned ParsedAttr::getMaxArgs() const {
  128. return getMinArgs() + getInfo().OptArgs;
  129. }
  130. unsigned ParsedAttr::getNumArgMembers() const {
  131. return getInfo().NumArgMembers;
  132. }
  133. bool ParsedAttr::hasCustomParsing() const {
  134. return getInfo().HasCustomParsing;
  135. }
  136. bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
  137. return getInfo().diagAppertainsToDecl(S, *this, D);
  138. }
  139. bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
  140. return getInfo().diagAppertainsToStmt(S, *this, St);
  141. }
  142. bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
  143. return getInfo().diagMutualExclusion(S, *this, D);
  144. }
  145. bool ParsedAttr::appliesToDecl(const Decl *D,
  146. attr::SubjectMatchRule MatchRule) const {
  147. return checkAttributeMatchRuleAppliesTo(D, MatchRule);
  148. }
  149. void ParsedAttr::getMatchRules(
  150. const LangOptions &LangOpts,
  151. SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
  152. const {
  153. return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
  154. }
  155. bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
  156. if (getInfo().acceptsLangOpts(S.getLangOpts()))
  157. return true;
  158. S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
  159. return false;
  160. }
  161. bool ParsedAttr::isTargetSpecificAttr() const {
  162. return getInfo().IsTargetSpecific;
  163. }
  164. bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
  165. bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
  166. bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
  167. return getInfo().existsInTarget(Target);
  168. }
  169. bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
  170. bool ParsedAttr::isSupportedByPragmaAttribute() const {
  171. return getInfo().IsSupportedByPragmaAttribute;
  172. }
  173. bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
  174. assert(isStandardAttributeSyntax());
  175. // We have historically allowed some type attributes with standard attribute
  176. // syntax to slide to the decl-specifier-seq, so we have to keep supporting
  177. // it. This property is consciously not defined as a flag in Attr.td because
  178. // we don't want new attributes to specify it.
  179. //
  180. // Note: No new entries should be added to this list. Entries should be
  181. // removed from this list after a suitable deprecation period, provided that
  182. // there are no compatibility considerations with other compilers. If
  183. // possible, we would like this list to go away entirely.
  184. switch (getParsedKind()) {
  185. case AT_AddressSpace:
  186. case AT_OpenCLPrivateAddressSpace:
  187. case AT_OpenCLGlobalAddressSpace:
  188. case AT_OpenCLGlobalDeviceAddressSpace:
  189. case AT_OpenCLGlobalHostAddressSpace:
  190. case AT_OpenCLLocalAddressSpace:
  191. case AT_OpenCLConstantAddressSpace:
  192. case AT_OpenCLGenericAddressSpace:
  193. case AT_NeonPolyVectorType:
  194. case AT_NeonVectorType:
  195. case AT_ArmMveStrictPolymorphism:
  196. case AT_BTFTypeTag:
  197. case AT_ObjCGC:
  198. case AT_MatrixType:
  199. return true;
  200. default:
  201. return false;
  202. }
  203. }
  204. bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
  205. unsigned ParsedAttr::getSemanticSpelling() const {
  206. return getInfo().spellingIndexToSemanticSpelling(*this);
  207. }
  208. bool ParsedAttr::hasVariadicArg() const {
  209. // If the attribute has the maximum number of optional arguments, we will
  210. // claim that as being variadic. If we someday get an attribute that
  211. // legitimately bumps up against that maximum, we can use another bit to track
  212. // whether it's truly variadic or not.
  213. return getInfo().OptArgs == 15;
  214. }
  215. bool ParsedAttr::isParamExpr(size_t N) const {
  216. return getInfo().isParamExpr(N);
  217. }
  218. void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
  219. ::handleAttrWithDelayedArgs(S, D, *this);
  220. }
  221. static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
  222. // FIXME: Include the type in the argument list.
  223. return AL.getNumArgs() + AL.hasParsedType();
  224. }
  225. template <typename Compare>
  226. static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
  227. unsigned Num, unsigned Diag,
  228. Compare Comp) {
  229. if (Comp(getNumAttributeArgs(AL), Num)) {
  230. S.Diag(AL.getLoc(), Diag) << AL << Num;
  231. return false;
  232. }
  233. return true;
  234. }
  235. bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
  236. return checkAttributeNumArgsImpl(S, *this, Num,
  237. diag::err_attribute_wrong_number_arguments,
  238. std::not_equal_to<unsigned>());
  239. }
  240. bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
  241. return checkAttributeNumArgsImpl(S, *this, Num,
  242. diag::err_attribute_too_few_arguments,
  243. std::less<unsigned>());
  244. }
  245. bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
  246. return checkAttributeNumArgsImpl(S, *this, Num,
  247. diag::err_attribute_too_many_arguments,
  248. std::greater<unsigned>());
  249. }
  250. void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
  251. ParsedAttributes &Second,
  252. ParsedAttributes &Result) {
  253. // Note that takeAllFrom() puts the attributes at the beginning of the list,
  254. // so to obtain the correct ordering, we add `Second`, then `First`.
  255. Result.takeAllFrom(Second);
  256. Result.takeAllFrom(First);
  257. if (First.Range.getBegin().isValid())
  258. Result.Range.setBegin(First.Range.getBegin());
  259. else
  260. Result.Range.setBegin(Second.Range.getBegin());
  261. if (Second.Range.getEnd().isValid())
  262. Result.Range.setEnd(Second.Range.getEnd());
  263. else
  264. Result.Range.setEnd(First.Range.getEnd());
  265. }