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 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 } 37a7dea167SDimitry Andric 38a7dea167SDimitry Andric static StringRef 39*5ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope, 40a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 41*5ffd83dbSDimitry Andric if (!Scope) 42*5ffd83dbSDimitry Andric return ""; 43*5ffd83dbSDimitry Andric 44a7dea167SDimitry Andric // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name 45a7dea167SDimitry Andric // to be "clang". 46*5ffd83dbSDimitry Andric StringRef ScopeName = Scope->getName(); 47a7dea167SDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 48a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x) { 49a7dea167SDimitry Andric if (ScopeName == "__gnu__") 50a7dea167SDimitry Andric ScopeName = "gnu"; 51a7dea167SDimitry Andric else if (ScopeName == "_Clang") 52a7dea167SDimitry Andric ScopeName = "clang"; 53a7dea167SDimitry Andric } 54a7dea167SDimitry Andric return ScopeName; 55a7dea167SDimitry Andric } 56a7dea167SDimitry Andric 57*5ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name, 58a7dea167SDimitry Andric StringRef NormalizedScopeName, 59a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 60a7dea167SDimitry Andric // Normalize the attribute name, __foo__ becomes foo. This is only allowable 61a7dea167SDimitry Andric // for GNU attributes, and attributes using the double square bracket syntax. 62a7dea167SDimitry Andric bool ShouldNormalize = 63a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_GNU || 64a7dea167SDimitry Andric ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 65a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x) && 66a7dea167SDimitry Andric (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || 67a7dea167SDimitry Andric NormalizedScopeName == "clang")); 68*5ffd83dbSDimitry Andric StringRef AttrName = Name->getName(); 69a7dea167SDimitry Andric if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && 70a7dea167SDimitry Andric AttrName.endswith("__")) 71a7dea167SDimitry Andric AttrName = AttrName.slice(2, AttrName.size() - 2); 72a7dea167SDimitry Andric 73a7dea167SDimitry Andric return AttrName; 74a7dea167SDimitry Andric } 75a7dea167SDimitry Andric 76a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const { 77a7dea167SDimitry Andric return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); 78a7dea167SDimitry Andric } 79a7dea167SDimitry Andric 80a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc" 81a7dea167SDimitry Andric 82*5ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name, 83*5ffd83dbSDimitry Andric const IdentifierInfo *Scope, 84*5ffd83dbSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 85*5ffd83dbSDimitry Andric StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed); 86*5ffd83dbSDimitry Andric StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed); 87*5ffd83dbSDimitry Andric 88*5ffd83dbSDimitry Andric SmallString<64> FullName = ScopeName; 89*5ffd83dbSDimitry Andric if (!ScopeName.empty()) { 90*5ffd83dbSDimitry Andric assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 91*5ffd83dbSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x); 92*5ffd83dbSDimitry Andric FullName += "::"; 93*5ffd83dbSDimitry Andric } 94*5ffd83dbSDimitry Andric FullName += AttrName; 95*5ffd83dbSDimitry Andric 96*5ffd83dbSDimitry Andric return FullName; 97*5ffd83dbSDimitry Andric } 98*5ffd83dbSDimitry Andric 99a7dea167SDimitry Andric AttributeCommonInfo::Kind 100a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, 101a7dea167SDimitry Andric const IdentifierInfo *ScopeName, 102a7dea167SDimitry Andric Syntax SyntaxUsed) { 103*5ffd83dbSDimitry Andric return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); 104*5ffd83dbSDimitry Andric } 105a7dea167SDimitry Andric 106*5ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const { 107*5ffd83dbSDimitry Andric return static_cast<std::string>( 108*5ffd83dbSDimitry Andric normalizeName(getAttrName(), getScopeName(), getSyntax())); 109a7dea167SDimitry Andric } 110a7dea167SDimitry Andric 111a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { 112a7dea167SDimitry Andric // Both variables will be used in tablegen generated 113a7dea167SDimitry Andric // attribute spell list index matching code. 114a7dea167SDimitry Andric auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); 115*5ffd83dbSDimitry Andric StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax); 116*5ffd83dbSDimitry Andric StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax); 117a7dea167SDimitry Andric 118a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc" 119a7dea167SDimitry Andric } 120