Coverage Report

Created: 2022-01-18 06:27

/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
27.8M
                                     IdentifierInfo *Ident) {
33
27.8M
  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
34
27.8M
  Result->Loc = Loc;
35
27.8M
  Result->Ident = Ident;
36
27.8M
  return Result;
37
27.8M
}
38
39
93.0M
size_t ParsedAttr::allocated_size() const {
40
93.0M
  if (IsAvailability) 
return AttributeFactory::AvailabilityAllocSize5.87M
;
41
87.1M
  else if (IsTypeTagForDatatype)
42
169
    return AttributeFactory::TypeTagForDatatypeAllocSize;
43
87.1M
  else if (IsProperty)
44
101
    return AttributeFactory::PropertyAllocSize;
45
87.1M
  else if (HasParsedType)
46
14.6k
    return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47
14.6k
                            detail::TypeTagForDatatypeData, ParsedType,
48
14.6k
                            detail::PropertyData>(0, 0, 0, 1, 0);
49
87.1M
  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
50
87.1M
                          detail::TypeTagForDatatypeData, ParsedType,
51
87.1M
                          detail::PropertyData>(NumArgs, 0, 0, 0, 0);
52
93.0M
}
53
54
151k
AttributeFactory::AttributeFactory() {
55
  // Go ahead and configure all the inline capacity.  This is just a memset.
56
151k
  FreeLists.resize(InlineFreeListsCapacity);
57
151k
}
58
151k
AttributeFactory::~AttributeFactory() = default;
59
60
186M
static size_t getFreeListIndexForSize(size_t size) {
61
186M
  assert(size >= sizeof(ParsedAttr));
62
0
  assert((size % sizeof(void*)) == 0);
63
0
  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
64
186M
}
65
66
93.0M
void *AttributeFactory::allocate(size_t size) {
67
  // Check for a previously reclaimed attribute.
68
93.0M
  size_t index = getFreeListIndexForSize(size);
69
93.0M
  if (index < FreeLists.size() && 
!FreeLists[index].empty()93.0M
) {
70
93.0M
    ParsedAttr *attr = FreeLists[index].back();
71
93.0M
    FreeLists[index].pop_back();
72
93.0M
    return attr;
73
93.0M
  }
74
75
  // Otherwise, allocate something new.
76
50.4k
  return Alloc.Allocate(size, alignof(AttributeFactory));
77
93.0M
}
78
79
93.0M
void AttributeFactory::deallocate(ParsedAttr *Attr) {
80
93.0M
  size_t size = Attr->allocated_size();
81
93.0M
  size_t freeListIndex = getFreeListIndexForSize(size);
82
83
  // Expand FreeLists to the appropriate size, if required.
84
93.0M
  if (freeListIndex >= FreeLists.size())
85
1
    FreeLists.resize(freeListIndex + 1);
86
87
93.0M
#ifndef NDEBUG
88
  // In debug mode, zero out the attribute to help find memory overwriting.
89
93.0M
  memset(Attr, 0, size);
90
93.0M
#endif
91
92
  // Add 'Attr' to the appropriate free-list.
93
93.0M
  FreeLists[freeListIndex].push_back(Attr);
94
93.0M
}
95
96
686M
void AttributeFactory::reclaimPool(AttributePool &cur) {
97
686M
  for (ParsedAttr *AL : cur.Attrs)
98
93.0M
    deallocate(AL);
99
686M
}
100
101
182M
void AttributePool::takePool(AttributePool &pool) {
102
182M
  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
103
182M
  pool.Attrs.clear();
104
182M
}
105
106
namespace {
107
108
#include "clang/Sema/AttrParsedAttrImpl.inc"
109
110
} // namespace
111
112
93.0M
const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113
  // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114
93.0M
  if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115
93.0M
    return *AttrInfoMap[A.getParsedKind()];
116
117
  // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118
324
  static const ParsedAttrInfo IgnoredParsedAttrInfo(
119
324
      AttributeCommonInfo::IgnoredAttribute);
120
324
  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
164
  static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
126
164
      PluginAttrInstances;
127
164
  if (PluginAttrInstances->empty())
128
164
    for (auto It : ParsedAttrInfoRegistry::entries())
129
0
      PluginAttrInstances->emplace_back(It.instantiate());
130
131
  // Search for a ParsedAttrInfo whose name and syntax match.
132
164
  std::string FullName = A.getNormalizedFullName();
133
164
  AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
134
164
  if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
135
0
    SyntaxUsed = AttributeCommonInfo::AS_Keyword;
136
137
164
  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
