Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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 <cassert>
23
#include <cstddef>
24
#include <utility>
25
26
using namespace clang;
27
28
IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
29
772k
                                     IdentifierInfo *Ident) {
30
772k
  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
31
772k
  Result->Loc = Loc;
32
772k
  Result->Ident = Ident;
33
772k
  return Result;
34
772k
}
35
36
8.07M
size_t ParsedAttr::allocated_size() const {
37
8.07M
  if (IsAvailability) 
return AttributeFactory::AvailabilityAllocSize709k
;
38
7.36M
  else if (IsTypeTagForDatatype)
39
167
    return AttributeFactory::TypeTagForDatatypeAllocSize;
40
7.36M
  else if (IsProperty)
41
101
    return AttributeFactory::PropertyAllocSize;
42
7.36M
  else if (HasParsedType)
43
36
    return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
44
36
                            detail::TypeTagForDatatypeData, ParsedType,
45
36
                            detail::PropertyData>(0, 0, 0, 1, 0);
46
7.36M
  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47
7.36M
                          detail::TypeTagForDatatypeData, ParsedType,
48
7.36M
                          detail::PropertyData>(NumArgs, 0, 0, 0, 0);
49
7.36M
}
50
51
49.6k
AttributeFactory::AttributeFactory() {
52
49.6k
  // Go ahead and configure all the inline capacity.  This is just a memset.
53
49.6k
  FreeLists.resize(InlineFreeListsCapacity);
54
49.6k
}
55
49.6k
AttributeFactory::~AttributeFactory() = default;
56
57
16.1M
static size_t getFreeListIndexForSize(size_t size) {
58
16.1M
  assert(size >= sizeof(ParsedAttr));
59
16.1M
  assert((size % sizeof(void*)) == 0);
60
16.1M
  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
61
16.1M
}
62
63
8.07M
void *AttributeFactory::allocate(size_t size) {
64
8.07M
  // Check for a previously reclaimed attribute.
65
8.07M
  size_t index = getFreeListIndexForSize(size);
66
8.07M
  if (index < FreeLists.size() && 
!FreeLists[index].empty()8.07M
) {
67
8.02M
    ParsedAttr *attr = FreeLists[index].back();
68
8.02M
    FreeLists[index].pop_back();
69
8.02M
    return attr;
70
8.02M
  }
71
49.1k
72
49.1k
  // Otherwise, allocate something new.
73
49.1k
  return Alloc.Allocate(size, alignof(AttributeFactory));
74
49.1k
}
75
76
8.07M
void AttributeFactory::deallocate(ParsedAttr *Attr) {
77
8.07M
  size_t size = Attr->allocated_size();
78
8.07M
  size_t freeListIndex = getFreeListIndexForSize(size);
79
8.07M
80
8.07M
  // Expand FreeLists to the appropriate size, if required.
81
8.07M
  if (freeListIndex >= FreeLists.size())
82
1
    FreeLists.resize(freeListIndex + 1);
83
8.07M
84
#ifndef NDEBUG
85
  // In debug mode, zero out the attribute to help find memory overwriting.
86
  memset(Attr, 0, size);
87
#endif
88
89
8.07M
  // Add 'Attr' to the appropriate free-list.
90
8.07M
  FreeLists[freeListIndex].push_back(Attr);
91
8.07M
}
92
93
187M
void AttributeFactory::reclaimPool(AttributePool &cur) {
94
187M
  for (ParsedAttr *AL : cur.Attrs)
95
8.07M
    deallocate(AL);
96
187M
}
97
98
36.8M
void AttributePool::takePool(AttributePool &pool) {
99
36.8M
  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100
36.8M
  pool.Attrs.clear();
101
36.8M
}
102
103
#include "clang/Sema/AttrParsedAttrKinds.inc"
104
105
static StringRef normalizeAttrScopeName(StringRef ScopeName,
106
4.32k
                                        ParsedAttr::Syntax SyntaxUsed) {
107
4.32k
  // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
108
4.32k
  // to be "clang".
109
4.32k
  if (SyntaxUsed == ParsedAttr::AS_CXX11 ||
110
4.32k
    
SyntaxUsed == ParsedAttr::AS_C2x169
) {
111
4.32k
    if (ScopeName == "__gnu__")
112
6
      ScopeName = "gnu";
113
4.31k
    else if (ScopeName == "_Clang")
114
41
      ScopeName = "clang";
115
4.32k
  }
116
4.32k
  return ScopeName;
117
4.32k
}
118
119
static StringRef normalizeAttrName(StringRef AttrName,
120
                                   StringRef NormalizedScopeName,
121
20.0M
                                   ParsedAttr::Syntax SyntaxUsed) {
122
20.0M
  // Normalize the attribute name, __foo__ becomes foo. This is only allowable
123
20.0M
  // for GNU attributes, and attributes using the double square bracket syntax.
124
20.0M
  bool ShouldNormalize =
125
20.0M
      SyntaxUsed == ParsedAttr::AS_GNU ||
126
20.0M
      
(630k
(630k
SyntaxUsed == ParsedAttr::AS_CXX11630k
||
127
630k
        
SyntaxUsed == ParsedAttr::AS_C2x601k
) &&
128
630k
       
(28.8k
NormalizedScopeName == "gnu"28.8k
||
NormalizedScopeName == "clang"28.4k
));
129
20.0M
  if (ShouldNormalize && 
AttrName.size() >= 419.3M
&&
AttrName.startswith("__")19.3M
&&
130
20.0M
      
AttrName.endswith("__")15.3M
)
131
15.3M
    AttrName = AttrName.slice(2, AttrName.size() - 2);
132
20.0M
133
20.0M
  return AttrName;
134
20.0M
}
135
136
ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
137
                                     const IdentifierInfo *ScopeName,
