clang 22.0.0git
Attributes.cpp
Go to the documentation of this file.
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
20
21#include "llvm/ADT/StringSwitch.h"
22
23using namespace clang;
24
25static StringRef canonicalizeScopeName(StringRef Name) {
26 // Normalize the scope name, but only for gnu and clang attributes.
27 if (Name == "__gnu__")
28 return "gnu";
29
30 if (Name == "_Clang")
31 return "clang";
32
33 return Name;
34}
35
36static StringRef canonicalizeAttrName(StringRef Name) {
37 // Normalize the attribute name, __foo__ becomes foo.
38 if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))
39 return Name.substr(2, Name.size() - 4);
40
41 return Name;
42}
43
44static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name,
45 StringRef ScopeName, const TargetInfo &Target,
46 const LangOptions &LangOpts) {
47#include "clang/Basic/AttrHasAttributeImpl.inc"
48 return 0;
49}
50
51int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax, StringRef ScopeName,
52 StringRef Name, const TargetInfo &Target,
53 const LangOptions &LangOpts, bool CheckPlugins) {
54 ScopeName = canonicalizeScopeName(ScopeName);
55 Name = canonicalizeAttrName(Name);
56
57 // As a special case, look for the omp::sequence and omp::directive
58 // attributes. We support those, but not through the typical attribute
59 // machinery that goes through TableGen. We support this in all OpenMP modes
60 // so long as double square brackets are enabled.
61 //
62 // Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the
63 // regular attribute parsing machinery.
64 if (LangOpts.OpenMP && ScopeName == "omp" &&
65 (Name == "directive" || Name == "sequence"))
66 return 1;
67
68 int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
69 if (res)
70 return res;
71
72 if (CheckPlugins) {
73 // Check if any plugin provides this attribute.
74 for (auto &Ptr : getAttributePluginInstances())
75 if (Ptr->hasSpelling(Syntax, Name))
76 return 1;
77 }
78
79 return 0;
80}
81
84 const TargetInfo &Target, const LangOptions &LangOpts,
85 bool CheckPlugins) {
86 return hasAttribute(Syntax, Scope ? Scope->getName() : "", Attr->getName(),
87 Target, LangOpts, CheckPlugins);
88}
89
92 const TargetInfo &Target, const LangOptions &LangOpts) {
93 return hasAttribute(Syntax, Scope, Attr, Target, LangOpts,
94 /*CheckPlugins=*/true);
95}
96
98 switch (Rule) {
99#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
100 case attr::NAME: \
101 return SPELLING;
102#include "clang/Basic/AttrSubMatchRulesList.inc"
103 }
104 llvm_unreachable("Invalid subject match rule");
105}
106
107static StringRef
108normalizeAttrScopeName(StringRef ScopeName,
109 AttributeCommonInfo::Syntax SyntaxUsed) {
110 if (SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
111 SyntaxUsed == AttributeCommonInfo::AS_C23)
112 return canonicalizeScopeName(ScopeName);
113
114 return ScopeName;
115}
116
117static StringRef
119 AttributeCommonInfo::Syntax SyntaxUsed) {
120 if (ScopeName)
121 return normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
122 return "";
123}
124
125static StringRef normalizeAttrName(StringRef AttrName,
126 StringRef NormalizedScopeName,
127 AttributeCommonInfo::Syntax SyntaxUsed) {
128 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
129 // for GNU attributes, and attributes using the double square bracket syntax.
130 bool ShouldNormalize =
131 SyntaxUsed == AttributeCommonInfo::AS_GNU ||
132 ((SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
133 SyntaxUsed == AttributeCommonInfo::AS_C23) &&
134 (NormalizedScopeName.empty() || NormalizedScopeName == "gnu" ||
135 NormalizedScopeName == "clang"));
136
137 if (ShouldNormalize)
138 return canonicalizeAttrName(AttrName);
139
140 return AttrName;
141}
142
146
147StringRef
149 return normalizeAttrName(getAttrName()->getName(), ScopeName, getSyntax());
150}
151
153 return AttrScope.isValid() && (AttrScope.getName()->isStr("gnu") ||
154 AttrScope.getName()->isStr("__gnu__"));
155}
156
158 return AttrScope.isValid() && (AttrScope.getName()->isStr("clang") ||
159 AttrScope.getName()->isStr("_Clang"));
160}
161
162#include "clang/Sema/AttrParsedAttrKinds.inc"
163
164static SmallString<64> normalizeName(StringRef AttrName, StringRef ScopeName,
165 AttributeCommonInfo::Syntax SyntaxUsed) {
166 std::string StrAttrName = SyntaxUsed == AttributeCommonInfo::AS_HLSLAnnotation
167 ? AttrName.lower()
168 : AttrName.str();
169 SmallString<64> FullName = ScopeName;
170 if (!ScopeName.empty()) {
171 assert(SyntaxUsed == AttributeCommonInfo::AS_CXX11 ||
172 SyntaxUsed == AttributeCommonInfo::AS_C23);
173 FullName += "::";
174 }
175 FullName += StrAttrName;
176 return FullName;
177}
178
180 const IdentifierInfo *Scope,
181 AttributeCommonInfo::Syntax SyntaxUsed) {
182 StringRef ScopeName = normalizeAttrScopeName(Scope, SyntaxUsed);
183 StringRef AttrName =
184 normalizeAttrName(Name->getName(), ScopeName, SyntaxUsed);
185 return normalizeName(AttrName, ScopeName, SyntaxUsed);
186}
187
190 const IdentifierInfo *ScopeName,
191 Syntax SyntaxUsed) {
193 ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
194 if (SyntaxUsed == AS_HLSLAnnotation &&
196 return AttributeCommonInfo::Kind::AT_HLSLUnparsedSemantic;
197 return Kind;
198}
199
202 StringRef AttrName = normalizeAttrName(
203 Name->getName(), /*NormalizedScopeName*/ "", Syntax::AS_CXX11);
204#define CXX11_ATTR_ARGS_INFO
205 return llvm::StringSwitch<AttributeCommonInfo::AttrArgsInfo>(AttrName)
206#include "clang/Basic/CXX11AttributeInfo.inc"
208#undef CXX11_ATTR_ARGS_INFO
209}
210
212 return static_cast<std::string>(
214}
215
216std::string
218 StringRef AttrName) const {
219 return static_cast<std::string>(
220 normalizeName(AttrName, ScopeName, getSyntax()));
221}
222
224 return hasScope() ? SourceRange(AttrScope.getNameLoc(), AttrRange.getEnd())
225 : AttrRange;
226}
227
230 return llvm::StringSwitch<AttributeCommonInfo::Scope>(ScopeName)
239 .Case("riscv", AttributeCommonInfo::Scope::RISCV);
240}
241
242unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
243 // Both variables will be used in tablegen generated
244 // attribute spell list index matching code.
245 auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
246 StringRef ScopeName = normalizeAttrScopeName(getScopeName(), Syntax);
247 StringRef Name =
249 AttributeCommonInfo::Scope ComputedScope =
251
252#include "clang/Sema/AttrSpellingListIndex.inc"
253}
254
255#define ATTR_NAME(NAME) NAME,
256static constexpr const char *AttrSpellingList[] = {
257#include "clang/Basic/AttributeSpellingList.inc"
258};
259
260#define ATTR_SCOPE_NAME(SCOPE_NAME) SCOPE_NAME,
261static constexpr const char *AttrScopeSpellingList[] = {
262#include "clang/Basic/AttributeSpellingList.inc"
263};
264
265std::optional<StringRef>
267 if (ScopeName.size() > 0 &&
268 !llvm::is_contained(AttrScopeSpellingList, ScopeName)) {
269 SimpleTypoCorrection STC(ScopeName);
270 for (const auto &Scope : AttrScopeSpellingList)
271 STC.add(Scope);
272
273 if (auto CorrectedScopeName = STC.getCorrection())
274 return CorrectedScopeName;
275 }
276 return std::nullopt;
277}
278
280 StringRef ScopeName, StringRef AttrName, const TargetInfo &Target,
281 const LangOptions &LangOpts) const {
282 if (!llvm::is_contained(AttrSpellingList, AttrName)) {
283 SimpleTypoCorrection STC(AttrName);
284 for (const auto &Attr : AttrSpellingList)
285 STC.add(Attr);
286
287 if (auto CorrectedAttrName = STC.getCorrection()) {
288 if (hasAttribute(getSyntax(), ScopeName, *CorrectedAttrName, Target,
289 LangOpts,
290 /*CheckPlugins=*/true))
291 return CorrectedAttrName;
292 }
293 }
294 return std::nullopt;
295}
static StringRef canonicalizeAttrName(StringRef Name)
static StringRef normalizeAttrName(StringRef AttrName, StringRef NormalizedScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
static constexpr const char * AttrScopeSpellingList[]
static StringRef canonicalizeScopeName(StringRef Name)
static AttributeCommonInfo::Scope getScopeFromNormalizedScopeName(StringRef ScopeName)
static SmallString< 64 > normalizeName(StringRef AttrName, StringRef ScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
static constexpr const char * AttrSpellingList[]
static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name, StringRef ScopeName, const TargetInfo &Target, const LangOptions &LangOpts)
static StringRef normalizeAttrScopeName(StringRef ScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Definition MachO.h:51
Attr - This represents one attribute.
Definition Attr.h:44
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
Syntax
The style used to specify an attribute.
@ AS_HLSLAnnotation
<vardecl> : <annotation>
const IdentifierInfo * getScopeName() const
StringRef getNormalizedAttrName(StringRef ScopeName) const
std::optional< StringRef > tryGetCorrectedAttrName(StringRef ScopeName, StringRef AttrName, const TargetInfo &Target, const LangOptions &LangOpts) const
static AttrArgsInfo getCXX11AttrArgsInfo(const IdentifierInfo *Name)
SourceRange getNormalizedRange() const
std::optional< StringRef > tryGetCorrectedScopeName(StringRef ScopeName) const
const IdentifierInfo * getAttrName() const
StringRef getNormalizedScopeName() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
std::optional< StringRef > getCorrection() const
void add(const StringRef Candidate)
A trivial tuple used to represent a source range.
Exposes information about the current target.
Definition TargetInfo.h:226
Defines the clang::TargetInfo interface.
SubjectMatchRule
A list of all the recognized kinds of attributes.
const char * getSubjectMatchRuleSpelling(SubjectMatchRule Rule)
StringRef getName(const HeaderType T)
Definition HeaderFile.h:38
The JSON file list parser is used to communicate input to InstallAPI.
int hasAttribute(AttributeCommonInfo::Syntax Syntax, llvm::StringRef ScopeName, llvm::StringRef AttrName, const TargetInfo &Target, const LangOptions &LangOpts, bool CheckPlugins)
Return the version number associated with the attribute if we recognize and implement the attribute s...
const std::list< std::unique_ptr< ParsedAttrInfo > > & getAttributePluginInstances()