xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Attributes.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
20b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
3a7dea167SDimitry Andric #include "clang/Basic/AttributeCommonInfo.h"
40b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
50b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
60b57cec5SDimitry Andric using namespace clang;
70b57cec5SDimitry Andric 
80b57cec5SDimitry Andric int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
90b57cec5SDimitry Andric                         const IdentifierInfo *Attr, const TargetInfo &Target,
100b57cec5SDimitry Andric                         const LangOptions &LangOpts) {
110b57cec5SDimitry Andric   StringRef Name = Attr->getName();
120b57cec5SDimitry Andric   // Normalize the attribute name, __foo__ becomes foo.
130b57cec5SDimitry Andric   if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
140b57cec5SDimitry Andric     Name = Name.substr(2, Name.size() - 4);
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric   // Normalize the scope name, but only for gnu and clang attributes.
170b57cec5SDimitry Andric   StringRef ScopeName = Scope ? Scope->getName() : "";
180b57cec5SDimitry Andric   if (ScopeName == "__gnu__")
190b57cec5SDimitry Andric     ScopeName = "gnu";
200b57cec5SDimitry Andric   else if (ScopeName == "_Clang")
210b57cec5SDimitry Andric     ScopeName = "clang";
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "clang/Basic/AttrHasAttributeImpl.inc"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric   return 0;
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
290b57cec5SDimitry Andric   switch (Rule) {
300b57cec5SDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
310b57cec5SDimitry Andric   case attr::NAME:                                                             \
320b57cec5SDimitry Andric     return SPELLING;
330b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
340b57cec5SDimitry Andric   }
350b57cec5SDimitry Andric   llvm_unreachable("Invalid subject match rule");
360b57cec5SDimitry Andric }
37a7dea167SDimitry Andric 
38a7dea167SDimitry Andric static StringRef
39*5ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope,
40a7dea167SDimitry Andric                        AttributeCommonInfo::Syntax SyntaxUsed) {
41*5ffd83dbSDimitry Andric   if (!Scope)
42*5ffd83dbSDimitry Andric     return "";
43*5ffd83dbSDimitry Andric 
44a7dea167SDimitry Andric   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
45a7dea167SDimitry Andric   // to be "clang".
46*5ffd83dbSDimitry Andric   StringRef ScopeName = Scope->getName();
47a7dea167SDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
48a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_C2x) {
49a7dea167SDimitry Andric     if (ScopeName == "__gnu__")
50a7dea167SDimitry Andric       ScopeName = "gnu";
51a7dea167SDimitry Andric     else if (ScopeName == "_Clang")
52a7dea167SDimitry Andric       ScopeName = "clang";
53a7dea167SDimitry Andric   }
54a7dea167SDimitry Andric   return ScopeName;
55a7dea167SDimitry Andric }
56a7dea167SDimitry Andric 
57*5ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name,
58a7dea167SDimitry Andric                                    StringRef NormalizedScopeName,
59a7dea167SDimitry Andric                                    AttributeCommonInfo::Syntax SyntaxUsed) {
60a7dea167SDimitry Andric   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
61a7dea167SDimitry Andric   // for GNU attributes, and attributes using the double square bracket syntax.
62a7dea167SDimitry Andric   bool ShouldNormalize =
63a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
64a7dea167SDimitry Andric       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
65a7dea167SDimitry Andric         SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
66a7dea167SDimitry Andric        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
67a7dea167SDimitry Andric         NormalizedScopeName == "clang"));
68*5ffd83dbSDimitry Andric   StringRef AttrName = Name->getName();
69a7dea167SDimitry Andric   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
70a7dea167SDimitry Andric       AttrName.endswith("__"))
71a7dea167SDimitry Andric     AttrName = AttrName.slice(2, AttrName.size() - 2);
72a7dea167SDimitry Andric 
73a7dea167SDimitry Andric   return AttrName;
74a7dea167SDimitry Andric }
75a7dea167SDimitry Andric 
76a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
77a7dea167SDimitry Andric   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
78a7dea167SDimitry Andric }
79a7dea167SDimitry Andric 
80a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
81a7dea167SDimitry Andric 
82*5ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name,
83*5ffd83dbSDimitry Andric                                      const IdentifierInfo *Scope,
84*5ffd83dbSDimitry Andric                                      AttributeCommonInfo::Syntax SyntaxUsed) {
85*5ffd83dbSDimitry Andric   StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
86*5ffd83dbSDimitry Andric   StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
87*5ffd83dbSDimitry Andric 
88*5ffd83dbSDimitry Andric   SmallString<64> FullName = ScopeName;
89*5ffd83dbSDimitry Andric   if (!ScopeName.empty()) {
90*5ffd83dbSDimitry Andric     assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
91*5ffd83dbSDimitry Andric            SyntaxUsed == AttributeCommonInfo::AS_C2x);
92*5ffd83dbSDimitry Andric     FullName += "::";
93*5ffd83dbSDimitry Andric   }
94*5ffd83dbSDimitry Andric   FullName += AttrName;
95*5ffd83dbSDimitry Andric 
96*5ffd83dbSDimitry Andric   return FullName;
97*5ffd83dbSDimitry Andric }
98*5ffd83dbSDimitry Andric 
99a7dea167SDimitry Andric AttributeCommonInfo::Kind
100a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
101a7dea167SDimitry Andric                                    const IdentifierInfo *ScopeName,
102a7dea167SDimitry Andric                                    Syntax SyntaxUsed) {
103*5ffd83dbSDimitry Andric   return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
104*5ffd83dbSDimitry Andric }
105a7dea167SDimitry Andric 
106*5ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const {
107*5ffd83dbSDimitry Andric   return static_cast<std::string>(
108*5ffd83dbSDimitry Andric       normalizeName(getAttrName(), getScopeName(), getSyntax()));
109a7dea167SDimitry Andric }
110a7dea167SDimitry Andric 
111a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
112a7dea167SDimitry Andric   // Both variables will be used in tablegen generated
113a7dea167SDimitry Andric   // attribute spell list index matching code.
114a7dea167SDimitry Andric   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
115*5ffd83dbSDimitry Andric   StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
116*5ffd83dbSDimitry Andric   StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
117a7dea167SDimitry Andric 
118a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
119a7dea167SDimitry Andric }
120