Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Sema/ParsedAttr.cpp
Line
Count
Source (jump to first uncovered line)
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
10
//
11
//===----------------------------------------------------------------------===//
12
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 "llvm/Support/ManagedStatic.h"
23
#include <cassert>
24
#include <cstddef>
25
#include <utility>
26
27
using namespace clang;
28
29
LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
30
31
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
32
24.4M
                                     IdentifierInfo *Ident) {
33
24.4M
  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
34
24.4M
  Result->Loc = Loc;
35
24.4M
  Result->Ident = Ident;
36
24.4M
  return Result;
37
24.4M
}
38
39
82.6M
size_t ParsedAttr::allocated_size() const {
40
82.6M
  if (IsAvailability) 
return AttributeFactory::AvailabilityAllocSize5.96M
;
41
76.6M
  else if (IsTypeTagForDatatype)
42
169
    return AttributeFactory::TypeTagForDatatypeAllocSize;
43
76.6M
  else if (IsProperty)
44
101
    return AttributeFactory::PropertyAllocSize;
45
76.6M
  else if (HasParsedType)
46
15.5k
    return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47
15.5k
                            detail::TypeTagForDatatypeData, ParsedType,
48
15.5k
                            detail::PropertyData>(0, 0, 0, 1, 0);
49
76.6M
  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
50
76.6M
                          detail::TypeTagForDatatypeData, ParsedType,
51
76.6M
                          detail::PropertyData>(NumArgs, 0, 0, 0, 0);
52
82.6M
}
53
54
152k
AttributeFactory::AttributeFactory() {
55
  // Go ahead and configure all the inline capacity.  This is just a memset.
56
152k
  FreeLists.resize(InlineFreeListsCapacity);
57
152k
}
58
152k
AttributeFactory::~AttributeFactory() = default;
59
60
165M
static size_t getFreeListIndexForSize(size_t size) {
61
165M
  assert(size >= sizeof(ParsedAttr));
62
0
  assert((size % sizeof(void*)) == 0);
63
0
  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
64
165M
}
65
66
82.6M
void *AttributeFactory::allocate(size_t size) {
67
  // Check for a previously reclaimed attribute.
68
82.6M
  size_t index = getFreeListIndexForSize(size);
69
82.6M
  if (index < FreeLists.size() && 
!FreeLists[index].empty()82.6M
) {
70
82.5M
    ParsedAttr *attr = FreeLists[index].back();
71
82.5M
    FreeLists[index].pop_back();
72
82.5M
    return attr;
73
82.5M
  }
74
75
  // Otherwise, allocate something new.
76
51.6k
  return Alloc.Allocate(size, alignof(AttributeFactory));
77
82.6M
}
78
79
82.6M
void AttributeFactory::deallocate(ParsedAttr *Attr) {
80
82.6M
  size_t size = Attr->allocated_size();
81
82.6M
  size_t freeListIndex = getFreeListIndexForSize(size);
82
83
  // Expand FreeLists to the appropriate size, if required.
84
82.6M
  if (freeListIndex >= FreeLists.size())
85
1
    FreeLists.resize(freeListIndex + 1);
86
87
82.6M
#ifndef NDEBUG
88
  // In debug mode, zero out the attribute to help find memory overwriting.
89
82.6M
  memset(Attr, 0, size);
90
82.6M
#endif
91
92
  // Add 'Attr' to the appropriate free-list.
93
82.6M
  FreeLists[freeListIndex].push_back(Attr);
94
82.6M
}
95
96
793M
void AttributeFactory::reclaimPool(AttributePool &cur) {
97
793M
  for (ParsedAttr *AL : cur.Attrs)
98
82.6M
    deallocate(AL);
99
793M
}
100
101
158M
void AttributePool::takePool(AttributePool &pool) {
102
158M
  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
103
158M
  pool.Attrs.clear();
104
158M
}
105
106
namespace {
107
108
#include "clang/Sema/AttrParsedAttrImpl.inc"
109
110
} // namespace
111
112
82.6M
const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113
  // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114
82.6M
  if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115
82.6M
    return *AttrInfoMap[A.getParsedKind()];
116
117
  // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118
367
  static const ParsedAttrInfo IgnoredParsedAttrInfo(
119
367
      AttributeCommonInfo::IgnoredAttribute);
120
367
  if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
121
160
    return IgnoredParsedAttrInfo;
122
123
  // Otherwise this may be an attribute defined by a plugin. First instantiate
124
  // all plugin attributes if we haven't already done so.
125
207
  static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
126
207
      PluginAttrInstances;
127
207
  if (PluginAttrInstances->empty())
128
207
    for (auto It : ParsedAttrInfoRegistry::entries())
