/src/llvm-project/clang/lib/Basic/Attributes.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Attributes.cpp ---------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements the AttributeCommonInfo interface. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/Basic/Attributes.h" |
14 | | #include "clang/Basic/AttrSubjectMatchRules.h" |
15 | | #include "clang/Basic/IdentifierTable.h" |
16 | | #include "clang/Basic/LangOptions.h" |
17 | | #include "clang/Basic/ParsedAttrInfo.h" |
18 | | #include "clang/Basic/TargetInfo.h" |
19 | | |
20 | | using namespace clang; |
21 | | |
22 | | static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name, |
23 | | StringRef ScopeName, const TargetInfo &Target, |
24 | 0 | const LangOptions &LangOpts) { |
25 | |
|
26 | 0 | #include "clang/Basic/AttrHasAttributeImpl.inc" |
27 | | |
28 | 0 | return 0; |
29 | 0 | } |
30 | | |
31 | | int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, |
32 | | const IdentifierInfo *Scope, const IdentifierInfo *Attr, |
33 | 0 | const TargetInfo &Target, const LangOptions &LangOpts) { |
34 | 0 | StringRef Name = Attr->getName(); |
35 | | // Normalize the attribute name, __foo__ becomes foo. |
36 | 0 | if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__")) |
37 | 0 | Name = Name.substr(2, Name.size() - 4); |
38 | | |
39 | | // Normalize the scope name, but only for gnu and clang attributes. |
40 | 0 | StringRef ScopeName = Scope ? Scope->getName() : ""; |
41 | 0 | if (ScopeName == "__gnu__") |
42 | 0 | ScopeName = "gnu"; |
43 | 0 | else if (ScopeName == "_Clang") |
44 | 0 | ScopeName = "clang"; |
45 | | |
46 | | // As a special case, look for the omp::sequence and omp::directive |
47 | | // attributes. We support those, but not through the typical attribute |
48 | | // machinery that goes through TableGen. We support this in all OpenMP modes |
49 | | // so long as double square brackets are enabled. |
50 | 0 | if (LangOpts.OpenMP && ScopeName == "omp") |
51 | 0 | return (Name == "directive" || Name == "sequence") ? 1 : 0; |
52 | | |
53 | 0 | int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts); |
54 | 0 | if (res) |
55 | 0 | return res; |
56 | | |
57 | | // Check if any plugin provides this attribute. |
58 | 0 | for (auto &Ptr : getAttributePluginInstances()) |
59 | 0 | if (Ptr->hasSpelling(Syntax, Name)) |
60 | 0 | return 1; |
61 | | |
62 | 0 | return 0; |
63 | 0 | } |
64 | | |
65 | 0 | const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) { |
66 | 0 | switch (Rule) { |
67 | 0 | #define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \ |
68 | 0 | case attr::NAME: \ |
69 | 0 | return SPELLING; |
70 | 0 | #include "clang/Basic/AttrSubMatchRulesList.inc" |
71 | 0 | } |
72 | 0 | llvm_unreachable("Invalid subject match rule"); |
73 | 0 | } |
74 | | |
75 | | static StringRef |
76 | | normalizeAttrScopeName(const IdentifierInfo *Scope, |
77 | 0 | AttributeCommonInfo::Syntax SyntaxUsed) { |
78 | 0 | if (!Scope) |
79 | 0 | return ""; |
80 | | |
81 | | // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name |
82 | | // to be "clang". |
83 | 0 | StringRef ScopeName = Scope->getName(); |
84 | 0 | if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 || |
85 | 0 | SyntaxUsed == AttributeCommonInfo::AS_C23) { |
86 | 0 | if (ScopeName == "__gnu__") |
87 | 0 | ScopeName = "gnu"; |
88 | 0 | else if (ScopeName == "_Clang") |
89 | 0 | ScopeName = "clang"; |
90 | 0 | } |
91 | 0 | return ScopeName; |
92 | 0 | } |
93 | | |
94 | | static StringRef normalizeAttrName(const IdentifierInfo *Name, |
95 | | StringRef NormalizedScopeName, |
96 | 0 | AttributeCommonInfo::Syntax SyntaxUsed) { |
97 | | // Normalize the attribute name, __foo__ becomes foo. This is only allowable |
98 | | // for GNU attributes, and attributes using the double square bracket syntax. |
99 | 0 | bool ShouldNormalize = |
100 | 0 | SyntaxUsed == AttributeCommonInfo::AS_GNU || |
101 | 0 | ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 || |
102 | 0 | SyntaxUsed == AttributeCommonInfo::AS_C23) && |
103 | 0 | (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" || |
104 | 0 | NormalizedScopeName == "clang")); |
105 | 0 | StringRef AttrName = Name->getName(); |
106 | 0 | if (ShouldNormalize && AttrName.size() >= 4 && AttrName.starts_with("__") && |
107 | 0 | AttrName.ends_with("__")) |
108 | 0 | AttrName = AttrName.slice(2, AttrName.size() - 2); |
109 | |
|
110 | 0 | return AttrName; |
111 | 0 | } |
112 | | |
113 | 0 | bool AttributeCommonInfo::isGNUScope() const { |
114 | 0 | return ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__")); |
115 | 0 | } |
116 | | |
117 | 0 | bool AttributeCommonInfo::isClangScope() const { |
118 | 0 | return ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")); |
119 | 0 | } |
120 | | |
121 | | #include "clang/Sema/AttrParsedAttrKinds.inc" |
122 | | |
123 | | static SmallString<64> normalizeName(const IdentifierInfo *Name, |
124 | | const IdentifierInfo *Scope, |
125 | 0 | AttributeCommonInfo::Syntax SyntaxUsed) { |
126 | 0 | StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed); |
127 | 0 | StringRef AttrName = normalizeAttrName(Name, ScopeName, SyntaxUsed); |
128 | |
|
129 | 0 | SmallString<64> FullName = ScopeName; |
130 | 0 | if (!ScopeName.empty()) { |
131 | 0 | assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 || |
132 | 0 | SyntaxUsed == AttributeCommonInfo::AS_C23); |
133 | 0 | FullName += "::"; |
134 | 0 | } |
135 | 0 | FullName += AttrName; |
136 | |
|
137 | 0 | return FullName; |
138 | 0 | } |
139 | | |
140 | | AttributeCommonInfo::Kind |
141 | | AttributeCommonInfo::getParsedKind(const IdentifierInfo *Name, |
142 | | const IdentifierInfo *ScopeName, |
143 | 0 | Syntax SyntaxUsed) { |
144 | 0 | return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed); |
145 | 0 | } |
146 | | |
147 | 0 | std::string AttributeCommonInfo::getNormalizedFullName() const { |
148 | 0 | return static_cast<std::string>( |
149 | 0 | normalizeName(getAttrName(), getScopeName(), getSyntax())); |
150 | 0 | } |
151 | | |
152 | 0 | unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const { |
153 | | // Both variables will be used in tablegen generated |
154 | | // attribute spell list index matching code. |
155 | 0 | auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax()); |
156 | 0 | StringRef Scope = normalizeAttrScopeName(getScopeName(), Syntax); |
157 | 0 | StringRef Name = normalizeAttrName(getAttrName(), Scope, Syntax); |
158 | |
|
159 | 0 | #include "clang/Sema/AttrSpellingListIndex.inc" |
160 | 0 | } |