Coverage Report

Created: 2021-09-21 08:58

/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
31.8M
                                     IdentifierInfo *Ident) {
33
31.8M
  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
34
31.8M
  Result->Loc = Loc;
35
31.8M
  Result->Ident = Ident;
36
31.8M
  return Result;
37
31.8M
}
38
39
108M
size_t ParsedAttr::allocated_size() const {
40
108M
  if (IsAvailability) 
return AttributeFactory::AvailabilityAllocSize5.85M
;
41
103M
  else if (IsTypeTagForDatatype)
42
168
    return AttributeFactory::TypeTagForDatatypeAllocSize;
43
103M
  else if (IsProperty)
44
125
    return AttributeFactory::PropertyAllocSize;
45
103M
  else if (HasParsedType)
46
14.4k
    return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47
14.4k
                            detail::TypeTagForDatatypeData, ParsedType,
48
14.4k
                            detail::PropertyData>(0, 0, 0, 1, 0);
49
103M
  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
50
103M
                          detail::TypeTagForDatatypeData, ParsedType,
51
103M
                          detail::PropertyData>(NumArgs, 0, 0, 0, 0);
52
108M
}
53
54
161k
AttributeFactory::AttributeFactory() {
55
  // Go ahead and configure all the inline capacity.  This is just a memset.
56
161k
  FreeLists.resize(InlineFreeListsCapacity);
57
161k
}
58
161k
AttributeFactory::~AttributeFactory() = default;
59
60
217M
static size_t getFreeListIndexForSize(size_t size) {
61
217M
  assert(size >= sizeof(ParsedAttr));
62
0
  assert((size % sizeof(void*)) == 0);
63
0
  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
64
217M
}
65
66
108M
void *AttributeFactory::allocate(size_t size) {
67
  // Check for a previously reclaimed attribute.
68
108M
  size_t index = getFreeListIndexForSize(size);
69
108M
  if (index < FreeLists.size() && 
!FreeLists[index].empty()108M
) {
70
108M
    ParsedAttr *attr = FreeLists[index].back();
71
108M
    FreeLists[index].pop_back();
72
108M
    return attr;
73
108M
  }
74
75
  // Otherwise, allocate something new.
76
52.5k
  return Alloc.Allocate(size, alignof(AttributeFactory));
77
108M
}
78
79
108M
void AttributeFactory::deallocate(ParsedAttr *Attr) {
80
108M
  size_t size = Attr->allocated_size();
81
108M
  size_t freeListIndex = getFreeListIndexForSize(size);
82
83
  // Expand FreeLists to the appropriate size, if required.
84
108M
  if (freeListIndex >= FreeLists.size())
85
1
    FreeLists.resize(freeListIndex + 1);
86
87
108M
#ifndef NDEBUG
88
  // In debug mode, zero out the attribute to help find memory overwriting.
89
108M
  memset(Attr, 0, size);
90
108M
#endif
91
92
  // Add 'Attr' to the appropriate free-list.
93
108M
  FreeLists[freeListIndex].push_back(Attr);
94
108M
}
95
96
791M
void AttributeFactory::reclaimPool(AttributePool &cur) {
97
791M
  for (ParsedAttr *AL : cur.Attrs)
98
108M
    deallocate(AL);
99
791M
}
100
101
213M
void AttributePool::takePool(AttributePool &pool) {
102
213M
  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
103
213M
  pool.Attrs.clear();
104
213M
}
105
106
namespace {
107
108
#include "clang/Sema/AttrParsedAttrImpl.inc"
109
110
} // namespace
111
112
108M
const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113
  // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114
108M
  if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115
108M
    return *AttrInfoMap[A.getParsedKind()];
116
117
  // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118
348
  static const ParsedAttrInfo IgnoredParsedAttrInfo(
119
348
      AttributeCommonInfo::IgnoredAttribute);
120
348
  if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
121
184
    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
306M
unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
153
154
102M
unsigned ParsedAttr::getMaxArgs() const {
155
102M
  return getMinArgs() + getInfo().OptArgs;
156
102M
}
157
158
108M
bool ParsedAttr::hasCustomParsing() const {
159
108M
  return getInfo().HasCustomParsing;
160
108M
}
161
162
108M
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
163
108M
  return getInfo().diagAppertainsToDecl(S, *this, D);
164
108M
}
165
166
1.69k
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
167
1.69k
  return getInfo().diagAppertainsToStmt(S, *this, St);
168
1.69k
}
169
170
108M
bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
171
108M
  return getInfo().diagMutualExclusion(S, *this, D);
172
108M
}
173
174
bool ParsedAttr::appliesToDecl(const Decl *D,
175
747k
                               attr::SubjectMatchRule MatchRule) const {
176
747k
  return checkAttributeMatchRuleAppliesTo(D, MatchRule);
177
747k
}
178
179
void ParsedAttr::getMatchRules(
180
    const LangOptions &LangOpts,
181
    SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
182
1.31k
    const {
183
1.31k
  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
184
1.31k
}
185
186
108M
bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
187
108M
  if (getInfo().acceptsLangOpts(S.getLangOpts()))
188
108M
    return true;
189
34
  S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
190
34
  return false;
191
108M
}
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
216M
bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
202
216M
  return getInfo().existsInTarget(Target);
203
216M
}
204
205
9.70k
bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
206
207
1.36k
bool ParsedAttr::isSupportedByPragmaAttribute() const {
208
1.36k
  return getInfo().IsSupportedByPragmaAttribute;
209
1.36k
}
210
211
8.29k
unsigned ParsedAttr::getSemanticSpelling() const {
212
8.29k
  return getInfo().spellingIndexToSemanticSpelling(*this);
213
8.29k
}
214
215
189k
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
189k
  return getInfo().OptArgs == 15;
221
189k
}
222
223
108M
static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
224
  // FIXME: Include the type in the argument list.
225
108M
  return AL.getNumArgs() + AL.hasParsedType();
226
108M
}
227
228
template <typename Compare>
229
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
230
                                      unsigned Num, unsigned Diag,
231
108M
                                      Compare Comp) {
232
108M
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
376
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
376
    return false;
235
376
  }
236
108M
  return true;
237
108M
}
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
107M
                                      Compare Comp) {
232
107M
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
284
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
284
    return false;
235
284
  }
236
107M
  return true;
237
107M
}
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.2k
                                      Compare Comp) {
232
19.2k
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
70
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
70
    return false;
235
70
  }
236
19.1k
  return true;
237
19.2k
}
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
113k
                                      Compare Comp) {
232
113k
  if (Comp(getNumAttributeArgs(AL), Num)) {
233
22
    S.Diag(AL.getLoc(), Diag) << AL << Num;
234
22
    return false;
235
22
  }
236
113k
  return true;
237
113k
}
238
239
107M
bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
240
107M
  return checkAttributeNumArgsImpl(S, *this, Num,
241
107M
                                   diag::err_attribute_wrong_number_arguments,
242
107M
                                   std::not_equal_to<unsigned>());
243
107M
}
244
19.2k
bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
245
19.2k
  return checkAttributeNumArgsImpl(S, *this, Num,
246
19.2k
                                   diag::err_attribute_too_few_arguments,
247
19.2k
                                   std::less<unsigned>());
248
19.2k
}
249
113k
bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
250
113k
  return checkAttributeNumArgsImpl(S, *this, Num,
251
113k
                                   diag::err_attribute_too_many_arguments,
252
113k
                                   std::greater<unsigned>());
253
113k
}