xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Attributes.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1*5f757f3fSDimitry Andric //===--- Attributes.cpp ---------------------------------------------------===//
2*5f757f3fSDimitry Andric //
3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5f757f3fSDimitry Andric //
7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
8*5f757f3fSDimitry Andric //
9*5f757f3fSDimitry Andric // This file implements the AttributeCommonInfo interface.
10*5f757f3fSDimitry Andric //
11*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
12*5f757f3fSDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
140b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
150b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
16*5f757f3fSDimitry Andric #include "clang/Basic/LangOptions.h"
1706c3fb27SDimitry Andric #include "clang/Basic/ParsedAttrInfo.h"
18*5f757f3fSDimitry Andric #include "clang/Basic/TargetInfo.h"
19*5f757f3fSDimitry Andric 
200b57cec5SDimitry Andric using namespace clang;
210b57cec5SDimitry Andric 
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 
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.
36*5f757f3fSDimitry 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.
5006c3fb27SDimitry Andric   if (LangOpts.OpenMP && ScopeName == "omp")
51fe6060f1SDimitry Andric     return (Name == "directive" || Name == "sequence") ? 1 : 0;
52fe6060f1SDimitry Andric 
5306c3fb27SDimitry Andric   int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
5406c3fb27SDimitry Andric   if (res)
5506c3fb27SDimitry Andric     return res;
5606c3fb27SDimitry Andric 
5706c3fb27SDimitry Andric   // Check if any plugin provides this attribute.
5806c3fb27SDimitry Andric   for (auto &Ptr : getAttributePluginInstances())
5906c3fb27SDimitry Andric     if (Ptr->hasSpelling(Syntax, Name))
6006c3fb27SDimitry Andric       return 1;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   return 0;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
660b57cec5SDimitry Andric   switch (Rule) {
670b57cec5SDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
680b57cec5SDimitry Andric   case attr::NAME:                                                             \
690b57cec5SDimitry Andric     return SPELLING;
700b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric   llvm_unreachable("Invalid subject match rule");
730b57cec5SDimitry Andric }
74a7dea167SDimitry Andric 
75a7dea167SDimitry Andric static StringRef
765ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope,
77a7dea167SDimitry Andric                        AttributeCommonInfo::Syntax SyntaxUsed) {
785ffd83dbSDimitry Andric   if (!Scope)
795ffd83dbSDimitry Andric     return "";
805ffd83dbSDimitry Andric 
81a7dea167SDimitry Andric   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
82a7dea167SDimitry Andric   // to be "clang".
835ffd83dbSDimitry Andric   StringRef ScopeName = Scope->getName();
84a7dea167SDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
85*5f757f3fSDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_C23) {
86a7dea167SDimitry Andric     if (ScopeName == "__gnu__")
87a7dea167SDimitry Andric       ScopeName = "gnu";
88a7dea167SDimitry Andric     else if (ScopeName == "_Clang")
89a7dea167SDimitry Andric       ScopeName = "clang";
90a7dea167SDimitry Andric   }
91a7dea167SDimitry Andric   return ScopeName;
92a7dea167SDimitry Andric }
93a7dea167SDimitry Andric 
945ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name,
95a7dea167SDimitry Andric                                    StringRef NormalizedScopeName,
96a7dea167SDimitry Andric                                    AttributeCommonInfo::Syntax SyntaxUsed) {
97a7dea167SDimitry Andric   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
98a7dea167SDimitry Andric   // for GNU attributes, and attributes using the double square bracket syntax.
99a7dea167SDimitry Andric   bool ShouldNormalize =
100a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
101a7dea167SDimitry Andric       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
102*5f757f3fSDimitry Andric         SyntaxUsed == AttributeCommonInfo::AS_C23) &&
103a7dea167SDimitry Andric        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
104a7dea167SDimitry Andric         NormalizedScopeName == "clang"));
1055ffd83dbSDimitry Andric   StringRef AttrName = Name->getName();
106*5f757f3fSDimitry Andric   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") &&
107*5f757f3fSDimitry Andric       AttrName.ends_with("__"))
108a7dea167SDimitry Andric     AttrName = AttrName.slice(2, AttrName.size() - 2);
109a7dea167SDimitry Andric 
110a7dea167SDimitry Andric   return AttrName;
111a7dea167SDimitry Andric }
112a7dea167SDimitry Andric 
113a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
114a7dea167SDimitry Andric   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
115a7dea167SDimitry Andric }
116a7dea167SDimitry Andric 
11781ad6265SDimitry Andric bool AttributeCommonInfo::isClangScope() const {
11881ad6265SDimitry Andric   return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
11981ad6265SDimitry Andric }
12081ad6265SDimitry Andric 
121a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
122a7dea167SDimitry Andric 
1235ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name,
1245ffd83dbSDimitry Andric                                      const IdentifierInfo *Scope,
1255ffd83dbSDimitry Andric                                      AttributeCommonInfo::Syntax SyntaxUsed) {
1265ffd83dbSDimitry Andric   StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
1275ffd83dbSDimitry Andric   StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
1285ffd83dbSDimitry Andric 
1295ffd83dbSDimitry Andric   SmallString<64> FullName = ScopeName;
1305ffd83dbSDimitry Andric   if (!ScopeName.empty()) {
1315ffd83dbSDimitry Andric     assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
132*5f757f3fSDimitry Andric            SyntaxUsed == AttributeCommonInfo::AS_C23);
1335ffd83dbSDimitry Andric     FullName += "::";
1345ffd83dbSDimitry Andric   }
1355ffd83dbSDimitry Andric   FullName += AttrName;
1365ffd83dbSDimitry Andric 
1375ffd83dbSDimitry Andric   return FullName;
1385ffd83dbSDimitry Andric }
1395ffd83dbSDimitry Andric 
140a7dea167SDimitry Andric AttributeCommonInfo::Kind
141a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
142a7dea167SDimitry Andric                                    const IdentifierInfo *ScopeName,
143a7dea167SDimitry Andric                                    Syntax SyntaxUsed) {
1445ffd83dbSDimitry Andric   return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
1455ffd83dbSDimitry Andric }
146a7dea167SDimitry Andric 
1475ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const {
1485ffd83dbSDimitry Andric   return static_cast<std::string>(
1495ffd83dbSDimitry Andric       normalizeName(getAttrName(), getScopeName(), getSyntax()));
150a7dea167SDimitry Andric }
151a7dea167SDimitry Andric 
152a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
153a7dea167SDimitry Andric   // Both variables will be used in tablegen generated
154a7dea167SDimitry Andric   // attribute spell list index matching code.
155a7dea167SDimitry Andric   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
1565ffd83dbSDimitry Andric   StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
1575ffd83dbSDimitry Andric   StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
158a7dea167SDimitry Andric 
159a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
160a7dea167SDimitry Andric }
161