ParsedAttr.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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() < llvm::array_lengthof(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::makeArrayRef(AttrInfoMap);
  125. }
  126. unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
  127. unsigned ParsedAttr::getMaxArgs() const {
  128. return getMinArgs() + getInfo().OptArgs;
  129. }
  130. bool ParsedAttr::hasCustomParsing() const {
  131. return getInfo().HasCustomParsing;
  132. }
  133. bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
  134. return getInfo().diagAppertainsToDecl(S, *this, D);
  135. }
  136. bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
  137. return getInfo().diagAppertainsToStmt(S, *this, St);
  138. }
  139. bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
  140. return getInfo().diagMutualExclusion(S, *this, D);
  141. }
  142. bool ParsedAttr::appliesToDecl(const Decl *D,
  143. attr::SubjectMatchRule MatchRule) const {
  144. return checkAttributeMatchRuleAppliesTo(D, MatchRule);
  145. }
  146. void ParsedAttr::getMatchRules(
  147. const LangOptions &LangOpts,
  148. SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
  149. const {
  150. return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
  151. }
  152. bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
  153. if (getInfo().acceptsLangOpts(S.getLangOpts()))
  154. return true;
  155. S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
  156. return false;
  157. }
  158. bool ParsedAttr::isTargetSpecificAttr() const {
  159. return getInfo().IsTargetSpecific;
  160. }
  161. bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
  162. bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
  163. bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
  164. return getInfo().existsInTarget(Target);
  165. }
  166. bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
  167. bool ParsedAttr::isSupportedByPragmaAttribute() const {
  168. return getInfo().IsSupportedByPragmaAttribute;
  169. }
  170. unsigned ParsedAttr::getSemanticSpelling() const {
  171. return getInfo().spellingIndexToSemanticSpelling(*this);
  172. }
  173. bool ParsedAttr::hasVariadicArg() const {
  174. // If the attribute has the maximum number of optional arguments, we will
  175. // claim that as being variadic. If we someday get an attribute that
  176. // legitimately bumps up against that maximum, we can use another bit to track
  177. // whether it's truly variadic or not.
  178. return getInfo().OptArgs == 15;
  179. }
  180. static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
  181. // FIXME: Include the type in the argument list.
  182. return AL.getNumArgs() + AL.hasParsedType();
  183. }
  184. template <typename Compare>
  185. static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
  186. unsigned Num, unsigned Diag,
  187. Compare Comp) {
  188. if (Comp(getNumAttributeArgs(AL), Num)) {
  189. S.Diag(AL.getLoc(), Diag) << AL << Num;
  190. return false;
  191. }
  192. return true;
  193. }
  194. bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
  195. return checkAttributeNumArgsImpl(S, *this, Num,
  196. diag::err_attribute_wrong_number_arguments,
  197. std::not_equal_to<unsigned>());
  198. }
  199. bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
  200. return checkAttributeNumArgsImpl(S, *this, Num,
  201. diag::err_attribute_too_few_arguments,
  202. std::less<unsigned>());
  203. }
  204. bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
  205. return checkAttributeNumArgsImpl(S, *this, Num,
  206. diag::err_attribute_too_many_arguments,
  207. std::greater<unsigned>());
  208. }