Path: blob/main/contrib/llvm-project/clang/lib/Basic/Attributes.cpp
35232 views
//===--- Attributes.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the AttributeCommonInfo interface.9//10//===----------------------------------------------------------------------===//1112#include "clang/Basic/Attributes.h"13#include "clang/Basic/AttrSubjectMatchRules.h"14#include "clang/Basic/IdentifierTable.h"15#include "clang/Basic/LangOptions.h"16#include "clang/Basic/ParsedAttrInfo.h"17#include "clang/Basic/TargetInfo.h"1819using namespace clang;2021static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,22StringRef ScopeName, const TargetInfo &Target,23const LangOptions &LangOpts) {2425#include "clang/Basic/AttrHasAttributeImpl.inc"2627return 0;28}2930int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,31const IdentifierInfo *Scope, const IdentifierInfo *Attr,32const TargetInfo &Target, const LangOptions &LangOpts) {33StringRef Name = Attr->getName();34// Normalize the attribute name, __foo__ becomes foo.35if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))36Name = Name.substr(2, Name.size() - 4);3738// Normalize the scope name, but only for gnu and clang attributes.39StringRef ScopeName = Scope ? Scope->getName() : "";40if (ScopeName == "__gnu__")41ScopeName = "gnu";42else if (ScopeName == "_Clang")43ScopeName = "clang";4445// As a special case, look for the omp::sequence and omp::directive46// attributes. We support those, but not through the typical attribute47// machinery that goes through TableGen. We support this in all OpenMP modes48// so long as double square brackets are enabled.49//50// Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the51// regular attribute parsing machinery.52if (LangOpts.OpenMP && ScopeName == "omp" &&53(Name == "directive" || Name == "sequence"))54return 1;5556int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);57if (res)58return res;5960// Check if any plugin provides this attribute.61for (auto &Ptr : getAttributePluginInstances())62if (Ptr->hasSpelling(Syntax, Name))63return 1;6465return 0;66}6768const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {69switch (Rule) {70#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \71case attr::NAME: \72return SPELLING;73#include "clang/Basic/AttrSubMatchRulesList.inc"74}75llvm_unreachable("Invalid subject match rule");76}7778static StringRef79normalizeAttrScopeName(const IdentifierInfo *Scope,80AttributeCommonInfo::Syntax SyntaxUsed) {81if (!Scope)82return "";8384// Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name85// to be "clang".86StringRef ScopeName = Scope->getName();87if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||88SyntaxUsed == AttributeCommonInfo::AS_C23) {89if (ScopeName == "__gnu__")90ScopeName = "gnu";91else if (ScopeName == "_Clang")92ScopeName = "clang";93}94return ScopeName;95}9697static StringRef normalizeAttrName(const IdentifierInfo *Name,98StringRef NormalizedScopeName,99AttributeCommonInfo::Syntax SyntaxUsed) {100// Normalize the attribute name, __foo__ becomes foo. This is only allowable101// for GNU attributes, and attributes using the double square bracket syntax.102bool ShouldNormalize =103SyntaxUsed == AttributeCommonInfo::AS_GNU ||104((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||105SyntaxUsed == AttributeCommonInfo::AS_C23) &&106(NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||107NormalizedScopeName == "clang"));108StringRef AttrName = Name->getName();109if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&110AttrName.ends_with("__"))111AttrName = AttrName.slice(2, AttrName.size() - 2);112113return AttrName;114}115116bool AttributeCommonInfo::isGNUScope() const {117return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));118}119120bool AttributeCommonInfo::isClangScope() const {121return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));122}123124#include "clang/Sema/AttrParsedAttrKinds.inc"125126static SmallString<64> normalizeName(const IdentifierInfo *Name,127const IdentifierInfo *Scope,128AttributeCommonInfo::Syntax SyntaxUsed) {129StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);130StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);131132SmallString<64> FullName = ScopeName;133if (!ScopeName.empty()) {134assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||135SyntaxUsed == AttributeCommonInfo::AS_C23);136FullName += "::";137}138FullName += AttrName;139140return FullName;141}142143AttributeCommonInfo::Kind144AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,145const IdentifierInfo *ScopeName,146Syntax SyntaxUsed) {147return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);148}149150std::string AttributeCommonInfo::getNormalizedFullName() const {151return static_cast<std::string>(152normalizeName(getAttrName(), getScopeName(), getSyntax()));153}154155unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {156// Both variables will be used in tablegen generated157// attribute spell list index matching code.158auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());159StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);160StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);161162#include "clang/Sema/AttrSpellingListIndex.inc"163}164165166