brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.6 KiB · 2b5ad33 Raw
315 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines the ParsedAttr class implementation10//11//===----------------------------------------------------------------------===//12 13#include "clang/Sema/ParsedAttr.h"14#include "clang/AST/ASTContext.h"15#include "clang/Basic/AttrSubjectMatchRules.h"16#include "clang/Basic/IdentifierTable.h"17#include "clang/Basic/TargetInfo.h"18#include "clang/Sema/SemaInternal.h"19#include "llvm/ADT/SmallVector.h"20#include <cassert>21#include <cstddef>22#include <utility>23 24using namespace clang;25 26size_t ParsedAttr::allocated_size() const {27  if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;28  else if (IsTypeTagForDatatype)29    return AttributeFactory::TypeTagForDatatypeAllocSize;30  else if (IsProperty)31    return AttributeFactory::PropertyAllocSize;32  else if (HasParsedType)33    return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,34                            detail::TypeTagForDatatypeData, ParsedType,35                            detail::PropertyData>(0, 0, 0, 1, 0);36  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,37                          detail::TypeTagForDatatypeData, ParsedType,38                          detail::PropertyData>(NumArgs, 0, 0, 0, 0);39}40 41AttributeFactory::AttributeFactory() {42  // Go ahead and configure all the inline capacity.  This is just a memset.43  FreeLists.resize(InlineFreeListsCapacity);44}45AttributeFactory::~AttributeFactory() = default;46 47static size_t getFreeListIndexForSize(size_t size) {48  assert(size >= sizeof(ParsedAttr));49  assert((size % sizeof(void*)) == 0);50  return ((size - sizeof(ParsedAttr)) / sizeof(void *));51}52 53void *AttributeFactory::allocate(size_t size) {54  // Check for a previously reclaimed attribute.55  size_t index = getFreeListIndexForSize(size);56  if (index < FreeLists.size() && !FreeLists[index].empty()) {57    ParsedAttr *attr = FreeLists[index].pop_back_val();58    return attr;59  }60 61  // Otherwise, allocate something new.62  return Alloc.Allocate(size, alignof(AttributeFactory));63}64 65void AttributeFactory::deallocate(ParsedAttr *Attr) {66  size_t size = Attr->allocated_size();67  size_t freeListIndex = getFreeListIndexForSize(size);68 69  // Expand FreeLists to the appropriate size, if required.70  if (freeListIndex >= FreeLists.size())71    FreeLists.resize(freeListIndex + 1);72 73#ifndef NDEBUG74  // In debug mode, zero out the attribute to help find memory overwriting.75  memset(Attr, 0, size);76#endif77 78  // Add 'Attr' to the appropriate free-list.79  FreeLists[freeListIndex].push_back(Attr);80}81 82void AttributeFactory::reclaimPool(AttributePool &cur) {83  for (ParsedAttr *AL : cur.Attrs)84    deallocate(AL);85}86 87void AttributePool::takePool(AttributePool &pool) {88  llvm::append_range(Attrs, pool.Attrs);89  pool.Attrs.clear();90}91 92void AttributePool::takeFrom(ParsedAttributesView &List, AttributePool &Pool) {93  assert(&Pool != this && "AttributePool can't take attributes from itself");94  for (ParsedAttr *A : List.AttrList)95    Pool.remove(A);96  llvm::append_range(Attrs, List.AttrList);97}98 99namespace {100 101#include "clang/Sema/AttrParsedAttrImpl.inc"102 103} // namespace104 105const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {106  // If we have a ParsedAttrInfo for this ParsedAttr then return that.107  if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))108    return *AttrInfoMap[A.getParsedKind()];109 110  // If this is an ignored attribute then return an appropriate ParsedAttrInfo.111  static const ParsedAttrInfo IgnoredParsedAttrInfo(112      AttributeCommonInfo::IgnoredAttribute);113  if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)114    return IgnoredParsedAttrInfo;115 116  // Otherwise this may be an attribute defined by a plugin.117 118  // Search for a ParsedAttrInfo whose name and syntax match.119  std::string FullName = A.getNormalizedFullName();120  AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();121  if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)122    SyntaxUsed = AttributeCommonInfo::AS_Keyword;123 124  for (auto &Ptr : getAttributePluginInstances())125    if (Ptr->hasSpelling(SyntaxUsed, FullName))126      return *Ptr;127 128  // If we failed to find a match then return a default ParsedAttrInfo.129  static const ParsedAttrInfo DefaultParsedAttrInfo(130      AttributeCommonInfo::UnknownAttribute);131  return DefaultParsedAttrInfo;132}133 134ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {135  return llvm::ArrayRef(AttrInfoMap);136}137 138unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }139 140unsigned ParsedAttr::getMaxArgs() const {141  return getMinArgs() + getInfo().OptArgs;142}143 144unsigned ParsedAttr::getNumArgMembers() const {145  return getInfo().NumArgMembers;146}147 148bool ParsedAttr::hasCustomParsing() const {149  return getInfo().HasCustomParsing;150}151 152bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {153  return getInfo().diagAppertainsToDecl(S, *this, D);154}155 156bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {157  return getInfo().diagAppertainsToStmt(S, *this, St);158}159 160bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {161  return getInfo().diagMutualExclusion(S, *this, D);162}163 164bool ParsedAttr::appliesToDecl(const Decl *D,165                               attr::SubjectMatchRule MatchRule) const {166  return checkAttributeMatchRuleAppliesTo(D, MatchRule);167}168 169void ParsedAttr::getMatchRules(170    const LangOptions &LangOpts,171    SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)172    const {173  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);174}175 176bool ParsedAttr::diagnoseLangOpts(Sema &S) const {177  if (getInfo().acceptsLangOpts(S.getLangOpts()))178    return true;179  S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;180  return false;181}182 183bool ParsedAttr::isTargetSpecificAttr() const {184  return getInfo().IsTargetSpecific;185}186 187bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }188 189bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }190 191bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {192  Kind K = getParsedKind();193 194  // If the attribute has a target-specific spelling, check that it exists.195  // Only call this if the attr is not ignored/unknown. For most targets, this196  // function just returns true.197  bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute &&198                     K != NoSemaHandlerAttribute;199  bool TargetSpecificSpellingExists =200      !HasSpelling ||201      getInfo().spellingExistsInTarget(Target, getAttributeSpellingListIndex());202 203  return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists;204}205 206bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }207 208bool ParsedAttr::isSupportedByPragmaAttribute() const {209  return getInfo().IsSupportedByPragmaAttribute;210}211 212bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {213  if (isRegularKeywordAttribute())214    // The appurtenance rules are applied strictly for all regular keyword215    // atributes.216    return false;217 218  assert(isStandardAttributeSyntax() || isAlignas());219 220  // We have historically allowed some type attributes with standard attribute221  // syntax to slide to the decl-specifier-seq, so we have to keep supporting222  // it. This property is consciously not defined as a flag in Attr.td because223  // we don't want new attributes to specify it.224  //225  // Note: No new entries should be added to this list. Entries should be226  // removed from this list after a suitable deprecation period, provided that227  // there are no compatibility considerations with other compilers. If228  // possible, we would like this list to go away entirely.229  switch (getParsedKind()) {230  case AT_AddressSpace:231  case AT_OpenCLPrivateAddressSpace:232  case AT_OpenCLGlobalAddressSpace:233  case AT_OpenCLGlobalDeviceAddressSpace:234  case AT_OpenCLGlobalHostAddressSpace:235  case AT_OpenCLLocalAddressSpace:236  case AT_OpenCLConstantAddressSpace:237  case AT_OpenCLGenericAddressSpace:238  case AT_NeonPolyVectorType:239  case AT_NeonVectorType:240  case AT_ArmMveStrictPolymorphism:241  case AT_BTFTypeTag:242  case AT_ObjCGC:243  case AT_MatrixType:244    return true;245  default:246    return false;247  }248}249 250bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }251 252unsigned ParsedAttr::getSemanticSpelling() const {253  return getInfo().spellingIndexToSemanticSpelling(*this);254}255 256bool ParsedAttr::hasVariadicArg() const {257  // If the attribute has the maximum number of optional arguments, we will258  // claim that as being variadic. If we someday get an attribute that259  // legitimately bumps up against that maximum, we can use another bit to track260  // whether it's truly variadic or not.261  return getInfo().OptArgs == 15;262}263 264bool ParsedAttr::isParamExpr(size_t N) const {265  return getInfo().isParamExpr(N);266}267 268void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {269  ::handleAttrWithDelayedArgs(S, D, *this);270}271 272static unsigned getNumAttributeArgs(const ParsedAttr &AL) {273  // FIXME: Include the type in the argument list.274  return AL.getNumArgs() + AL.hasParsedType();275}276 277template <typename Compare>278static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,279                                      unsigned Num, unsigned Diag,280                                      Compare Comp) {281  if (Comp(getNumAttributeArgs(AL), Num)) {282    S.Diag(AL.getLoc(), Diag) << AL << Num;283    return false;284  }285  return true;286}287 288bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {289  return checkAttributeNumArgsImpl(S, *this, Num,290                                   diag::err_attribute_wrong_number_arguments,291                                   std::not_equal_to<unsigned>());292}293bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {294  return checkAttributeNumArgsImpl(S, *this, Num,295                                   diag::err_attribute_too_few_arguments,296                                   std::less<unsigned>());297}298bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {299  return checkAttributeNumArgsImpl(S, *this, Num,300                                   diag::err_attribute_too_many_arguments,301                                   std::greater<unsigned>());302}303 304void clang::takeAndConcatenateAttrs(ParsedAttributes &First,305                                    ParsedAttributes &&Second) {306 307  First.takeAllAppendingFrom(Second);308 309  if (!First.Range.getBegin().isValid())310    First.Range.setBegin(Second.Range.getBegin());311 312  if (Second.Range.getEnd().isValid())313    First.Range.setEnd(Second.Range.getEnd());314}315