123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- //======- ParsedAttr.cpp --------------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines the ParsedAttr class implementation
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Sema/ParsedAttr.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/Basic/AttrSubjectMatchRules.h"
- #include "clang/Basic/IdentifierTable.h"
- #include "clang/Basic/TargetInfo.h"
- #include "clang/Sema/SemaInternal.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Support/ManagedStatic.h"
- #include <cassert>
- #include <cstddef>
- #include <utility>
- using namespace clang;
- LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
- IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
- IdentifierInfo *Ident) {
- IdentifierLoc *Result = new (Ctx) IdentifierLoc;
- Result->Loc = Loc;
- Result->Ident = Ident;
- return Result;
- }
- size_t ParsedAttr::allocated_size() const {
- if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
- else if (IsTypeTagForDatatype)
- return AttributeFactory::TypeTagForDatatypeAllocSize;
- else if (IsProperty)
- return AttributeFactory::PropertyAllocSize;
- else if (HasParsedType)
- return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
- detail::TypeTagForDatatypeData, ParsedType,
- detail::PropertyData>(0, 0, 0, 1, 0);
- return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
- detail::TypeTagForDatatypeData, ParsedType,
- detail::PropertyData>(NumArgs, 0, 0, 0, 0);
- }
- AttributeFactory::AttributeFactory() {
- // Go ahead and configure all the inline capacity. This is just a memset.
- FreeLists.resize(InlineFreeListsCapacity);
- }
- AttributeFactory::~AttributeFactory() = default;
- static size_t getFreeListIndexForSize(size_t size) {
- assert(size >= sizeof(ParsedAttr));
- assert((size % sizeof(void*)) == 0);
- return ((size - sizeof(ParsedAttr)) / sizeof(void *));
- }
- void *AttributeFactory::allocate(size_t size) {
- // Check for a previously reclaimed attribute.
- size_t index = getFreeListIndexForSize(size);
- if (index < FreeLists.size() && !FreeLists[index].empty()) {
- ParsedAttr *attr = FreeLists[index].back();
- FreeLists[index].pop_back();
- return attr;
- }
- // Otherwise, allocate something new.
- return Alloc.Allocate(size, alignof(AttributeFactory));
- }
- void AttributeFactory::deallocate(ParsedAttr *Attr) {
- size_t size = Attr->allocated_size();
- size_t freeListIndex = getFreeListIndexForSize(size);
- // Expand FreeLists to the appropriate size, if required.
- if (freeListIndex >= FreeLists.size())
- FreeLists.resize(freeListIndex + 1);
- #ifndef NDEBUG
- // In debug mode, zero out the attribute to help find memory overwriting.
- memset(Attr, 0, size);
- #endif
- // Add 'Attr' to the appropriate free-list.
- FreeLists[freeListIndex].push_back(Attr);
- }
- void AttributeFactory::reclaimPool(AttributePool &cur) {
- for (ParsedAttr *AL : cur.Attrs)
- deallocate(AL);
- }
- void AttributePool::takePool(AttributePool &pool) {
- Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
- pool.Attrs.clear();
- }
- namespace {
- #include "clang/Sema/AttrParsedAttrImpl.inc"
- } // namespace
- const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
- // If we have a ParsedAttrInfo for this ParsedAttr then return that.
- if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
- return *AttrInfoMap[A.getParsedKind()];
- // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
- static const ParsedAttrInfo IgnoredParsedAttrInfo(
- AttributeCommonInfo::IgnoredAttribute);
- if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
- return IgnoredParsedAttrInfo;
- // Otherwise this may be an attribute defined by a plugin. First instantiate
- // all plugin attributes if we haven't already done so.
- static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
- PluginAttrInstances;
- if (PluginAttrInstances->empty())
- for (auto It : ParsedAttrInfoRegistry::entries())
- PluginAttrInstances->emplace_back(It.instantiate());
- // Search for a ParsedAttrInfo whose name and syntax match.
- std::string FullName = A.getNormalizedFullName();
- AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
- if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
- SyntaxUsed = AttributeCommonInfo::AS_Keyword;
- for (auto &Ptr : *PluginAttrInstances)
- for (auto &S : Ptr->Spellings)
- if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
- return *Ptr;
- // If we failed to find a match then return a default ParsedAttrInfo.
- static const ParsedAttrInfo DefaultParsedAttrInfo(
- AttributeCommonInfo::UnknownAttribute);
- return DefaultParsedAttrInfo;
- }
- ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
- return llvm::ArrayRef(AttrInfoMap);
- }
- unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
- unsigned ParsedAttr::getMaxArgs() const {
- return getMinArgs() + getInfo().OptArgs;
- }
- unsigned ParsedAttr::getNumArgMembers() const {
- return getInfo().NumArgMembers;
- }
- bool ParsedAttr::hasCustomParsing() const {
- return getInfo().HasCustomParsing;
- }
- bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
- return getInfo().diagAppertainsToDecl(S, *this, D);
- }
- bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
- return getInfo().diagAppertainsToStmt(S, *this, St);
- }
- bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
- return getInfo().diagMutualExclusion(S, *this, D);
- }
- bool ParsedAttr::appliesToDecl(const Decl *D,
- attr::SubjectMatchRule MatchRule) const {
- return checkAttributeMatchRuleAppliesTo(D, MatchRule);
- }
- void ParsedAttr::getMatchRules(
- const LangOptions &LangOpts,
- SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
- const {
- return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
- }
- bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
- if (getInfo().acceptsLangOpts(S.getLangOpts()))
- return true;
- S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
- return false;
- }
- bool ParsedAttr::isTargetSpecificAttr() const {
- return getInfo().IsTargetSpecific;
- }
- bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
- bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
- bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
- return getInfo().existsInTarget(Target);
- }
- bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
- bool ParsedAttr::isSupportedByPragmaAttribute() const {
- return getInfo().IsSupportedByPragmaAttribute;
- }
- bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
- assert(isStandardAttributeSyntax());
- // We have historically allowed some type attributes with standard attribute
- // syntax to slide to the decl-specifier-seq, so we have to keep supporting
- // it. This property is consciously not defined as a flag in Attr.td because
- // we don't want new attributes to specify it.
- //
- // Note: No new entries should be added to this list. Entries should be
- // removed from this list after a suitable deprecation period, provided that
- // there are no compatibility considerations with other compilers. If
- // possible, we would like this list to go away entirely.
- switch (getParsedKind()) {
- case AT_AddressSpace:
- case AT_OpenCLPrivateAddressSpace:
- case AT_OpenCLGlobalAddressSpace:
- case AT_OpenCLGlobalDeviceAddressSpace:
- case AT_OpenCLGlobalHostAddressSpace:
- case AT_OpenCLLocalAddressSpace:
- case AT_OpenCLConstantAddressSpace:
- case AT_OpenCLGenericAddressSpace:
- case AT_NeonPolyVectorType:
- case AT_NeonVectorType:
- case AT_ArmMveStrictPolymorphism:
- case AT_BTFTypeTag:
- case AT_ObjCGC:
- case AT_MatrixType:
- return true;
- default:
- return false;
- }
- }
- bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
- unsigned ParsedAttr::getSemanticSpelling() const {
- return getInfo().spellingIndexToSemanticSpelling(*this);
- }
- bool ParsedAttr::hasVariadicArg() const {
- // If the attribute has the maximum number of optional arguments, we will
- // claim that as being variadic. If we someday get an attribute that
- // legitimately bumps up against that maximum, we can use another bit to track
- // whether it's truly variadic or not.
- return getInfo().OptArgs == 15;
- }
- bool ParsedAttr::isParamExpr(size_t N) const {
- return getInfo().isParamExpr(N);
- }
- void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
- ::handleAttrWithDelayedArgs(S, D, *this);
- }
- static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
- // FIXME: Include the type in the argument list.
- return AL.getNumArgs() + AL.hasParsedType();
- }
- template <typename Compare>
- static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
- unsigned Num, unsigned Diag,
- Compare Comp) {
- if (Comp(getNumAttributeArgs(AL), Num)) {
- S.Diag(AL.getLoc(), Diag) << AL << Num;
- return false;
- }
- return true;
- }
- bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
- return checkAttributeNumArgsImpl(S, *this, Num,
- diag::err_attribute_wrong_number_arguments,
- std::not_equal_to<unsigned>());
- }
- bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
- return checkAttributeNumArgsImpl(S, *this, Num,
- diag::err_attribute_too_few_arguments,
- std::less<unsigned>());
- }
- bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
- return checkAttributeNumArgsImpl(S, *this, Num,
- diag::err_attribute_too_many_arguments,
- std::greater<unsigned>());
- }
- void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
- ParsedAttributes &Second,
- ParsedAttributes &Result) {
- // Note that takeAllFrom() puts the attributes at the beginning of the list,
- // so to obtain the correct ordering, we add `Second`, then `First`.
- Result.takeAllFrom(Second);
- Result.takeAllFrom(First);
- if (First.Range.getBegin().isValid())
- Result.Range.setBegin(First.Range.getBegin());
- else
- Result.Range.setBegin(Second.Range.getBegin());
- if (Second.Range.getEnd().isValid())
- Result.Range.setEnd(Second.Range.getEnd());
- else
- Result.Range.setEnd(First.Range.getEnd());
- }
|