17330f729Sjoerg #include "clang/Basic/Attributes.h"
27330f729Sjoerg #include "clang/Basic/AttrSubjectMatchRules.h"
37330f729Sjoerg #include "clang/Basic/AttributeCommonInfo.h"
47330f729Sjoerg #include "clang/Basic/IdentifierTable.h"
57330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
67330f729Sjoerg using namespace clang;
77330f729Sjoerg
hasAttribute(AttrSyntax Syntax,const IdentifierInfo * Scope,const IdentifierInfo * Attr,const TargetInfo & Target,const LangOptions & LangOpts)87330f729Sjoerg int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
97330f729Sjoerg const IdentifierInfo *Attr, const TargetInfo &Target,
107330f729Sjoerg const LangOptions &LangOpts) {
117330f729Sjoerg StringRef Name = Attr->getName();
127330f729Sjoerg // Normalize the attribute name, __foo__ becomes foo.
137330f729Sjoerg if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
147330f729Sjoerg Name = Name.substr(2, Name.size() - 4);
157330f729Sjoerg
167330f729Sjoerg // Normalize the scope name, but only for gnu and clang attributes.
177330f729Sjoerg StringRef ScopeName = Scope ? Scope->getName() : "";
187330f729Sjoerg if (ScopeName == "__gnu__")
197330f729Sjoerg ScopeName = "gnu";
207330f729Sjoerg else if (ScopeName == "_Clang")
217330f729Sjoerg ScopeName = "clang";
227330f729Sjoerg
237330f729Sjoerg #include "clang/Basic/AttrHasAttributeImpl.inc"
247330f729Sjoerg
257330f729Sjoerg return 0;
267330f729Sjoerg }
277330f729Sjoerg
getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule)287330f729Sjoerg const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
297330f729Sjoerg switch (Rule) {
307330f729Sjoerg #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
317330f729Sjoerg case attr::NAME: \
327330f729Sjoerg return SPELLING;
337330f729Sjoerg #include "clang/Basic/AttrSubMatchRulesList.inc"
347330f729Sjoerg }
357330f729Sjoerg llvm_unreachable("Invalid subject match rule");
367330f729Sjoerg }
377330f729Sjoerg
387330f729Sjoerg static StringRef
normalizeAttrScopeName(const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)39*e038c9c4Sjoerg normalizeAttrScopeName(const IdentifierInfo *Scope,
407330f729Sjoerg AttributeCommonInfo::Syntax SyntaxUsed) {
41*e038c9c4Sjoerg if (!Scope)
42*e038c9c4Sjoerg return "";
43*e038c9c4Sjoerg
447330f729Sjoerg // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
457330f729Sjoerg // to be "clang".
46*e038c9c4Sjoerg StringRef ScopeName = Scope->getName();
477330f729Sjoerg if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
487330f729Sjoerg SyntaxUsed == AttributeCommonInfo::AS_C2x) {
497330f729Sjoerg if (ScopeName == "__gnu__")
507330f729Sjoerg ScopeName = "gnu";
517330f729Sjoerg else if (ScopeName == "_Clang")
527330f729Sjoerg ScopeName = "clang";
537330f729Sjoerg }
547330f729Sjoerg return ScopeName;
557330f729Sjoerg }
567330f729Sjoerg
normalizeAttrName(const IdentifierInfo * Name,StringRef NormalizedScopeName,AttributeCommonInfo::Syntax SyntaxUsed)57*e038c9c4Sjoerg static StringRef normalizeAttrName(const IdentifierInfo *Name,
587330f729Sjoerg StringRef NormalizedScopeName,
597330f729Sjoerg AttributeCommonInfo::Syntax SyntaxUsed) {
607330f729Sjoerg // Normalize the attribute name, __foo__ becomes foo. This is only allowable
617330f729Sjoerg // for GNU attributes, and attributes using the double square bracket syntax.
627330f729Sjoerg bool ShouldNormalize =
637330f729Sjoerg SyntaxUsed == AttributeCommonInfo::AS_GNU ||
647330f729Sjoerg ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
657330f729Sjoerg SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
667330f729Sjoerg (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
677330f729Sjoerg NormalizedScopeName == "clang"));
68*e038c9c4Sjoerg StringRef AttrName = Name->getName();
697330f729Sjoerg if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
707330f729Sjoerg AttrName.endswith("__"))
717330f729Sjoerg AttrName = AttrName.slice(2, AttrName.size() - 2);
727330f729Sjoerg
737330f729Sjoerg return AttrName;
747330f729Sjoerg }
757330f729Sjoerg
isGNUScope() const767330f729Sjoerg bool AttributeCommonInfo::isGNUScope() const {
777330f729Sjoerg return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
787330f729Sjoerg }
797330f729Sjoerg
807330f729Sjoerg #include "clang/Sema/AttrParsedAttrKinds.inc"
817330f729Sjoerg
normalizeName(const IdentifierInfo * Name,const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)82*e038c9c4Sjoerg static SmallString<64> normalizeName(const IdentifierInfo *Name,
83*e038c9c4Sjoerg const IdentifierInfo *Scope,
84*e038c9c4Sjoerg AttributeCommonInfo::Syntax SyntaxUsed) {
85*e038c9c4Sjoerg StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
86*e038c9c4Sjoerg StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
87*e038c9c4Sjoerg
88*e038c9c4Sjoerg SmallString<64> FullName = ScopeName;
89*e038c9c4Sjoerg if (!ScopeName.empty()) {
90*e038c9c4Sjoerg assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
91*e038c9c4Sjoerg SyntaxUsed == AttributeCommonInfo::AS_C2x);
92*e038c9c4Sjoerg FullName += "::";
93*e038c9c4Sjoerg }
94*e038c9c4Sjoerg FullName += AttrName;
95*e038c9c4Sjoerg
96*e038c9c4Sjoerg return FullName;
97*e038c9c4Sjoerg }
98*e038c9c4Sjoerg
997330f729Sjoerg AttributeCommonInfo::Kind
getParsedKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)1007330f729Sjoerg AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
1017330f729Sjoerg const IdentifierInfo *ScopeName,
1027330f729Sjoerg Syntax SyntaxUsed) {
103*e038c9c4Sjoerg return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
104*e038c9c4Sjoerg }
1057330f729Sjoerg
getNormalizedFullName() const106*e038c9c4Sjoerg std::string AttributeCommonInfo::getNormalizedFullName() const {
107*e038c9c4Sjoerg return static_cast<std::string>(
108*e038c9c4Sjoerg normalizeName(getAttrName(), getScopeName(), getSyntax()));
1097330f729Sjoerg }
1107330f729Sjoerg
calculateAttributeSpellingListIndex() const1117330f729Sjoerg unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
1127330f729Sjoerg // Both variables will be used in tablegen generated
1137330f729Sjoerg // attribute spell list index matching code.
1147330f729Sjoerg auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
115*e038c9c4Sjoerg StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
116*e038c9c4Sjoerg StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
1177330f729Sjoerg
1187330f729Sjoerg #include "clang/Sema/AttrSpellingListIndex.inc"
1197330f729Sjoerg }
120