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