138
11.8M
                                     Syntax SyntaxUsed) {
139
11.8M
  StringRef AttrName = Name->getName();
140
11.8M
141
11.8M
  SmallString<64> FullName;
142
11.8M
  if (ScopeName)
143
3.07k
    FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
144
11.8M
145
11.8M
  AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
146
11.8M
147
11.8M
  // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
148
11.8M
  // unscoped.
149
11.8M
  if (ScopeName || 
SyntaxUsed == AS_CXX1111.8M
||
SyntaxUsed == AS_C2x11.8M
)
150
19.5k
    FullName += "::";
151
11.8M
  FullName += AttrName;
152
11.8M
153
11.8M
  return ::getAttrKind(FullName, SyntaxUsed);
154
11.8M
}
155
156
8.11M
unsigned ParsedAttr::getAttributeSpellingListIndex() const {
157
8.11M
  // Both variables will be used in tablegen generated
158
8.11M
  // attribute spell list index matching code.
159
8.11M
  auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
160
8.11M
  StringRef Scope =
161
8.11M
      ScopeName ? 
normalizeAttrScopeName(ScopeName->getName(), Syntax)1.25k
:
""8.11M
;
162
8.11M
  StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
163
8.11M
164
8.11M
#include "clang/Sema/AttrSpellingListIndex.inc"
165
55.7k
166
55.7k
}
167
168
struct ParsedAttrInfo {
169
  unsigned NumArgs : 4;
170
  unsigned OptArgs : 4;
171
  unsigned HasCustomParsing : 1;
172
  unsigned IsTargetSpecific : 1;
173
  unsigned IsType : 1;
174
  unsigned IsStmt : 1;
175
  unsigned IsKnownToGCC : 1;
176
  unsigned IsSupportedByPragmaAttribute : 1;
177
178
  bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
179
  bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
180
  bool (*ExistsInTarget)(const TargetInfo &Target);
181
  unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
182
  void (*GetPragmaAttributeMatchRules)(
183
      llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
184
      const LangOptions &LangOpts);
185
};
186
187
namespace {
188
189
#include "clang/Sema/AttrParsedAttrImpl.inc"
190
191
} // namespace
192
193
69.8M
static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
194
69.8M
  return AttrInfoMap[A.getKind()];
195
69.8M
}
196
197
22.1M
unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
198
199
7.48M
unsigned ParsedAttr::getMaxArgs() const {
200
7.48M
  return getMinArgs() + getInfo(*this).OptArgs;
201
7.48M
}
202
203
8.14M
bool ParsedAttr::hasCustomParsing() const {
204
8.14M
  return getInfo(*this).HasCustomParsing;
205
8.14M
}
206
207
8.14M
bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
208
8.14M
  return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
209
8.14M
}
210
211
bool ParsedAttr::appliesToDecl(const Decl *D,
212
582k
                               attr::SubjectMatchRule MatchRule) const {
213
582k
  return checkAttributeMatchRuleAppliesTo(D, MatchRule);
214
582k
}
215
216
void ParsedAttr::getMatchRules(
217
    const LangOptions &LangOpts,
218
    SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
219
681
    const {
220
681
  return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
221
681
}
222
223
8.14M
bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
224
8.14M
  return getInfo(*this).DiagLangOpts(S, *this);
225
8.14M
}
226
227
0
bool ParsedAttr::isTargetSpecificAttr() const {
228
0
  return getInfo(*this).IsTargetSpecific;
229
0
}
230
231
151
bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
232
233
243k
bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
234
235
15.4M
bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
236
15.4M
  return getInfo(*this).ExistsInTarget(Target);
237
15.4M
}
238
239
4.37k
bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
240
241
733
bool ParsedAttr::isSupportedByPragmaAttribute() const {
242
733
  return getInfo(*this).IsSupportedByPragmaAttribute;
243
733
}
244
245
7.87k
unsigned ParsedAttr::getSemanticSpelling() const {
246
7.87k
  return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
247
7.87k
}
248
249
95.3k
bool ParsedAttr::hasVariadicArg() const {
250
95.3k
  // If the attribute has the maximum number of optional arguments, we will
251
95.3k
  // claim that as being variadic. If we someday get an attribute that
252
95.3k
  // legitimately bumps up against that maximum, we can use another bit to track
253
95.3k
  // whether it's truly variadic or not.
254
95.3k
  return getInfo(*this).OptArgs == 15;
255
95.3k
}