]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Sema/ParsedAttr.cpp
MFC r343918: Teach /etc/rc.d/growfs how to handle systems running ZFS.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Sema / ParsedAttr.cpp
1 //======- ParsedAttr.cpp --------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the ParsedAttr class implementation
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/Sema/ParsedAttr.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/AttrSubjectMatchRules.h"
17 #include "clang/Basic/IdentifierTable.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "clang/Sema/SemaInternal.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include <cassert>
24 #include <cstddef>
25 #include <utility>
26
27 using namespace clang;
28
29 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
30                                      IdentifierInfo *Ident) {
31   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
32   Result->Loc = Loc;
33   Result->Ident = Ident;
34   return Result;
35 }
36
37 size_t ParsedAttr::allocated_size() const {
38   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
39   else if (IsTypeTagForDatatype)
40     return AttributeFactory::TypeTagForDatatypeAllocSize;
41   else if (IsProperty)
42     return AttributeFactory::PropertyAllocSize;
43   else if (HasParsedType)
44     return sizeof(ParsedAttr) + sizeof(void *);
45   return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion));
46 }
47
48 AttributeFactory::AttributeFactory() {
49   // Go ahead and configure all the inline capacity.  This is just a memset.
50   FreeLists.resize(InlineFreeListsCapacity);
51 }
52 AttributeFactory::~AttributeFactory() = default;
53
54 static size_t getFreeListIndexForSize(size_t size) {
55   assert(size >= sizeof(ParsedAttr));
56   assert((size % sizeof(void*)) == 0);
57   return ((size - sizeof(ParsedAttr)) / sizeof(void *));
58 }
59
60 void *AttributeFactory::allocate(size_t size) {
61   // Check for a previously reclaimed attribute.
62   size_t index = getFreeListIndexForSize(size);
63   if (index < FreeLists.size() && !FreeLists[index].empty()) {
64     ParsedAttr *attr = FreeLists[index].back();
65     FreeLists[index].pop_back();
66     return attr;
67   }
68
69   // Otherwise, allocate something new.
70   return Alloc.Allocate(size, alignof(AttributeFactory));
71 }
72
73 void AttributeFactory::deallocate(ParsedAttr *Attr) {
74   size_t size = Attr->allocated_size();
75   size_t freeListIndex = getFreeListIndexForSize(size);
76
77   // Expand FreeLists to the appropriate size, if required.
78   if (freeListIndex >= FreeLists.size())
79     FreeLists.resize(freeListIndex + 1);
80
81 #if !NDEBUG
82   // In debug mode, zero out the attribute to help find memory overwriting.
83   memset(Attr, 0, size);
84 #endif
85
86   // Add 'Attr' to the appropriate free-list.
87   FreeLists[freeListIndex].push_back(Attr);
88 }
89
90 void AttributeFactory::reclaimPool(AttributePool &cur) {
91   for (ParsedAttr *AL : cur.Attrs)
92     deallocate(AL);
93 }
94
95 void AttributePool::takePool(AttributePool &pool) {
96   Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
97   pool.Attrs.clear();
98 }
99
100 #include "clang/Sema/AttrParsedAttrKinds.inc"
101
102 static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
103                                    ParsedAttr::Syntax SyntaxUsed) {
104   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
105   // for GNU attributes.
106   bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
107                ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
108                  SyntaxUsed == ParsedAttr::AS_C2x) &&
109                 ScopeName == "gnu");
110   if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
111       AttrName.endswith("__"))
112     AttrName = AttrName.slice(2, AttrName.size() - 2);
113
114   return AttrName;
115 }
116
117 ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
118                                      const IdentifierInfo *ScopeName,
119                                      Syntax SyntaxUsed) {
120   StringRef AttrName = Name->getName();
121
122   SmallString<64> FullName;
123   if (ScopeName)
124     FullName += ScopeName->getName();
125
126   AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
127
128   // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
129   // unscoped.
130   if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
131     FullName += "::";
132   FullName += AttrName;
133
134   return ::getAttrKind(FullName, SyntaxUsed);
135 }
136
137 unsigned ParsedAttr::getAttributeSpellingListIndex() const {
138   // Both variables will be used in tablegen generated
139   // attribute spell list index matching code.
140   StringRef Scope = ScopeName ? ScopeName->getName() : "";
141   StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
142                                      (ParsedAttr::Syntax)SyntaxUsed);
143
144 #include "clang/Sema/AttrSpellingListIndex.inc"
145
146 }
147
148 struct ParsedAttrInfo {
149   unsigned NumArgs : 4;
150   unsigned OptArgs : 4;
151   unsigned HasCustomParsing : 1;
152   unsigned IsTargetSpecific : 1;
153   unsigned IsType : 1;
154   unsigned IsStmt : 1;
155   unsigned IsKnownToGCC : 1;
156   unsigned IsSupportedByPragmaAttribute : 1;
157
158   bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
159   bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
160   bool (*ExistsInTarget)(const TargetInfo &Target);
161   unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
162   void (*GetPragmaAttributeMatchRules)(
163       llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
164       const LangOptions &LangOpts);
165 };
166
167 namespace {
168
169 #include "clang/Sema/AttrParsedAttrImpl.inc"
170
171 } // namespace
172
173 static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
174   return AttrInfoMap[A.getKind()];
175 }
176
177 unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
178
179 unsigned ParsedAttr::getMaxArgs() const {
180   return getMinArgs() + getInfo(*this).OptArgs;
181 }
182
183 bool ParsedAttr::hasCustomParsing() const {
184   return getInfo(*this).HasCustomParsing;
185 }
186
187 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
188   return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
189 }
190
191 bool ParsedAttr::appliesToDecl(const Decl *D,
192                                attr::SubjectMatchRule MatchRule) const {
193   return checkAttributeMatchRuleAppliesTo(D, MatchRule);
194 }
195
196 void ParsedAttr::getMatchRules(
197     const LangOptions &LangOpts,
198     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
199     const {
200   return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
201 }
202
203 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
204   return getInfo(*this).DiagLangOpts(S, *this);
205 }
206
207 bool ParsedAttr::isTargetSpecificAttr() const {
208   return getInfo(*this).IsTargetSpecific;
209 }
210
211 bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
212
213 bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
214
215 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
216   return getInfo(*this).ExistsInTarget(Target);
217 }
218
219 bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
220
221 bool ParsedAttr::isSupportedByPragmaAttribute() const {
222   return getInfo(*this).IsSupportedByPragmaAttribute;
223 }
224
225 unsigned ParsedAttr::getSemanticSpelling() const {
226   return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
227 }
228
229 bool ParsedAttr::hasVariadicArg() const {
230   // If the attribute has the maximum number of optional arguments, we will
231   // claim that as being variadic. If we someday get an attribute that
232   // legitimately bumps up against that maximum, we can use another bit to track
233   // whether it's truly variadic or not.
234   return getInfo(*this).OptArgs == 15;
235 }