xref: /freebsd/contrib/llvm-project/clang/lib/Basic/Attributes.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
10b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
20b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
3*a7dea167SDimitry 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 }
37*a7dea167SDimitry Andric 
38*a7dea167SDimitry Andric static StringRef
39*a7dea167SDimitry Andric normalizeAttrScopeName(StringRef ScopeName,
40*a7dea167SDimitry Andric                        AttributeCommonInfo::Syntax SyntaxUsed) {
41*a7dea167SDimitry Andric   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
42*a7dea167SDimitry Andric   // to be "clang".
43*a7dea167SDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
44*a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_C2x) {
45*a7dea167SDimitry Andric     if (ScopeName == "__gnu__")
46*a7dea167SDimitry Andric       ScopeName = "gnu";
47*a7dea167SDimitry Andric     else if (ScopeName == "_Clang")
48*a7dea167SDimitry Andric       ScopeName = "clang";
49*a7dea167SDimitry Andric   }
50*a7dea167SDimitry Andric   return ScopeName;
51*a7dea167SDimitry Andric }
52*a7dea167SDimitry Andric 
53*a7dea167SDimitry Andric static StringRef normalizeAttrName(StringRef AttrName,
54*a7dea167SDimitry Andric                                    StringRef NormalizedScopeName,
55*a7dea167SDimitry Andric                                    AttributeCommonInfo::Syntax SyntaxUsed) {
56*a7dea167SDimitry Andric   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
57*a7dea167SDimitry Andric   // for GNU attributes, and attributes using the double square bracket syntax.
58*a7dea167SDimitry Andric   bool ShouldNormalize =
59*a7dea167SDimitry Andric       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
60*a7dea167SDimitry Andric       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
61*a7dea167SDimitry Andric         SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
62*a7dea167SDimitry Andric        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
63*a7dea167SDimitry Andric         NormalizedScopeName == "clang"));
64*a7dea167SDimitry Andric   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
65*a7dea167SDimitry Andric       AttrName.endswith("__"))
66*a7dea167SDimitry Andric     AttrName = AttrName.slice(2, AttrName.size() - 2);
67*a7dea167SDimitry Andric 
68*a7dea167SDimitry Andric   return AttrName;
69*a7dea167SDimitry Andric }
70*a7dea167SDimitry Andric 
71*a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const {
72*a7dea167SDimitry Andric   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
73*a7dea167SDimitry Andric }
74*a7dea167SDimitry Andric 
75*a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc"
76*a7dea167SDimitry Andric 
77*a7dea167SDimitry Andric AttributeCommonInfo::Kind
78*a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
79*a7dea167SDimitry Andric                                    const IdentifierInfo *ScopeName,
80*a7dea167SDimitry Andric                                    Syntax SyntaxUsed) {
81*a7dea167SDimitry Andric   StringRef AttrName = Name->getName();
82*a7dea167SDimitry Andric 
83*a7dea167SDimitry Andric   SmallString<64> FullName;
84*a7dea167SDimitry Andric   if (ScopeName)
85*a7dea167SDimitry Andric     FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
86*a7dea167SDimitry Andric 
87*a7dea167SDimitry Andric   AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
88*a7dea167SDimitry Andric 
89*a7dea167SDimitry Andric   // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
90*a7dea167SDimitry Andric   // unscoped.
91*a7dea167SDimitry Andric   if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
92*a7dea167SDimitry Andric     FullName += "::";
93*a7dea167SDimitry Andric   FullName += AttrName;
94*a7dea167SDimitry Andric 
95*a7dea167SDimitry Andric   return ::getAttrKind(FullName, SyntaxUsed);
96*a7dea167SDimitry Andric }
97*a7dea167SDimitry Andric 
98*a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
99*a7dea167SDimitry Andric   // Both variables will be used in tablegen generated
100*a7dea167SDimitry Andric   // attribute spell list index matching code.
101*a7dea167SDimitry Andric   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
102*a7dea167SDimitry Andric   StringRef Scope =
103*a7dea167SDimitry Andric       getScopeName() ? normalizeAttrScopeName(getScopeName()->getName(), Syntax)
104*a7dea167SDimitry Andric                      : "";
105*a7dea167SDimitry Andric   StringRef Name = normalizeAttrName(getAttrName()->getName(), Scope, Syntax);
106*a7dea167SDimitry Andric 
107*a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc"
108*a7dea167SDimitry Andric }
109