15f757f3fSDimitry Andric //===--- Attributes.cpp ---------------------------------------------------===//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric //
95f757f3fSDimitry Andric // This file implements the AttributeCommonInfo interface.
105f757f3fSDimitry Andric //
115f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
125f757f3fSDimitry Andric
130b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
140b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
150b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
165f757f3fSDimitry Andric #include "clang/Basic/LangOptions.h"
1706c3fb27SDimitry Andric #include "clang/Basic/ParsedAttrInfo.h"
185f757f3fSDimitry Andric #include "clang/Basic/TargetInfo.h"
195f757f3fSDimitry Andric
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric
hasAttributeImpl(AttributeCommonInfo::Syntax Syntax,StringRef Name,StringRef ScopeName,const TargetInfo & Target,const LangOptions & LangOpts)2206c3fb27SDimitry Andric static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
2306c3fb27SDimitry Andric StringRef ScopeName, const TargetInfo &Target,
2406c3fb27SDimitry Andric const LangOptions &LangOpts) {
2506c3fb27SDimitry Andric
2606c3fb27SDimitry Andric #include "clang/Basic/AttrHasAttributeImpl.inc"
2706c3fb27SDimitry Andric
2806c3fb27SDimitry Andric return 0;
2906c3fb27SDimitry Andric }
3006c3fb27SDimitry Andric
hasAttribute(AttributeCommonInfo::Syntax Syntax,const IdentifierInfo * Scope,const IdentifierInfo * Attr,const TargetInfo & Target,const LangOptions & LangOpts)3181ad6265SDimitry Andric int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
3281ad6265SDimitry Andric const IdentifierInfo *Scope, const IdentifierInfo *Attr,
3381ad6265SDimitry Andric const TargetInfo &Target, const LangOptions &LangOpts) {
340b57cec5SDimitry Andric StringRef Name = Attr->getName();
350b57cec5SDimitry Andric // Normalize the attribute name, __foo__ becomes foo.
365f757f3fSDimitry Andric if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
370b57cec5SDimitry Andric Name = Name.substr(2, Name.size() - 4);
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric // Normalize the scope name, but only for gnu and clang attributes.
400b57cec5SDimitry Andric StringRef ScopeName = Scope ? Scope->getName() : "";
410b57cec5SDimitry Andric if (ScopeName == "__gnu__")
420b57cec5SDimitry Andric ScopeName = "gnu";
430b57cec5SDimitry Andric else if (ScopeName == "_Clang")
440b57cec5SDimitry Andric ScopeName = "clang";
450b57cec5SDimitry Andric
46fe6060f1SDimitry Andric // As a special case, look for the omp::sequence and omp::directive
47fe6060f1SDimitry Andric // attributes. We support those, but not through the typical attribute
48fe6060f1SDimitry Andric // machinery that goes through TableGen. We support this in all OpenMP modes
49fe6060f1SDimitry Andric // so long as double square brackets are enabled.
50*0fca6ea1SDimitry Andric //
51*0fca6ea1SDimitry Andric // Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the
52*0fca6ea1SDimitry Andric // regular attribute parsing machinery.
53*0fca6ea1SDimitry Andric if (LangOpts.OpenMP && ScopeName == "omp" &&
54*0fca6ea1SDimitry Andric (Name == "directive" || Name == "sequence"))
55*0fca6ea1SDimitry Andric return 1;
56fe6060f1SDimitry Andric
5706c3fb27SDimitry Andric int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
5806c3fb27SDimitry Andric if (res)
5906c3fb27SDimitry Andric return res;
6006c3fb27SDimitry Andric
6106c3fb27SDimitry Andric // Check if any plugin provides this attribute.
6206c3fb27SDimitry Andric for (auto &Ptr : getAttributePluginInstances())
6306c3fb27SDimitry Andric if (Ptr->hasSpelling(Syntax, Name))
6406c3fb27SDimitry Andric return 1;
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric return 0;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule)690b57cec5SDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
700b57cec5SDimitry Andric switch (Rule) {
710b57cec5SDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
720b57cec5SDimitry Andric case attr::NAME: \
730b57cec5SDimitry Andric return SPELLING;
740b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric llvm_unreachable("Invalid subject match rule");
770b57cec5SDimitry Andric }
78a7dea167SDimitry Andric
79a7dea167SDimitry Andric static StringRef
normalizeAttrScopeName(const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)805ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope,
81a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
825ffd83dbSDimitry Andric if (!Scope)
835ffd83dbSDimitry Andric return "";
845ffd83dbSDimitry Andric
85a7dea167SDimitry Andric // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
86a7dea167SDimitry Andric // to be "clang".
875ffd83dbSDimitry Andric StringRef ScopeName = Scope->getName();
88a7dea167SDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
895f757f3fSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23) {
90a7dea167SDimitry Andric if (ScopeName == "__gnu__")
91a7dea167SDimitry Andric ScopeName = "gnu";
92a7dea167SDimitry Andric else if (ScopeName == "_Clang")
93a7dea167SDimitry Andric ScopeName = "clang";
94a7dea167SDimitry Andric }
95a7dea167SDimitry Andric return ScopeName;
96a7dea167SDimitry Andric }
97a7dea167SDimitry Andric
normalizeAttrName(const IdentifierInfo * Name,StringRef NormalizedScopeName,AttributeCommonInfo::Syntax SyntaxUsed)985ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name,
99a7dea167SDimitry Andric StringRef NormalizedScopeName,
100a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
101a7dea167SDimitry Andric // Normalize the attribute name, __foo__ becomes foo. This is only allowable
102a7dea167SDimitry Andric // for GNU attributes, and attributes using the double square bracket syntax.
103a7dea167SDimitry Andric bool ShouldNormalize =
104a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_GNU ||
105a7dea167SDimitry Andric ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
1065f757f3fSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23) &&
107a7dea167SDimitry Andric (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
108a7dea167SDimitry Andric NormalizedScopeName == "clang"));
1095ffd83dbSDimitry Andric StringRef AttrName = Name->getName();
1105f757f3fSDimitry Andric if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
1115f757f3fSDimitry Andric AttrName.ends_with("__"))
112a7dea167SDimitry Andric AttrName = AttrName.slice(2, AttrName.size() - 2);
113a7dea167SDimitry Andric
114a7dea167SDimitry Andric return AttrName;
115a7dea167SDimitry Andric }
116a7dea167SDimitry Andric
isGNUScope() const117a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
118a7dea167SDimitry Andric return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
119a7dea167SDimitry Andric }
120a7dea167SDimitry Andric
isClangScope() const12181ad6265SDimitry Andric bool AttributeCommonInfo::isClangScope() const {
12281ad6265SDimitry Andric return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
12381ad6265SDimitry Andric }
12481ad6265SDimitry Andric
125a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
126a7dea167SDimitry Andric
normalizeName(const IdentifierInfo * Name,const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)1275ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name,
1285ffd83dbSDimitry Andric const IdentifierInfo *Scope,
1295ffd83dbSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) {
1305ffd83dbSDimitry Andric StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
1315ffd83dbSDimitry Andric StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
1325ffd83dbSDimitry Andric
1335ffd83dbSDimitry Andric SmallString<64> FullName = ScopeName;
1345ffd83dbSDimitry Andric if (!ScopeName.empty()) {
1355ffd83dbSDimitry Andric assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
1365f757f3fSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C23);
1375ffd83dbSDimitry Andric FullName += "::";
1385ffd83dbSDimitry Andric }
1395ffd83dbSDimitry Andric FullName += AttrName;
1405ffd83dbSDimitry Andric
1415ffd83dbSDimitry Andric return FullName;
1425ffd83dbSDimitry Andric }
1435ffd83dbSDimitry Andric
144a7dea167SDimitry Andric AttributeCommonInfo::Kind
getParsedKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)145a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
146a7dea167SDimitry Andric const IdentifierInfo *ScopeName,
147a7dea167SDimitry Andric Syntax SyntaxUsed) {
1485ffd83dbSDimitry Andric return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
1495ffd83dbSDimitry Andric }
150a7dea167SDimitry Andric
getNormalizedFullName() const1515ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const {
1525ffd83dbSDimitry Andric return static_cast<std::string>(
1535ffd83dbSDimitry Andric normalizeName(getAttrName(), getScopeName(), getSyntax()));
154a7dea167SDimitry Andric }
155a7dea167SDimitry Andric
calculateAttributeSpellingListIndex() const156a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
157a7dea167SDimitry Andric // Both variables will be used in tablegen generated
158a7dea167SDimitry Andric // attribute spell list index matching code.
159a7dea167SDimitry Andric auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
1605ffd83dbSDimitry Andric StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
1615ffd83dbSDimitry Andric StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
162a7dea167SDimitry Andric
163a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
164a7dea167SDimitry Andric }
165