[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / lib / Sema / ParsedAttr.cpp
blobf59b01efe7ed8f4d6e81908d2ff4e343399b5c41
1 //======- ParsedAttr.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 defines the ParsedAttr class implementation
11 //===----------------------------------------------------------------------===//
13 #include "clang/Sema/ParsedAttr.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/Basic/AttrSubjectMatchRules.h"
16 #include "clang/Basic/IdentifierTable.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Sema/SemaInternal.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include <cassert>
23 #include <cstddef>
24 #include <utility>
26 using namespace clang;
28 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
29 IdentifierInfo *Ident) {
30 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
31 Result->Loc = Loc;
32 Result->Ident = Ident;
33 return Result;
36 size_t ParsedAttr::allocated_size() const {
37 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
38 else if (IsTypeTagForDatatype)
39 return AttributeFactory::TypeTagForDatatypeAllocSize;
40 else if (IsProperty)
41 return AttributeFactory::PropertyAllocSize;
42 else if (HasParsedType)
43 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
44 detail::TypeTagForDatatypeData, ParsedType,
45 detail::PropertyData>(0, 0, 0, 1, 0);
46 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47 detail::TypeTagForDatatypeData, ParsedType,
48 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
51 AttributeFactory::AttributeFactory() {
52 // Go ahead and configure all the inline capacity. This is just a memset.
53 FreeLists.resize(InlineFreeListsCapacity);
55 AttributeFactory::~AttributeFactory() = default;
57 static size_t getFreeListIndexForSize(size_t size) {
58 assert(size >= sizeof(ParsedAttr));
59 assert((size % sizeof(void*)) == 0);
60 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
63 void *AttributeFactory::allocate(size_t size) {
64 // Check for a previously reclaimed attribute.
65 size_t index = getFreeListIndexForSize(size);
66 if (index < FreeLists.size() && !FreeLists[index].empty()) {
67 ParsedAttr *attr = FreeLists[index].back();
68 FreeLists[index].pop_back();
69 return attr;
72 // Otherwise, allocate something new.
73 return Alloc.Allocate(size, alignof(AttributeFactory));
76 void AttributeFactory::deallocate(ParsedAttr *Attr) {
77 size_t size = Attr->allocated_size();
78 size_t freeListIndex = getFreeListIndexForSize(size);
80 // Expand FreeLists to the appropriate size, if required.
81 if (freeListIndex >= FreeLists.size())
82 FreeLists.resize(freeListIndex + 1);
84 #ifndef NDEBUG
85 // In debug mode, zero out the attribute to help find memory overwriting.
86 memset(Attr, 0, size);
87 #endif
89 // Add 'Attr' to the appropriate free-list.
90 FreeLists[freeListIndex].push_back(Attr);
93 void AttributeFactory::reclaimPool(AttributePool &cur) {
94 for (ParsedAttr *AL : cur.Attrs)
95 deallocate(AL);
98 void AttributePool::takePool(AttributePool &pool) {
99 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100 pool.Attrs.clear();
103 namespace {
105 #include "clang/Sema/AttrParsedAttrImpl.inc"
107 } // namespace
109 const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
110 // If we have a ParsedAttrInfo for this ParsedAttr then return that.
111 if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
112 return *AttrInfoMap[A.getParsedKind()];
114 // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
115 static const ParsedAttrInfo IgnoredParsedAttrInfo(
116 AttributeCommonInfo::IgnoredAttribute);
117 if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
118 return IgnoredParsedAttrInfo;
120 // Otherwise this may be an attribute defined by a plugin.
122 // Search for a ParsedAttrInfo whose name and syntax match.
123 std::string FullName = A.getNormalizedFullName();
124 AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
125 if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
126 SyntaxUsed = AttributeCommonInfo::AS_Keyword;
128 for (auto &Ptr : getAttributePluginInstances())
129 if (Ptr->hasSpelling(SyntaxUsed, FullName))
130 return *Ptr;
132 // If we failed to find a match then return a default ParsedAttrInfo.
133 static const ParsedAttrInfo DefaultParsedAttrInfo(
134 AttributeCommonInfo::UnknownAttribute);
135 return DefaultParsedAttrInfo;
138 ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
139 return llvm::ArrayRef(AttrInfoMap);
142 unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
144 unsigned ParsedAttr::getMaxArgs() const {
145 return getMinArgs() + getInfo().OptArgs;
148 unsigned ParsedAttr::getNumArgMembers() const {
149 return getInfo().NumArgMembers;
152 bool ParsedAttr::hasCustomParsing() const {
153 return getInfo().HasCustomParsing;
156 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
157 return getInfo().diagAppertainsToDecl(S, *this, D);
160 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
161 return getInfo().diagAppertainsToStmt(S, *this, St);
164 bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
165 return getInfo().diagMutualExclusion(S, *this, D);
168 bool ParsedAttr::appliesToDecl(const Decl *D,
169 attr::SubjectMatchRule MatchRule) const {
170 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
173 void ParsedAttr::getMatchRules(
174 const LangOptions &LangOpts,
175 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
176 const {
177 return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
180 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
181 if (getInfo().acceptsLangOpts(S.getLangOpts()))
182 return true;
183 S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
184 return false;
187 bool ParsedAttr::isTargetSpecificAttr() const {
188 return getInfo().IsTargetSpecific;
191 bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
193 bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
195 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
196 return getInfo().existsInTarget(Target) &&
197 getInfo().spellingExistsInTarget(Target,
198 getAttributeSpellingListIndex());
201 bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
203 bool ParsedAttr::isSupportedByPragmaAttribute() const {
204 return getInfo().IsSupportedByPragmaAttribute;
207 bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
208 if (isRegularKeywordAttribute())
209 // The appurtenance rules are applied strictly for all regular keyword
210 // atributes.
211 return false;
213 assert(isStandardAttributeSyntax());
215 // We have historically allowed some type attributes with standard attribute
216 // syntax to slide to the decl-specifier-seq, so we have to keep supporting
217 // it. This property is consciously not defined as a flag in Attr.td because
218 // we don't want new attributes to specify it.
220 // Note: No new entries should be added to this list. Entries should be
221 // removed from this list after a suitable deprecation period, provided that
222 // there are no compatibility considerations with other compilers. If
223 // possible, we would like this list to go away entirely.
224 switch (getParsedKind()) {
225 case AT_AddressSpace:
226 case AT_OpenCLPrivateAddressSpace:
227 case AT_OpenCLGlobalAddressSpace:
228 case AT_OpenCLGlobalDeviceAddressSpace:
229 case AT_OpenCLGlobalHostAddressSpace:
230 case AT_OpenCLLocalAddressSpace:
231 case AT_OpenCLConstantAddressSpace:
232 case AT_OpenCLGenericAddressSpace:
233 case AT_NeonPolyVectorType:
234 case AT_NeonVectorType:
235 case AT_ArmMveStrictPolymorphism:
236 case AT_BTFTypeTag:
237 case AT_ObjCGC:
238 case AT_MatrixType:
239 return true;
240 default:
241 return false;
245 bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
247 unsigned ParsedAttr::getSemanticSpelling() const {
248 return getInfo().spellingIndexToSemanticSpelling(*this);
251 bool ParsedAttr::hasVariadicArg() const {
252 // If the attribute has the maximum number of optional arguments, we will
253 // claim that as being variadic. If we someday get an attribute that
254 // legitimately bumps up against that maximum, we can use another bit to track
255 // whether it's truly variadic or not.
256 return getInfo().OptArgs == 15;
259 bool ParsedAttr::isParamExpr(size_t N) const {
260 return getInfo().isParamExpr(N);
263 void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
264 ::handleAttrWithDelayedArgs(S, D, *this);
267 static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
268 // FIXME: Include the type in the argument list.
269 return AL.getNumArgs() + AL.hasParsedType();
272 template <typename Compare>
273 static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
274 unsigned Num, unsigned Diag,
275 Compare Comp) {
276 if (Comp(getNumAttributeArgs(AL), Num)) {
277 S.Diag(AL.getLoc(), Diag) << AL << Num;
278 return false;
280 return true;
283 bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
284 return checkAttributeNumArgsImpl(S, *this, Num,
285 diag::err_attribute_wrong_number_arguments,
286 std::not_equal_to<unsigned>());
288 bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
289 return checkAttributeNumArgsImpl(S, *this, Num,
290 diag::err_attribute_too_few_arguments,
291 std::less<unsigned>());
293 bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
294 return checkAttributeNumArgsImpl(S, *this, Num,
295 diag::err_attribute_too_many_arguments,
296 std::greater<unsigned>());
299 void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
300 ParsedAttributes &Second,
301 ParsedAttributes &Result) {
302 // Note that takeAllFrom() puts the attributes at the beginning of the list,
303 // so to obtain the correct ordering, we add `Second`, then `First`.
304 Result.takeAllFrom(Second);
305 Result.takeAllFrom(First);
306 if (First.Range.getBegin().isValid())
307 Result.Range.setBegin(First.Range.getBegin());
308 else
309 Result.Range.setBegin(Second.Range.getBegin());
310 if (Second.Range.getEnd().isValid())
311 Result.Range.setEnd(Second.Range.getEnd());
312 else
313 Result.Range.setEnd(First.Range.getEnd());