Aaron Ballman | 2fbf994 | 2014-03-31 13:14:44 +0000 | [diff] [blame] | 1 | #include "clang/Basic/Attributes.h" |
Alex Lorenz | 9e7bf16 | 2017-04-18 14:33:39 +0000 | [diff] [blame] | 2 | #include "clang/Basic/AttrSubjectMatchRules.h" |
Erich Keane | b79f331 | 2019-09-16 13:58:59 +0000 | [diff] [blame] | 3 | #include "clang/Basic/AttributeCommonInfo.h" |
Aaron Ballman | 2fbf994 | 2014-03-31 13:14:44 +0000 | [diff] [blame] | 4 | #include "clang/Basic/IdentifierTable.h" |
| 5 | #include "llvm/ADT/StringSwitch.h" |
| 6 | using namespace clang; |
| 7 | |
Aaron Ballman | a0344c5 | 2014-11-14 13:44:02 +0000 | [diff] [blame] | 8 | int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, |
Bob Wilson | 7c73083 | 2015-07-20 22:57:31 +0000 | [diff] [blame] | 9 | const IdentifierInfo *Attr, const TargetInfo &Target, |
| 10 | const LangOptions &LangOpts) { |
Aaron Ballman | 2fbf994 | 2014-03-31 13:14:44 +0000 | [diff] [blame] | 11 | StringRef Name = Attr->getName(); |
| 12 | // Normalize the attribute name, __foo__ becomes foo. |
Aaron Ballman | c44c1742 | 2018-11-09 17:19:45 +0000 | [diff] [blame] | 13 | if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) |
| 14 | Name = Name.substr(2, Name.size() - 4); |
| 15 | |
| 16 | // Normalize the scope name, but only for gnu and clang attributes. |
| 17 | StringRef ScopeName = Scope ? Scope->getName() : ""; |
| 18 | if (ScopeName == "__gnu__") |
| 19 | ScopeName = "gnu"; |
| 20 | else if (ScopeName == "_Clang") |
| 21 | ScopeName = "clang"; |
| 22 | |
| 23 | #include "clang/Basic/AttrHasAttributeImpl.inc" |
| 24 | |
Erich Keane | b79f331 | 2019-09-16 13:58:59 +0000 | [diff] [blame] | 25 | return 0; |
Aaron Ballman | 2fbf994 | 2014-03-31 13:14:44 +0000 | [diff] [blame] | 26 | } |
Alex Lorenz | 9e7bf16 | 2017-04-18 14:33:39 +0000 | [diff] [blame] | 27 | |
| 28 | const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { |
| 29 | switch (Rule) { |
| 30 | #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \ |
| 31 | case attr::NAME: \ |
| 32 | return SPELLING; |
| 33 | #include "clang/Basic/AttrSubMatchRulesList.inc" |
| 34 | } |
| 35 | llvm_unreachable("Invalid subject match rule"); |
| 36 | } |
Erich Keane | b79f331 | 2019-09-16 13:58:59 +0000 | [diff] [blame] | 37 | |
| 38 | static StringRef |
| 39 | normalizeAttrScopeName(StringRef ScopeName, |
| 40 | AttributeCommonInfo::Syntax SyntaxUsed) { |
| 41 | // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name |
| 42 | // to be "clang". |
| 43 | if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || |
| 44 | SyntaxUsed == AttributeCommonInfo::AS_C2x) { |
| 45 | if (ScopeName == "__gnu__") |
| 46 | ScopeName = "gnu"; |
| 47 | else if (ScopeName == "_Clang") |
| 48 | ScopeName = "clang"; |
| 49 | } |
| 50 | return ScopeName; |
| 51 | } |
| 52 | |
| 53 | static StringRef normalizeAttrName(StringRef AttrName, |
| 54 | StringRef NormalizedScopeName, |
| 55 | AttributeCommonInfo::Syntax SyntaxUsed) { |
| 56 | // Normalize the attribute name, __foo__ becomes foo. This is only allowable |
| 57 | // for GNU attributes, and attributes using the double square bracket syntax. |
| 58 | bool ShouldNormalize = |
| 59 | SyntaxUsed == AttributeCommonInfo::AS_GNU || |
| 60 | ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || |
| 61 | SyntaxUsed == AttributeCommonInfo::AS_C2x) && |
| 62 | (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || |
| 63 | NormalizedScopeName == "clang")); |
| 64 | if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && |
| 65 | AttrName.endswith("__")) |
| 66 | AttrName = AttrName.slice(2, AttrName.size() - 2); |
| 67 | |
| 68 | return AttrName; |
| 69 | } |
| 70 | |
| 71 | bool AttributeCommonInfo::isGNUScope() const { |
| 72 | return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); |
| 73 | } |
| 74 | |
| 75 | #include "clang/Sema/AttrParsedAttrKinds.inc" |
| 76 | |
| 77 | AttributeCommonInfo::Kind |
| 78 | AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, |
| 79 | const IdentifierInfo *ScopeName, |
| 80 | Syntax SyntaxUsed) { |
| 81 | StringRef AttrName = Name->getName(); |
| 82 | |
| 83 | SmallString<64> FullName; |
| 84 | if (ScopeName) |
| 85 | FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed); |
| 86 | |
| 87 | AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); |
| 88 | |
| 89 | // Ensure that in the case of C++11 attributes, we look for '::foo' if it is |
| 90 | // unscoped. |
| 91 | if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x) |
| 92 | FullName += "::"; |
| 93 | FullName += AttrName; |
| 94 | |
| 95 | return ::getAttrKind(FullName, SyntaxUsed); |
| 96 | } |
| 97 | |
| 98 | unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { |
| 99 | // Both variables will be used in tablegen generated |
| 100 | // attribute spell list index matching code. |
| 101 | auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); |
| 102 | StringRef Scope = |
| 103 | getScopeName() ? normalizeAttrScopeName(getScopeName()->getName(), Syntax) |
| 104 | : ""; |
| 105 | StringRef Name = normalizeAttrName(getAttrName()->getName(), Scope, Syntax); |
| 106 | |
| 107 | #include "clang/Sema/AttrSpellingListIndex.inc" |
| 108 | } |