1 #include "clang/Basic/Attributes.h" 2 #include "clang/Basic/AttrSubjectMatchRules.h" 3 #include "clang/Basic/AttributeCommonInfo.h" 4 #include "clang/Basic/IdentifierTable.h" 5 using namespace clang; 6 7 int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, 8 const IdentifierInfo *Scope, const IdentifierInfo *Attr, 9 const TargetInfo &Target, const LangOptions &LangOpts) { 10 StringRef Name = Attr->getName(); 11 // Normalize the attribute name, __foo__ becomes foo. 12 if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) 13 Name = Name.substr(2, Name.size() - 4); 14 15 // Normalize the scope name, but only for gnu and clang attributes. 16 StringRef ScopeName = Scope ? Scope->getName() : ""; 17 if (ScopeName == "__gnu__") 18 ScopeName = "gnu"; 19 else if (ScopeName == "_Clang") 20 ScopeName = "clang"; 21 22 // As a special case, look for the omp::sequence and omp::directive 23 // attributes. We support those, but not through the typical attribute 24 // machinery that goes through TableGen. We support this in all OpenMP modes 25 // so long as double square brackets are enabled. 26 if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes && 27 ScopeName == "omp") 28 return (Name == "directive" || Name == "sequence") ? 1 : 0; 29 30 #include "clang/Basic/AttrHasAttributeImpl.inc" 31 32 return 0; 33 } 34 35 const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { 36 switch (Rule) { 37 #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \ 38 case attr::NAME: \ 39 return SPELLING; 40 #include "clang/Basic/AttrSubMatchRulesList.inc" 41 } 42 llvm_unreachable("Invalid subject match rule"); 43 } 44 45 static StringRef 46 normalizeAttrScopeName(const IdentifierInfo *Scope, 47 AttributeCommonInfo::Syntax SyntaxUsed) { 48 if (!Scope) 49 return ""; 50 51 // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name 52 // to be "clang". 53 StringRef ScopeName = Scope->getName(); 54 if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 55 SyntaxUsed == AttributeCommonInfo::AS_C2x) { 56 if (ScopeName == "__gnu__") 57 ScopeName = "gnu"; 58 else if (ScopeName == "_Clang") 59 ScopeName = "clang"; 60 } 61 return ScopeName; 62 } 63 64 static StringRef normalizeAttrName(const IdentifierInfo *Name, 65 StringRef NormalizedScopeName, 66 AttributeCommonInfo::Syntax SyntaxUsed) { 67 // Normalize the attribute name, __foo__ becomes foo. This is only allowable 68 // for GNU attributes, and attributes using the double square bracket syntax. 69 bool ShouldNormalize = 70 SyntaxUsed == AttributeCommonInfo::AS_GNU || 71 ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 72 SyntaxUsed == AttributeCommonInfo::AS_C2x) && 73 (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || 74 NormalizedScopeName == "clang")); 75 StringRef AttrName = Name->getName(); 76 if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && 77 AttrName.endswith("__")) 78 AttrName = AttrName.slice(2, AttrName.size() - 2); 79 80 return AttrName; 81 } 82 83 bool AttributeCommonInfo::isGNUScope() const { 84 return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); 85 } 86 87 bool AttributeCommonInfo::isClangScope() const { 88 return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")); 89 } 90 91 #include "clang/Sema/AttrParsedAttrKinds.inc" 92 93 static SmallString<64> normalizeName(const IdentifierInfo *Name, 94 const IdentifierInfo *Scope, 95 AttributeCommonInfo::Syntax SyntaxUsed) { 96 StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed); 97 StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed); 98 99 SmallString<64> FullName = ScopeName; 100 if (!ScopeName.empty()) { 101 assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 102 SyntaxUsed == AttributeCommonInfo::AS_C2x); 103 FullName += "::"; 104 } 105 FullName += AttrName; 106 107 return FullName; 108 } 109 110 AttributeCommonInfo::Kind 111 AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, 112 const IdentifierInfo *ScopeName, 113 Syntax SyntaxUsed) { 114 return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); 115 } 116 117 std::string AttributeCommonInfo::getNormalizedFullName() const { 118 return static_cast<std::string>( 119 normalizeName(getAttrName(), getScopeName(), getSyntax())); 120 } 121 122 unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { 123 // Both variables will be used in tablegen generated 124 // attribute spell list index matching code. 125 auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); 126 StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax); 127 StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax); 128 129 #include "clang/Sema/AttrSpellingListIndex.inc" 130 } 131