xref: /openbsd-src/gnu/llvm/clang/lib/Basic/Attributes.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick #include "clang/Basic/Attributes.h"
2e5dd7070Spatrick #include "clang/Basic/AttrSubjectMatchRules.h"
3e5dd7070Spatrick #include "clang/Basic/AttributeCommonInfo.h"
4e5dd7070Spatrick #include "clang/Basic/IdentifierTable.h"
5e5dd7070Spatrick using namespace clang;
6e5dd7070Spatrick 
hasAttribute(AttributeCommonInfo::Syntax Syntax,const IdentifierInfo * Scope,const IdentifierInfo * Attr,const TargetInfo & Target,const LangOptions & LangOpts)7*12c85518Srobert int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
8*12c85518Srobert                         const IdentifierInfo *Scope, const IdentifierInfo *Attr,
9*12c85518Srobert                         const TargetInfo &Target, const LangOptions &LangOpts) {
10e5dd7070Spatrick   StringRef Name = Attr->getName();
11e5dd7070Spatrick   // Normalize the attribute name, __foo__ becomes foo.
12e5dd7070Spatrick   if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
13e5dd7070Spatrick     Name = Name.substr(2, Name.size() - 4);
14e5dd7070Spatrick 
15e5dd7070Spatrick   // Normalize the scope name, but only for gnu and clang attributes.
16e5dd7070Spatrick   StringRef ScopeName = Scope ? Scope->getName() : "";
17e5dd7070Spatrick   if (ScopeName == "__gnu__")
18e5dd7070Spatrick     ScopeName = "gnu";
19e5dd7070Spatrick   else if (ScopeName == "_Clang")
20e5dd7070Spatrick     ScopeName = "clang";
21e5dd7070Spatrick 
22a9ac8606Spatrick   // As a special case, look for the omp::sequence and omp::directive
23a9ac8606Spatrick   // attributes. We support those, but not through the typical attribute
24a9ac8606Spatrick   // machinery that goes through TableGen. We support this in all OpenMP modes
25a9ac8606Spatrick   // so long as double square brackets are enabled.
26a9ac8606Spatrick   if (LangOpts.OpenMP && LangOpts.DoubleSquareBracketAttributes &&
27a9ac8606Spatrick       ScopeName == "omp")
28a9ac8606Spatrick     return (Name == "directive" || Name == "sequence") ? 1 : 0;
29a9ac8606Spatrick 
30e5dd7070Spatrick #include "clang/Basic/AttrHasAttributeImpl.inc"
31e5dd7070Spatrick 
32e5dd7070Spatrick   return 0;
33e5dd7070Spatrick }
34e5dd7070Spatrick 
getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule)35e5dd7070Spatrick const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
36e5dd7070Spatrick   switch (Rule) {
37e5dd7070Spatrick #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract)                            \
38e5dd7070Spatrick   case attr::NAME:                                                             \
39e5dd7070Spatrick     return SPELLING;
40e5dd7070Spatrick #include "clang/Basic/AttrSubMatchRulesList.inc"
41e5dd7070Spatrick   }
42e5dd7070Spatrick   llvm_unreachable("Invalid subject match rule");
43e5dd7070Spatrick }
44e5dd7070Spatrick 
45e5dd7070Spatrick static StringRef
normalizeAttrScopeName(const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)46ec727ea7Spatrick normalizeAttrScopeName(const IdentifierInfo *Scope,
47e5dd7070Spatrick                        AttributeCommonInfo::Syntax SyntaxUsed) {
48ec727ea7Spatrick   if (!Scope)
49ec727ea7Spatrick     return "";
50ec727ea7Spatrick 
51e5dd7070Spatrick   // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
52e5dd7070Spatrick   // to be "clang".
53ec727ea7Spatrick   StringRef ScopeName = Scope->getName();
54e5dd7070Spatrick   if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
55e5dd7070Spatrick       SyntaxUsed == AttributeCommonInfo::AS_C2x) {
56e5dd7070Spatrick     if (ScopeName == "__gnu__")
57e5dd7070Spatrick       ScopeName = "gnu";
58e5dd7070Spatrick     else if (ScopeName == "_Clang")
59e5dd7070Spatrick       ScopeName = "clang";
60e5dd7070Spatrick   }
61e5dd7070Spatrick   return ScopeName;
62e5dd7070Spatrick }
63e5dd7070Spatrick 
normalizeAttrName(const IdentifierInfo * Name,StringRef NormalizedScopeName,AttributeCommonInfo::Syntax SyntaxUsed)64ec727ea7Spatrick static StringRef normalizeAttrName(const IdentifierInfo *Name,
65e5dd7070Spatrick                                    StringRef NormalizedScopeName,
66e5dd7070Spatrick                                    AttributeCommonInfo::Syntax SyntaxUsed) {
67e5dd7070Spatrick   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
68e5dd7070Spatrick   // for GNU attributes, and attributes using the double square bracket syntax.
69e5dd7070Spatrick   bool ShouldNormalize =
70e5dd7070Spatrick       SyntaxUsed == AttributeCommonInfo::AS_GNU ||
71e5dd7070Spatrick       ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
72e5dd7070Spatrick         SyntaxUsed == AttributeCommonInfo::AS_C2x) &&
73e5dd7070Spatrick        (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
74e5dd7070Spatrick         NormalizedScopeName == "clang"));
75ec727ea7Spatrick   StringRef AttrName = Name->getName();
76e5dd7070Spatrick   if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
77e5dd7070Spatrick       AttrName.endswith("__"))
78e5dd7070Spatrick     AttrName = AttrName.slice(2, AttrName.size() - 2);
79e5dd7070Spatrick 
80e5dd7070Spatrick   return AttrName;
81e5dd7070Spatrick }
82e5dd7070Spatrick 
isGNUScope() const83e5dd7070Spatrick bool AttributeCommonInfo::isGNUScope() const {
84e5dd7070Spatrick   return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"));
85e5dd7070Spatrick }
86e5dd7070Spatrick 
isClangScope() const87*12c85518Srobert bool AttributeCommonInfo::isClangScope() const {
88*12c85518Srobert   return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"));
89*12c85518Srobert }
90*12c85518Srobert 
91e5dd7070Spatrick #include "clang/Sema/AttrParsedAttrKinds.inc"
92e5dd7070Spatrick 
normalizeName(const IdentifierInfo * Name,const IdentifierInfo * Scope,AttributeCommonInfo::Syntax SyntaxUsed)93ec727ea7Spatrick static SmallString<64> normalizeName(const IdentifierInfo *Name,
94ec727ea7Spatrick                                      const IdentifierInfo *Scope,
95ec727ea7Spatrick                                      AttributeCommonInfo::Syntax SyntaxUsed) {
96ec727ea7Spatrick   StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
97ec727ea7Spatrick   StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed);
98ec727ea7Spatrick 
99ec727ea7Spatrick   SmallString<64> FullName = ScopeName;
100ec727ea7Spatrick   if (!ScopeName.empty()) {
101ec727ea7Spatrick     assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
102ec727ea7Spatrick            SyntaxUsed == AttributeCommonInfo::AS_C2x);
103ec727ea7Spatrick     FullName += "::";
104ec727ea7Spatrick   }
105ec727ea7Spatrick   FullName += AttrName;
106ec727ea7Spatrick 
107ec727ea7Spatrick   return FullName;
108ec727ea7Spatrick }
109ec727ea7Spatrick 
110e5dd7070Spatrick AttributeCommonInfo::Kind
getParsedKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)111e5dd7070Spatrick AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name,
112e5dd7070Spatrick                                    const IdentifierInfo *ScopeName,
113e5dd7070Spatrick                                    Syntax SyntaxUsed) {
114ec727ea7Spatrick   return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
115ec727ea7Spatrick }
116e5dd7070Spatrick 
getNormalizedFullName() const117ec727ea7Spatrick std::string AttributeCommonInfo::getNormalizedFullName() const {
118ec727ea7Spatrick   return static_cast<std::string>(
119ec727ea7Spatrick       normalizeName(getAttrName(), getScopeName(), getSyntax()));
120e5dd7070Spatrick }
121e5dd7070Spatrick 
calculateAttributeSpellingListIndex() const122e5dd7070Spatrick unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
123e5dd7070Spatrick   // Both variables will be used in tablegen generated
124e5dd7070Spatrick   // attribute spell list index matching code.
125e5dd7070Spatrick   auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
126ec727ea7Spatrick   StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax);
127ec727ea7Spatrick   StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax);
128e5dd7070Spatrick 
129e5dd7070Spatrick #include "clang/Sema/AttrSpellingListIndex.inc"
130e5dd7070Spatrick }
131