129
0
      PluginAttrInstances->emplace_back(It.instantiate());
130
131
  // Search for a ParsedAttrInfo whose name and syntax match.
132
207
  std::string FullName = A.getNormalizedFullName();
133
207
  AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
134
207
  if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
135
0
    SyntaxUsed = AttributeCommonInfo::AS_Keyword;
136
137
207
  for (auto &Ptr : *PluginAttrInstances)
138
0
    for (auto &S : Ptr->Spellings)
139
0
      if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
140
0
        return *Ptr;
141
142
  // If we failed to find a match then return a default ParsedAttrInfo.
143
207
  static const ParsedAttrInfo DefaultParsedAttrInfo(
144
207
      AttributeCommonInfo::UnknownAttribute);
145
207
  return DefaultParsedAttrInfo;
146
207
}
147
148
12
ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
149
12
  return llvm::makeArrayRef(AttrInfoMap);
150
12
}
151
152
227M
unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
153
154
75.8M
unsigned ParsedAttr::getMaxArgs() const {
155
75.8M
  return getMinArgs() + getInfo().OptArgs;
156
75.8M
}
157
158
448
unsigned ParsedAttr::getNumArgMembers() const {
159
448
  return getInfo().NumArgMembers;
160
448
}
161
162
81.6M
bool ParsedAttr::hasCustomParsing() const {
163
81.6M
  return getInfo().HasCustomParsing;
164
81.6M
}
165
166
81.6M
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
167
81.6M
  return getInfo().diagAppertainsToDecl(S, *this, D);
168
81.6M
}
169
170
1.84k
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
171
1.84k
  return getInfo().diagAppertainsToStmt(S, *this, St);
172
1.84k
}
173
174
81.6M
bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
175
81.6M
  return getInfo().diagMutualExclusion(S, *this, D);
176
81.6M
}
177
178
bool ParsedAttr::appliesToDecl(const Decl *D,
179
598k
                               attr::SubjectMatchRule MatchRule) const {
180
598k
  return checkAttributeMatchRuleAppliesTo(D, MatchRule);
181
598k
}
182
183
void ParsedAttr::getMatchRules(
184
    const LangOptions &LangOpts,
185
    SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
186
1.10k
    const {
187
1.10k
  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
188
1.10k
}
189
190
81.6M
bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
191
81.6M
  if (getInfo().acceptsLangOpts(S.getLangOpts()))
192
81.6M
    return true;
193
35
  S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
194
35
  return false;
195
81.6M
}
196
197
0
bool ParsedAttr::isTargetSpecificAttr() const {
198
0
  return getInfo().IsTargetSpecific;
199
0
}
200
201
4.45M
bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
202
203
2.22M
bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
204
205
163M
bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
206
163M
  return getInfo().existsInTarget(Target);
207
163M
}
208
209
9.17k
bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
210
211
1.16k
bool ParsedAttr::isSupportedByPragmaAttribute() const {
212
1.16k
  return getInfo().IsSupportedByPragmaAttribute;
213
1.16k
}
214
215
49.5k
bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
216
49.5k
  assert(isStandardAttributeSyntax());
217
218
  // We have historically allowed some type attributes with standard attribute
219
  // syntax to slide to the decl-specifier-seq, so we have to keep supporting
220
  // it. This property is consciously not defined as a flag in Attr.td because
221
  // we don't want new attributes to specify it.
222
  //
223
  // Note: No new entries should be added to this list. Entries should be
224
  // removed from this list after a suitable deprecation period, provided that
225
  // there are no compatibility considerations with other compilers. If
226
  // possible, we would like this list to go away entirely.
227
0
  switch (getParsedKind()) {
228
44
  case AT_AddressSpace:
229
50
  case AT_OpenCLPrivateAddressSpace:
230
56
  case AT_OpenCLGlobalAddressSpace:
231
62
  case AT_OpenCLGlobalDeviceAddressSpace:
232
68
  case AT_OpenCLGlobalHostAddressSpace:
233
74
  case AT_OpenCLLocalAddressSpace:
234
80
  case AT_OpenCLConstantAddressSpace:
235
86
  case AT_OpenCLGenericAddressSpace:
236
86
  case AT_NeonPolyVectorType:
237
86
  case AT_NeonVectorType:
238
86
  case AT_ArmMveStrictPolymorphism:
239
86
  case AT_BTFTypeTag:
240
90
  case AT_ObjCGC:
241
99
  case AT_MatrixType:
242
99
    return true;
243
49.4k
  default:
244
49.4k
    return false;
245
49.5k
  }
