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