12fbf9942SAaron Ballman #include "clang/Basic/Attributes.h"
29e7bf161SAlex Lorenz #include "clang/Basic/AttrSubjectMatchRules.h"
3b79f3319SErich Keane #include "clang/Basic/AttributeCommonInfo.h"
42fbf9942SAaron Ballman #include "clang/Basic/IdentifierTable.h"
52fbf9942SAaron Ballman #include "llvm/ADT/StringSwitch.h"
62fbf9942SAaron Ballman using namespace clang;
72fbf9942SAaron Ballman 
hasAttribute(AttributeCommonInfo::Syntax Syntax,const IdentifierInfo * Scope,const IdentifierInfo * Attr,const TargetInfo & Target,const LangOptions & LangOpts)8*dd6bcdbfSLeonard Grey int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
9*dd6bcdbfSLeonard Grey                         const IdentifierInfo *Scope, const IdentifierInfo *Attr,
10*dd6bcdbfSLeonard Grey                         const TargetInfo &Target, const LangOptions &LangOpts) {
112fbf9942SAaron Ballman   StringRef Name = Attr->getName();
122fbf9942SAaron Ballman   // Normalize the attribute name, __foo__ becomes foo.
132fbf9942SAaron Ballman   if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
142fbf9942SAaron Ballman     Name = Name.substr(2, Name.size() - 4);
152fbf9942SAaron Ballman 
16c44c1742SAaron Ballman   // Normalize the scope name, but only for gnu and clang attributes.
17ad672ffbSAaron Ballman   StringRef ScopeName = Scope ? Scope->getName() : "";
18ad672ffbSAaron Ballman   if (ScopeName == "__gnu__")
19c44c1742SAaron Ballman     ScopeName = "gnu";
20c44c1742SAaron Ballman   else if (ScopeName == "_Clang")
21c44c1742SAaron Ballman     ScopeName = "clang";
22ad672ffbSAaron Ballman 
23de59f564SAaron Ballman   // As a special case, look for the omp::sequence and omp::directive
24de59f564SAaron Ballman   // attributes. We support those, but not through the typical attribute
25de59f564SAaron Ballman   // machinery that goes through TableGen. We support this in all OpenMP modes
26de59f564SAaron Ballman   // so long as double square brackets are enabled.
27de59f564SAaron Ballman   if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes &&
28de59f564SAaron Ballman       ScopeName == "omp")
29de59f564SAaron Ballman     return (Name == "directive" || Name == "sequence") ? 1 : 0;
30de59f564SAaron Ballman 
312fbf9942SAaron Ballman #include "clang/Basic/AttrHasAttributeImpl.inc"
322fbf9942SAaron Ballman 
33a0344c5dSAaron Ballman   return 0;
342fbf9942SAaron Ballman }
359e7bf161SAlex Lorenz 
getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule)369e7bf161SAlex Lorenz const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
379e7bf161SAlex Lorenz   switch (Rule) {
389e7bf161SAlex Lorenz #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
399e7bf161SAlex Lorenz   case attr::NAME:                                                             \
409e7bf161SAlex Lorenz     return SPELLING;
419e7bf161SAlex Lorenz #include "clang/Basic/AttrSubMatchRulesList.inc"
429e7bf161SAlex Lorenz   }
439e7bf161SAlex Lorenz   llvm_unreachable("Invalid subject match rule");
449e7bf161SAlex Lorenz }
45b79f3319SErich Keane 
46b79f3319SErich Keane static StringRef
normalizeAttrScopeName(const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)4775d4d4bdSJohn Brawn normalizeAttrScopeName(const IdentifierInfo *Scope,
48b79f3319SErich Keane                        AttributeCommonInfo::Syntax SyntaxUsed) {
4975d4d4bdSJohn Brawn   if (!Scope)
5075d4d4bdSJohn Brawn     return "";
5175d4d4bdSJohn Brawn 
52b79f3319SErich Keane   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
53b79f3319SErich Keane   // to be "clang".
5475d4d4bdSJohn Brawn   StringRef ScopeName = Scope->getName();
55b79f3319SErich Keane   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
56b79f3319SErich Keane       SyntaxUsed == AttributeCommonInfo::AS_C2x) {
57b79f3319SErich Keane     if (ScopeName == "__gnu__")
58b79f3319SErich Keane       ScopeName = "gnu";
59b79f3319SErich Keane     else if (ScopeName == "_Clang")
60b79f3319SErich Keane       ScopeName = "clang";
61b79f3319SErich Keane   }
62b79f3319SErich Keane   return ScopeName;
63b79f3319SErich Keane }
64b79f3319SErich Keane 
normalizeAttrName(const IdentifierInfo * Name,StringRef NormalizedScopeName,AttributeCommonInfo::Syntax SyntaxUsed)6575d4d4bdSJohn Brawn static StringRef normalizeAttrName(const IdentifierInfo *Name,
66b79f3319SErich Keane                                    StringRef NormalizedScopeName,
67b79f3319SErich Keane                                    AttributeCommonInfo::Syntax SyntaxUsed) {
68b79f3319SErich Keane   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
69b79f3319SErich Keane   // for GNU attributes, and attributes using the double square bracket syntax.
70b79f3319SErich Keane   bool ShouldNormalize =
71b79f3319SErich Keane       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
72b79f3319SErich Keane       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
73b79f3319SErich Keane         SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
74b79f3319SErich Keane        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
75b79f3319SErich Keane         NormalizedScopeName == "clang"));
7675d4d4bdSJohn Brawn   StringRef AttrName = Name->getName();
77b79f3319SErich Keane   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
78b79f3319SErich Keane       AttrName.endswith("__"))
79b79f3319SErich Keane     AttrName = AttrName.slice(2, AttrName.size() - 2);
80b79f3319SErich Keane 
81b79f3319SErich Keane   return AttrName;
82b79f3319SErich Keane }
83b79f3319SErich Keane 
isGNUScope() const84b79f3319SErich Keane bool AttributeCommonInfo::isGNUScope() const {
85b79f3319SErich Keane   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
86b79f3319SErich Keane }
87b79f3319SErich Keane 
isClangScope() const88cb08f4aaSDavid Blaikie bool AttributeCommonInfo::isClangScope() const {
89cb08f4aaSDavid Blaikie   return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
90cb08f4aaSDavid Blaikie }
91cb08f4aaSDavid Blaikie 
92b79f3319SErich Keane #include "clang/Sema/AttrParsedAttrKinds.inc"
93b79f3319SErich Keane 
normalizeName(const IdentifierInfo * Name,const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)9475d4d4bdSJohn Brawn static SmallString<64> normalizeName(const IdentifierInfo *Name,
9575d4d4bdSJohn Brawn                                      const IdentifierInfo *Scope,
9675d4d4bdSJohn Brawn                                      AttributeCommonInfo::Syntax SyntaxUsed) {
9775d4d4bdSJohn Brawn   StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
9875d4d4bdSJohn Brawn   StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
9975d4d4bdSJohn Brawn 
10075d4d4bdSJohn Brawn   SmallString<64> FullName = ScopeName;
101bc3f1710SJohn Brawn   if (!ScopeName.empty()) {
102bc3f1710SJohn Brawn     assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
103c278e8f8SHans Wennborg            SyntaxUsed == AttributeCommonInfo::AS_C2x);
10475d4d4bdSJohn Brawn     FullName += "::";
105bc3f1710SJohn Brawn   }
10675d4d4bdSJohn Brawn   FullName += AttrName;
10775d4d4bdSJohn Brawn 
10875d4d4bdSJohn Brawn   return FullName;
10975d4d4bdSJohn Brawn }
11075d4d4bdSJohn Brawn 
111b79f3319SErich Keane AttributeCommonInfo::Kind
getParsedKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)112b79f3319SErich Keane AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
113b79f3319SErich Keane                                    const IdentifierInfo *ScopeName,
114b79f3319SErich Keane                                    Syntax SyntaxUsed) {
11575d4d4bdSJohn Brawn   return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
11675d4d4bdSJohn Brawn }
117b79f3319SErich Keane 
getNormalizedFullName() const11875d4d4bdSJohn Brawn std::string AttributeCommonInfo::getNormalizedFullName() const {
11975d4d4bdSJohn Brawn   return static_cast<std::string>(
12075d4d4bdSJohn Brawn       normalizeName(getAttrName(), getScopeName(), getSyntax()));
121b79f3319SErich Keane }
122b79f3319SErich Keane 
calculateAttributeSpellingListIndex() const123b79f3319SErich Keane unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
124b79f3319SErich Keane   // Both variables will be used in tablegen generated
125b79f3319SErich Keane   // attribute spell list index matching code.
126b79f3319SErich Keane   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
12775d4d4bdSJohn Brawn   StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
12875d4d4bdSJohn Brawn   StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
129b79f3319SErich Keane 
130b79f3319SErich Keane #include "clang/Sema/AttrSpellingListIndex.inc"
131b79f3319SErich Keane }
132