246
49.5k
}
247
248
81.6M
bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
249
250
8.21k
unsigned ParsedAttr::getSemanticSpelling() const {
251
8.21k
  return getInfo().spellingIndexToSemanticSpelling(*this);
252
8.21k
}
253
254
1.17M
bool ParsedAttr::hasVariadicArg() const {
255
  // If the attribute has the maximum number of optional arguments, we will
256
  // claim that as being variadic. If we someday get an attribute that
257
  // legitimately bumps up against that maximum, we can use another bit to track
258
  // whether it's truly variadic or not.
259
1.17M
  return getInfo().OptArgs == 15;
260
1.17M
}
261
262
422
bool ParsedAttr::isParamExpr(size_t N) const {
263
422
  return getInfo().isParamExpr(N);
264
422
}
265
266
6
void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
267
6
  ::handleAttrWithDelayedArgs(S, D, *this);
268
6
}
269
270
81.6M
static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
271
  // FIXME: Include the type in the argument list.
272
81.6M
  return AL.getNumArgs() + AL.hasParsedType();
273
81.6M
}
274
275
template <typename Compare>
276
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
277
                                      unsigned Num, unsigned Diag,
278
81.6M
                                      Compare Comp) {
279
81.6M
  if (Comp(getNumAttributeArgs(AL), Num)) {
280
400
    S.Diag(AL.getLoc(), Diag) << AL << Num;
281
400
    return false;
282
400
  }
283
81.6M
  return true;
284
81.6M
}
ParsedAttr.cpp:bool checkAttributeNumArgsImpl<std::__1::not_equal_to<unsigned int> >(clang::Sema&, clang::ParsedAttr const&, unsigned int, unsigned int, std::__1::not_equal_to<unsigned int>)
Line
Count
Source
278
80.5M
                                      Compare Comp) {
279
80.5M
  if (Comp(getNumAttributeArgs(AL), Num)) {
280
301
    S.Diag(AL.getLoc(), Diag) << AL << Num;
281
301
    return false;
282
301
  }
283
80.5M
  return true;
284
80.5M
}
ParsedAttr.cpp:bool checkAttributeNumArgsImpl<std::__1::less<unsigned int> >(clang::Sema&, clang::ParsedAttr const&, unsigned int, unsigned int, std::__1::less<unsigned int>)
Line
Count
Source
278
1.00M
                                      Compare Comp) {
279
1.00M
  if (Comp(getNumAttributeArgs(AL), Num)) {
280
76
    S.Diag(AL.getLoc(), Diag) << AL << Num;
281
76
    return false;
282
76
  }
283
1.00M
  return true;
284
1.00M
}
ParsedAttr.cpp:bool checkAttributeNumArgsImpl<std::__1::greater<unsigned int> >(clang::Sema&, clang::ParsedAttr const&, unsigned int, unsigned int, std::__1::greater<unsigned int>)
Line
Count
Source
278
116k
                                      Compare Comp) {
279
116k
  if (Comp(getNumAttributeArgs(AL), Num)) {
280
23
    S.Diag(AL.getLoc(), Diag) << AL << Num;
281
23
    return false;
282
23
  }
283
116k
  return true;
284
116k
}
285
286
80.5M
bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
287
80.5M
  return checkAttributeNumArgsImpl(S, *this, Num,
288
80.5M
                                   diag::err_attribute_wrong_number_arguments,
289
80.5M
                                   std::not_equal_to<unsigned>());
290
80.5M
}
291
1.00M
bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
292
1.00M
  return checkAttributeNumArgsImpl(S, *this, Num,
293
1.00M
                                   diag::err_attribute_too_few_arguments,
294
1.00M
                                   std::less<unsigned>());
295
1.00M
}
296
116k
bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
297
116k
  return checkAttributeNumArgsImpl(S, *this, Num,
298
116k
                                   diag::err_attribute_too_many_arguments,
299
116k
                                   std::greater<unsigned>());
300
116k
}
301
302
void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
303
                                    ParsedAttributes &Second,
304
9.30M
                                    ParsedAttributes &Result) {
305
  // Note that takeAllFrom() puts the attributes at the beginning of the list,
306
  // so to obtain the correct ordering, we add `Second`, then `First`.
307
9.30M
  Result.takeAllFrom(Second);
308
9.30M
  Result.takeAllFrom(First);
309
9.30M
  if (First.Range.getBegin().isValid())
310
2.31k
    Result.Range.setBegin(First.Range.getBegin());
311
9.30M
  else
312
9.30M
    Result.Range.setBegin(Second.Range.getBegin());
313
9.30M
  if (Second.Range.getEnd().isValid())
314
2.60k
    Result.Range.setEnd(Second.Range.getEnd());
315
9.30M
  else
316
9.30M
    Result.Range.setEnd(First.Range.getEnd());
317
9.30M
}