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