xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Attributes.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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 
23*fe6060f1SDimitry Andric   // As a special case, look for the omp::sequence and omp::directive
24*fe6060f1SDimitry Andric   // attributes. We support those, but not through the typical attribute
25*fe6060f1SDimitry Andric   // machinery that goes through TableGen. We support this in all OpenMP modes
26*fe6060f1SDimitry Andric   // so long as double square brackets are enabled.
27*fe6060f1SDimitry Andric   if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes &&
28*fe6060f1SDimitry Andric       ScopeName == "omp")
29*fe6060f1SDimitry Andric     return (Name == "directive" || Name == "sequence") ? 1 : 0;
30*fe6060f1SDimitry Andric 
310b57cec5SDimitry Andric #include "clang/Basic/AttrHasAttributeImpl.inc"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   return 0;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
370b57cec5SDimitry Andric   switch (Rule) {
380b57cec5SDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
390b57cec5SDimitry Andric   case attr::NAME:                                                             \
400b57cec5SDimitry Andric     return SPELLING;
410b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc"
420b57cec5SDimitry Andric   }
430b57cec5SDimitry Andric   llvm_unreachable("Invalid subject match rule");
440b57cec5SDimitry Andric }
45a7dea167SDimitry Andric 
46a7dea167SDimitry Andric static StringRef
475ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope,
48a7dea167SDimitry Andric                        AttributeCommonInfo::Syntax SyntaxUsed) {
495ffd83dbSDimitry Andric   if (!Scope)
505ffd83dbSDimitry Andric     return "";
515ffd83dbSDimitry Andric 
52a7dea167SDimitry Andric   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
53a7dea167SDimitry Andric   // to be "clang".
545ffd83dbSDimitry Andric   StringRef ScopeName = Scope->getName();
55a7dea167SDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
56a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_C2x) {
57a7dea167SDimitry Andric     if (ScopeName == "__gnu__")
58a7dea167SDimitry Andric       ScopeName = "gnu";
59a7dea167SDimitry Andric     else if (ScopeName == "_Clang")
60a7dea167SDimitry Andric       ScopeName = "clang";
61a7dea167SDimitry Andric   }
62a7dea167SDimitry Andric   return ScopeName;
63a7dea167SDimitry Andric }
64a7dea167SDimitry Andric 
655ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name,
66a7dea167SDimitry Andric                                    StringRef NormalizedScopeName,
67a7dea167SDimitry Andric                                    AttributeCommonInfo::Syntax SyntaxUsed) {
68a7dea167SDimitry Andric   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
69a7dea167SDimitry Andric   // for GNU attributes, and attributes using the double square bracket syntax.
70a7dea167SDimitry Andric   bool ShouldNormalize =
71a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
72a7dea167SDimitry Andric       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
73a7dea167SDimitry Andric         SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
74a7dea167SDimitry Andric        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
75a7dea167SDimitry Andric         NormalizedScopeName == "clang"));
765ffd83dbSDimitry Andric   StringRef AttrName = Name->getName();
77a7dea167SDimitry Andric   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
78a7dea167SDimitry Andric       AttrName.endswith("__"))
79a7dea167SDimitry Andric     AttrName = AttrName.slice(2, AttrName.size() - 2);
80a7dea167SDimitry Andric 
81a7dea167SDimitry Andric   return AttrName;
82a7dea167SDimitry Andric }
83a7dea167SDimitry Andric 
84a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
85a7dea167SDimitry Andric   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
86a7dea167SDimitry Andric }
87a7dea167SDimitry Andric 
88a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
89a7dea167SDimitry Andric 
905ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name,
915ffd83dbSDimitry Andric                                      const IdentifierInfo *Scope,
925ffd83dbSDimitry Andric                                      AttributeCommonInfo::Syntax SyntaxUsed) {
935ffd83dbSDimitry Andric   StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
945ffd83dbSDimitry Andric   StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
955ffd83dbSDimitry Andric 
965ffd83dbSDimitry Andric   SmallString<64> FullName = ScopeName;
975ffd83dbSDimitry Andric   if (!ScopeName.empty()) {
985ffd83dbSDimitry Andric     assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
995ffd83dbSDimitry Andric            SyntaxUsed == AttributeCommonInfo::AS_C2x);
1005ffd83dbSDimitry Andric     FullName += "::";
1015ffd83dbSDimitry Andric   }
1025ffd83dbSDimitry Andric   FullName += AttrName;
1035ffd83dbSDimitry Andric 
1045ffd83dbSDimitry Andric   return FullName;
1055ffd83dbSDimitry Andric }
1065ffd83dbSDimitry Andric 
107a7dea167SDimitry Andric AttributeCommonInfo::Kind
108a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
109a7dea167SDimitry Andric                                    const IdentifierInfo *ScopeName,
110a7dea167SDimitry Andric                                    Syntax SyntaxUsed) {
1115ffd83dbSDimitry Andric   return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
1125ffd83dbSDimitry Andric }
113a7dea167SDimitry Andric 
1145ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const {
1155ffd83dbSDimitry Andric   return static_cast<std::string>(
1165ffd83dbSDimitry Andric       normalizeName(getAttrName(), getScopeName(), getSyntax()));
117a7dea167SDimitry Andric }
118a7dea167SDimitry Andric 
119a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
120a7dea167SDimitry Andric   // Both variables will be used in tablegen generated
121a7dea167SDimitry Andric   // attribute spell list index matching code.
122a7dea167SDimitry Andric   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
1235ffd83dbSDimitry Andric   StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
1245ffd83dbSDimitry Andric   StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
125a7dea167SDimitry Andric 
126a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
127a7dea167SDimitry Andric }
128