164
  static const ParsedAttrInfo DefaultParsedAttrInfo(
144
164
      AttributeCommonInfo::UnknownAttribute);
145
164
  return DefaultParsedAttrInfo;
146
164
}
147
148
12
ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
149
12
  return llvm::makeArrayRef(AttrInfoMap);
150
12
}
151
152
258M
unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
153
154
86.3M
unsigned ParsedAttr::getMaxArgs() const {
155
86.3M
  return getMinArgs() + getInfo().OptArgs;
156
86.3M
}
157
158
92.0M
bool ParsedAttr::hasCustomParsing() const {
159
92.0M
  return getInfo().HasCustomParsing;
160
92.0M
}
161
162
92.0M
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
163
92.0M
  return getInfo().diagAppertainsToDecl(S, *this, D);
164
92.0M
}
165
166
1.71k
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
167
1.71k
  return getInfo().diagAppertainsToStmt(S, *this, St);
168
1.71k
}
169
170
92.0M
bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
171
92.0M
  return getInfo().diagMutualExclusion(S, *this, D);
172
92.0M
}
173
174
bool ParsedAttr::appliesToDecl(const Decl *D,
175
598k
                               attr::SubjectMatchRule MatchRule) const {
176
598k
  return checkAttributeMatchRuleAppliesTo(D, MatchRule);
177
598k
}
178
179
void ParsedAttr::getMatchRules(
180
    const LangOptions &LangOpts,
181
    SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
182
1.09k
    const {
183
1.09k
  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
184
1.09k
}
185
186
92.0M
bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
187
92.0M
  if (getInfo().acceptsLangOpts(S.getLangOpts()))
188
92.0M
    return true;
189
34
  S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
190
34
  return false;
191
92.0M
}
192
193
0
bool ParsedAttr::isTargetSpecificAttr() const {
194
0
  return getInfo().IsTargetSpecific;
195
0
}
196
197
2.18M
bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
198
199
2.18M
bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
200
201
184M
bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
202
184M
  return getInfo().existsInTarget(Target);
203
184M
}
204
205
8.49k
bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
206
207
1.14k
bool ParsedAttr::isSupportedByPragmaAttribute() const {
208
1.14k
  return getInfo().IsSupportedByPragmaAttribute;
209
1.14k
}
210
211
8.58k
unsigned ParsedAttr::getSemanticSpelling() const {
212
8.58k
  return getInfo().spellingIndexToSemanticSpelling(*this);
213
8.58k
}
214
215
187k
bool ParsedAttr::hasVariadicArg() const {
216
  // If the attribute has the maximum number of optional arguments, we will
217
  // claim that as being variadic. If we someday get an attribute that
218
  // legitimately bumps up against that maximum, we can use another bit to track
219
  // whether it's truly variadic or not.
220
187k
  return getInfo().OptArgs == 15;
221
187k
}
222
223
92.0M
static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
224
  // FIXME: Include the type in the argument list.
225
92.0M
  return AL.getNumArgs() + AL.hasParsedType();
226
92.0M
}
227
228
template <typename Compare>
229
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
230
                                      unsigned Num, unsigned Diag,
231
92.0M
                                      Compare Comp) {
232
92.0M
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
379
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
379
    return false;
235
379
  }
236
92.0M
  return true;
237
92.0M
}
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
231
91.9M
                                      Compare Comp) {
232
91.9M
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
284
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
284
    return false;
235
284
  }
236
91.9M
  return true;
237
91.9M
}
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
231
19.1k
                                      Compare Comp) {
232
19.1k
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
72
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
72
    return false;
235
72
  }
236
19.1k
  return true;
237
19.1k
}
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
231
111k
                                      Compare Comp) {
232
111k
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
23
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
23
    return false;
235
23
  }
236
111k
  return true;
237
111k
}
238
239
91.9M
bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
240
91.9M
  return checkAttributeNumArgsImpl(S, *this, Num,
241
91.9M
                                   diag::err_attribute_wrong_number_arguments,
242
91.9M
                                   std::not_equal_to<unsigned>());
243
91.9M
}
244
19.1k
bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
245
19.1k
  return checkAttributeNumArgsImpl(S, *this, Num,
246
19.1k
                                   diag::err_attribute_too_few_arguments,
247
19.1k
                                   std::less<unsigned>());
248
19.1k
}
249
111k
bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
250
111k
  return checkAttributeNumArgsImpl(S, *this, Num,
251
111k
                                   diag::err_attribute_too_many_arguments,
252
111k
                                   std::greater<unsigned>());
253
111k
}