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" 5*06c3fb27SDimitry Andric #include "clang/Basic/ParsedAttrInfo.h" 60b57cec5SDimitry Andric using namespace clang; 70b57cec5SDimitry Andric 8*06c3fb27SDimitry Andric static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name, 9*06c3fb27SDimitry Andric StringRef ScopeName, const TargetInfo &Target, 10*06c3fb27SDimitry Andric const LangOptions &LangOpts) { 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric #include "clang/Basic/AttrHasAttributeImpl.inc" 13*06c3fb27SDimitry Andric 14*06c3fb27SDimitry Andric return 0; 15*06c3fb27SDimitry Andric } 16*06c3fb27SDimitry Andric 1781ad6265SDimitry Andric int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, 1881ad6265SDimitry Andric const IdentifierInfo *Scope, const IdentifierInfo *Attr, 1981ad6265SDimitry Andric const TargetInfo &Target, const LangOptions &LangOpts) { 200b57cec5SDimitry Andric StringRef Name = Attr->getName(); 210b57cec5SDimitry Andric // Normalize the attribute name, __foo__ becomes foo. 220b57cec5SDimitry Andric if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) 230b57cec5SDimitry Andric Name = Name.substr(2, Name.size() - 4); 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric // Normalize the scope name, but only for gnu and clang attributes. 260b57cec5SDimitry Andric StringRef ScopeName = Scope ? Scope->getName() : ""; 270b57cec5SDimitry Andric if (ScopeName == "__gnu__") 280b57cec5SDimitry Andric ScopeName = "gnu"; 290b57cec5SDimitry Andric else if (ScopeName == "_Clang") 300b57cec5SDimitry Andric ScopeName = "clang"; 310b57cec5SDimitry Andric 32fe6060f1SDimitry Andric // As a special case, look for the omp::sequence and omp::directive 33fe6060f1SDimitry Andric // attributes. We support those, but not through the typical attribute 34fe6060f1SDimitry Andric // machinery that goes through TableGen. We support this in all OpenMP modes 35fe6060f1SDimitry Andric // so long as double square brackets are enabled. 36*06c3fb27SDimitry Andric if (LangOpts.OpenMP && ScopeName == "omp") 37fe6060f1SDimitry Andric return (Name == "directive" || Name == "sequence") ? 1 : 0; 38fe6060f1SDimitry Andric 39*06c3fb27SDimitry Andric int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts); 40*06c3fb27SDimitry Andric if (res) 41*06c3fb27SDimitry Andric return res; 42*06c3fb27SDimitry Andric 43*06c3fb27SDimitry Andric // Check if any plugin provides this attribute. 44*06c3fb27SDimitry Andric for (auto &Ptr : getAttributePluginInstances()) 45*06c3fb27SDimitry Andric if (Ptr->hasSpelling(Syntax, Name)) 46*06c3fb27SDimitry Andric return 1; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric return 0; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { 520b57cec5SDimitry Andric switch (Rule) { 530b57cec5SDimitry Andric #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \ 540b57cec5SDimitry Andric case attr::NAME: \ 550b57cec5SDimitry Andric return SPELLING; 560b57cec5SDimitry Andric #include "clang/Basic/AttrSubMatchRulesList.inc" 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric llvm_unreachable("Invalid subject match rule"); 590b57cec5SDimitry Andric } 60a7dea167SDimitry Andric 61a7dea167SDimitry Andric static StringRef 625ffd83dbSDimitry Andric normalizeAttrScopeName(const IdentifierInfo *Scope, 63a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 645ffd83dbSDimitry Andric if (!Scope) 655ffd83dbSDimitry Andric return ""; 665ffd83dbSDimitry Andric 67a7dea167SDimitry Andric // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name 68a7dea167SDimitry Andric // to be "clang". 695ffd83dbSDimitry Andric StringRef ScopeName = Scope->getName(); 70a7dea167SDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 71a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x) { 72a7dea167SDimitry Andric if (ScopeName == "__gnu__") 73a7dea167SDimitry Andric ScopeName = "gnu"; 74a7dea167SDimitry Andric else if (ScopeName == "_Clang") 75a7dea167SDimitry Andric ScopeName = "clang"; 76a7dea167SDimitry Andric } 77a7dea167SDimitry Andric return ScopeName; 78a7dea167SDimitry Andric } 79a7dea167SDimitry Andric 805ffd83dbSDimitry Andric static StringRef normalizeAttrName(const IdentifierInfo *Name, 81a7dea167SDimitry Andric StringRef NormalizedScopeName, 82a7dea167SDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 83a7dea167SDimitry Andric // Normalize the attribute name, __foo__ becomes foo. This is only allowable 84a7dea167SDimitry Andric // for GNU attributes, and attributes using the double square bracket syntax. 85a7dea167SDimitry Andric bool ShouldNormalize = 86a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_GNU || 87a7dea167SDimitry Andric ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 88a7dea167SDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x) && 89a7dea167SDimitry Andric (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || 90a7dea167SDimitry Andric NormalizedScopeName == "clang")); 915ffd83dbSDimitry Andric StringRef AttrName = Name->getName(); 92a7dea167SDimitry Andric if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && 93a7dea167SDimitry Andric AttrName.endswith("__")) 94a7dea167SDimitry Andric AttrName = AttrName.slice(2, AttrName.size() - 2); 95a7dea167SDimitry Andric 96a7dea167SDimitry Andric return AttrName; 97a7dea167SDimitry Andric } 98a7dea167SDimitry Andric 99a7dea167SDimitry Andric bool AttributeCommonInfo::isGNUScope() const { 100a7dea167SDimitry Andric return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); 101a7dea167SDimitry Andric } 102a7dea167SDimitry Andric 10381ad6265SDimitry Andric bool AttributeCommonInfo::isClangScope() const { 10481ad6265SDimitry Andric return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")); 10581ad6265SDimitry Andric } 10681ad6265SDimitry Andric 107a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrKinds.inc" 108a7dea167SDimitry Andric 1095ffd83dbSDimitry Andric static SmallString<64> normalizeName(const IdentifierInfo *Name, 1105ffd83dbSDimitry Andric const IdentifierInfo *Scope, 1115ffd83dbSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed) { 1125ffd83dbSDimitry Andric StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed); 1135ffd83dbSDimitry Andric StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed); 1145ffd83dbSDimitry Andric 1155ffd83dbSDimitry Andric SmallString<64> FullName = ScopeName; 1165ffd83dbSDimitry Andric if (!ScopeName.empty()) { 1175ffd83dbSDimitry Andric assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 || 1185ffd83dbSDimitry Andric SyntaxUsed == AttributeCommonInfo::AS_C2x); 1195ffd83dbSDimitry Andric FullName += "::"; 1205ffd83dbSDimitry Andric } 1215ffd83dbSDimitry Andric FullName += AttrName; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric return FullName; 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric 126a7dea167SDimitry Andric AttributeCommonInfo::Kind 127a7dea167SDimitry Andric AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, 128a7dea167SDimitry Andric const IdentifierInfo *ScopeName, 129a7dea167SDimitry Andric Syntax SyntaxUsed) { 1305ffd83dbSDimitry Andric return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); 1315ffd83dbSDimitry Andric } 132a7dea167SDimitry Andric 1335ffd83dbSDimitry Andric std::string AttributeCommonInfo::getNormalizedFullName() const { 1345ffd83dbSDimitry Andric return static_cast<std::string>( 1355ffd83dbSDimitry Andric normalizeName(getAttrName(), getScopeName(), getSyntax())); 136a7dea167SDimitry Andric } 137a7dea167SDimitry Andric 138a7dea167SDimitry Andric unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { 139a7dea167SDimitry Andric // Both variables will be used in tablegen generated 140a7dea167SDimitry Andric // attribute spell list index matching code. 141a7dea167SDimitry Andric auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); 1425ffd83dbSDimitry Andric StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax); 1435ffd83dbSDimitry Andric StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax); 144a7dea167SDimitry Andric 145a7dea167SDimitry Andric #include "clang/Sema/AttrSpellingListIndex.inc" 146a7dea167SDimitry Andric } 147