Clang Project

clang_source_code/lib/Sema/ParsedAttr.cpp
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
26using namespace clang;
27
28IdentifierLoc *IdentifierLoc::create(ASTContext &CtxSourceLocation Loc,
29                                     IdentifierInfo *Ident) {
30  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
31  Result->Loc = Loc;
32  Result->Ident = Ident;
33  return Result;
34}
35
36size_t ParsedAttr::allocated_size() const {
37  if (IsAvailabilityreturn 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>(00010);
46  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47                          detail::TypeTagForDatatypeData, ParsedType,
48                          detail::PropertyData>(NumArgs, 0000);
49}
50
51AttributeFactory::AttributeFactory() {
52  // Go ahead and configure all the inline capacity.  This is just a memset.
53  FreeLists.resize(InlineFreeListsCapacity);
54}
55AttributeFactory::~AttributeFactory() = default;
56
57static size_t getFreeListIndexForSize(size_t size) {
58  = sizeof(ParsedAttr)", "/home/seafit/code_projects/clang_source/clang/lib/Sema/ParsedAttr.cpp", 58, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(size >= sizeof(ParsedAttr));
59  assert((size % sizeof(void*)) == 0);
60  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
61}
62
63void *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;
70  }
71
72  // Otherwise, allocate something new.
73  return Alloc.Allocate(size, alignof(AttributeFactory));
74}
75
76void AttributeFactory::deallocate(ParsedAttr *Attr) {
77  size_t size = Attr->allocated_size();
78  size_t freeListIndex = getFreeListIndexForSize(size);
79
80  // Expand FreeLists to the appropriate size, if required.
81  if (freeListIndex >= FreeLists.size())
82    FreeLists.resize(freeListIndex + 1);
83
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  // Add 'Attr' to the appropriate free-list.
90  FreeLists[freeListIndex].push_back(Attr);
91}
92
93void AttributeFactory::reclaimPool(AttributePool &cur) {
94  for (ParsedAttr *AL : cur.Attrs)
95    deallocate(AL);
96}
97
98void AttributePool::takePool(AttributePool &pool) {
99  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100  pool.Attrs.clear();
101}
102
103#include "clang/Sema/AttrParsedAttrKinds.inc"
104
105static StringRef normalizeAttrScopeName(StringRef ScopeName,
106                                        ParsedAttr::Syntax SyntaxUsed) {
107  // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
108  // to be "clang".
109  if (SyntaxUsed == ParsedAttr::AS_CXX11 ||
110    SyntaxUsed == ParsedAttr::AS_C2x) {
111    if (ScopeName == "__gnu__")
112      ScopeName = "gnu";
113    else if (ScopeName == "_Clang")
114      ScopeName = "clang";
115  }
116  return ScopeName;
117}
118
119static StringRef normalizeAttrName(StringRef AttrName,
120                                   StringRef NormalizedScopeName,
121                                   ParsedAttr::Syntax SyntaxUsed) {
122  // Normalize the attribute name, __foo__ becomes foo. This is only allowable
123  // for GNU attributes, and attributes using the double square bracket syntax.
124  bool ShouldNormalize =
125      SyntaxUsed == ParsedAttr::AS_GNU ||
126      ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
127        SyntaxUsed == ParsedAttr::AS_C2x) &&
128       (NormalizedScopeName == "gnu" || NormalizedScopeName == "clang"));
129  if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
130      AttrName.endswith("__"))
131    AttrName = AttrName.slice(2, AttrName.size() - 2);
132
133  return AttrName;
134}
135
136ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
137                                     const IdentifierInfo *ScopeName,
138                                     Syntax SyntaxUsed) {
139  StringRef AttrName = Name->getName();
140
141  SmallString<64FullName;
142  if (ScopeName)
143    FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
144
145  AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
146
147  // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
148  // unscoped.
149  if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
150    FullName += "::";
151  FullName += AttrName;
152
153  return ::getAttrKind(FullName, SyntaxUsed);
154}
155
156unsigned ParsedAttr::getAttributeSpellingListIndex() const {
157  // Both variables will be used in tablegen generated
158  // attribute spell list index matching code.
159  auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
160  StringRef Scope =
161      ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
162  StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
163
164#include "clang/Sema/AttrSpellingListIndex.inc"
165
166}
167
168struct 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 &Sconst ParsedAttr &Attrconst Decl *);
179  bool (*DiagLangOpts)(Sema &Sconst ParsedAttr &Attr);
180  bool (*ExistsInTarget)(const TargetInfo &Target);
181  unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
182  void (*GetPragmaAttributeMatchRules)(
183      llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRulebool>> &Rules,
184      const LangOptions &LangOpts);
185};
186
187namespace {
188
189#include "clang/Sema/AttrParsedAttrImpl.inc"
190
191// namespace
192
193static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
194  return AttrInfoMap[A.getKind()];
195}
196
197unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
198
199unsigned ParsedAttr::getMaxArgs() const {
200  return getMinArgs() + getInfo(*this).OptArgs;
201}
202
203bool ParsedAttr::hasCustomParsing() const {
204  return getInfo(*this).HasCustomParsing;
205}
206
207bool ParsedAttr::diagnoseAppertainsTo(Sema &Sconst Decl *Dconst {
208  return getInfo(*this).DiagAppertainsToDecl(S, *thisD);
209}
210
211bool ParsedAttr::appliesToDecl(const Decl *D,
212                               attr::SubjectMatchRule MatchRuleconst {
213  return checkAttributeMatchRuleAppliesTo(DMatchRule);
214}
215
216void ParsedAttr::getMatchRules(
217    const LangOptions &LangOpts,
218    SmallVectorImpl<std::pair<attr::SubjectMatchRulebool>> &MatchRules)
219    const {
220  return getInfo(*this).GetPragmaAttributeMatchRules(MatchRulesLangOpts);
221}
222
223bool ParsedAttr::diagnoseLangOpts(Sema &Sconst {
224  return getInfo(*this).DiagLangOpts(S, *this);
225}
226
227bool ParsedAttr::isTargetSpecificAttr() const {
228  return getInfo(*this).IsTargetSpecific;
229}
230
231bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
232
233bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
234
235bool ParsedAttr::existsInTarget(const TargetInfo &Targetconst {
236  return getInfo(*this).ExistsInTarget(Target);
237}
238
239bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
240
241bool ParsedAttr::isSupportedByPragmaAttribute() const {
242  return getInfo(*this).IsSupportedByPragmaAttribute;
243}
244
245unsigned ParsedAttr::getSemanticSpelling() const {
246  return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
247}
248
249bool ParsedAttr::hasVariadicArg() const {
250  // If the attribute has the maximum number of optional arguments, we will
251  // claim that as being variadic. If we someday get an attribute that
252  // legitimately bumps up against that maximum, we can use another bit to track
253  // whether it's truly variadic or not.
254  return getInfo(*this).OptArgs == 15;
255}
256
clang::IdentifierLoc::create
clang::ParsedAttr::allocated_size
clang::AttributeFactory::allocate
clang::AttributeFactory::deallocate
clang::AttributeFactory::reclaimPool
clang::AttributePool::takePool
clang::ParsedAttr::getKind
clang::ParsedAttr::getAttributeSpellingListIndex
clang::ParsedAttr::getMinArgs
clang::ParsedAttr::getMaxArgs
clang::ParsedAttr::hasCustomParsing
clang::ParsedAttr::diagnoseAppertainsTo
clang::ParsedAttr::appliesToDecl
clang::ParsedAttr::getMatchRules
clang::ParsedAttr::diagnoseLangOpts
clang::ParsedAttr::isTargetSpecificAttr
clang::ParsedAttr::isTypeAttr
clang::ParsedAttr::isStmtAttr
clang::ParsedAttr::existsInTarget
clang::ParsedAttr::isKnownToGCC
clang::ParsedAttr::isSupportedByPragmaAttribute
clang::ParsedAttr::getSemanticSpelling
clang::ParsedAttr::hasVariadicArg