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
145}
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) {
192 return ::getAttrKind(normalizeName(Name, ScopeName, SyntaxUsed), SyntaxUsed);
193}
194
197 StringRef AttrName = normalizeAttrName(
198 Name->getName(), /*NormalizedScopeName*/ "", Syntax::AS_CXX11);
199#define CXX11_ATTR_ARGS_INFO
200 return llvm::StringSwitch<AttributeCommonInfo::AttrArgsInfo>(AttrName)
201#include "clang/Basic/CXX11AttributeInfo.inc"
203#undef CXX11_ATTR_ARGS_INFO
204}
205
207 return static_cast<std::string>(
209}
210
211std::string
213 StringRef AttrName) const {
214 return static_cast<std::string>(
215 normalizeName(AttrName, ScopeName, getSyntax()));
216}
217
219 return hasScope() ? SourceRange(AttrScope.getNameLoc(), AttrRange.getEnd())
220 : AttrRange;
221}
222
225 return llvm::StringSwitch<AttributeCommonInfo::Scope>(ScopeName)
234 .Case("riscv", AttributeCommonInfo::Scope::RISCV);
235}
236
237unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
238 // Both variables will be used in tablegen generated
239 // attribute spell list index matching code.
240 auto Syntax = static_cast<AttributeCommonInfo::Syntax>(getSyntax());
241 StringRef ScopeName = normalizeAttrScopeName(getScopeName(), Syntax);
242 StringRef Name =
244 AttributeCommonInfo::Scope ComputedScope =
246
247#include "clang/Sema/AttrSpellingListIndex.inc"
248}
249
250#define ATTR_NAME(NAME) NAME,
251static constexpr const char *AttrSpellingList[] = {
252#include "clang/Basic/AttributeSpellingList.inc"
253};
254
255#define ATTR_SCOPE_NAME(SCOPE_NAME) SCOPE_NAME,
256static constexpr const char *AttrScopeSpellingList[] = {
257#include "clang/Basic/AttributeSpellingList.inc"
258};
259
260std::optional<StringRef>
262 if (ScopeName.size() > 0 &&
263 !llvm::is_contained(AttrScopeSpellingList, ScopeName)) {
264 SimpleTypoCorrection STC(ScopeName);
265 for (const auto &Scope : AttrScopeSpellingList)
266 STC.add(Scope);
267
268 if (auto CorrectedScopeName = STC.getCorrection())
269 return CorrectedScopeName;
270 }
271 return std::nullopt;
272}
273
275 StringRef ScopeName, StringRef AttrName, const TargetInfo &Target,
276 const LangOptions &LangOpts) const {
277 if (!llvm::is_contained(AttrSpellingList, AttrName)) {
278 SimpleTypoCorrection STC(AttrName);
279 for (const auto &Attr : AttrSpellingList)
280 STC.add(Attr);
281
282 if (auto CorrectedAttrName = STC.getCorrection()) {
283 if (hasAttribute(getSyntax(), ScopeName, *CorrectedAttrName, Target,
284 LangOpts,
285 /*CheckPlugins=*/true))
286 return CorrectedAttrName;
287 }
288 }
289 return std::nullopt;
290}
static StringRef canonicalizeAttrName(StringRef Name)
Definition: Attributes.cpp:36
static StringRef normalizeAttrName(StringRef AttrName, StringRef NormalizedScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
Definition: Attributes.cpp:125
static constexpr const char * AttrScopeSpellingList[]
Definition: Attributes.cpp:256
static StringRef canonicalizeScopeName(StringRef Name)
Definition: Attributes.cpp:25
static AttributeCommonInfo::Scope getScopeFromNormalizedScopeName(StringRef ScopeName)
Definition: Attributes.cpp:224
static SmallString< 64 > normalizeName(StringRef AttrName, StringRef ScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
Definition: Attributes.cpp:164
static constexpr const char * AttrSpellingList[]
Definition: Attributes.cpp:251
static int hasAttributeImpl(AttributeCommonInfo::Syntax Syntax, StringRef Name, StringRef ScopeName, const TargetInfo &Target, const LangOptions &LangOpts)
Definition: Attributes.cpp:44
static StringRef normalizeAttrScopeName(StringRef ScopeName, AttributeCommonInfo::Syntax SyntaxUsed)
Definition: Attributes.cpp:108
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Definition: MachO.h:51
int32_t FullName
Definition: SemaARM.cpp:1180
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...
Definition: Attributes.cpp:206
Syntax
The style used to specify an attribute.
@ AS_HLSLAnnotation
<vardecl> : <annotation>
const IdentifierInfo * getScopeName() const
StringRef getNormalizedAttrName(StringRef ScopeName) const
Definition: Attributes.cpp:148
std::optional< StringRef > tryGetCorrectedAttrName(StringRef ScopeName, StringRef AttrName, const TargetInfo &Target, const LangOptions &LangOpts) const
Definition: Attributes.cpp:274
static AttrArgsInfo getCXX11AttrArgsInfo(const IdentifierInfo *Name)
Definition: Attributes.cpp:196
SourceRange getNormalizedRange() const
Definition: Attributes.cpp:218
std::optional< StringRef > tryGetCorrectedScopeName(StringRef ScopeName) const
Definition: Attributes.cpp:261
const IdentifierInfo * getAttrName() const
StringRef getNormalizedScopeName() const
Definition: Attributes.cpp:143
SourceLocation getNameLoc() const
const IdentifierInfo * getName() const
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
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...
Definition: LangOptions.h:434
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.
SourceLocation getEnd() const
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)
Definition: Attributes.cpp:97
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()