xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Basic/Attributes.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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