blob: 6d5c6a26ef57ac9b0b0e482adfe4230c2a43e565 [file] [log] [blame]
Eugene Zelenko711964d2018-02-20 02:16:28 +00001//===- AttributeList.cpp --------------------------------------------------===//
Steve Naroffb8371e12007-06-09 03:39:29 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5b12ab82007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Steve Naroffb8371e12007-06-09 03:39:29 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the AttributeList class implementation
11//
12//===----------------------------------------------------------------------===//
13
John McCall8b0666c2010-08-20 18:27:03 +000014#include "clang/Sema/AttributeList.h"
Benjamin Kramer1ea8e092012-07-04 17:04:04 +000015#include "clang/AST/ASTContext.h"
Alex Lorenz9e7bf162017-04-18 14:33:39 +000016#include "clang/Basic/AttrSubjectMatchRules.h"
Chris Lattner7e0fe442009-04-11 18:48:18 +000017#include "clang/Basic/IdentifierTable.h"
Bob Wilson7c730832015-07-20 22:57:31 +000018#include "clang/Basic/TargetInfo.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000019#include "clang/Sema/SemaInternal.h"
Richard Smith84837d52012-05-03 18:27:39 +000020#include "llvm/ADT/SmallString.h"
Eugene Zelenko711964d2018-02-20 02:16:28 +000021#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include <cassert>
24#include <cstddef>
25#include <utility>
26
Steve Naroffb8371e12007-06-09 03:39:29 +000027using namespace clang;
28
Richard Smithfeefaf52013-09-03 18:01:40 +000029IdentifierLoc *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
John McCall084e83d2011-03-24 11:26:52 +000037size_t AttributeList::allocated_size() const {
38 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
Dmitri Gribenkoe4a5a902012-08-17 00:08:38 +000039 else if (IsTypeTagForDatatype)
40 return AttributeFactory::TypeTagForDatatypeAllocSize;
John McCall5e77d762013-04-16 07:28:30 +000041 else if (IsProperty)
42 return AttributeFactory::PropertyAllocSize;
Erich Keane87cfcfd2018-06-22 17:34:44 +000043 else if (HasParsedType)
44 return sizeof(AttributeList) + sizeof(void *);
Aaron Ballman00e99962013-08-31 01:11:41 +000045 return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
Steve Naroffb8371e12007-06-09 03:39:29 +000046}
Chris Lattnerf18c7432008-02-20 23:14:47 +000047
John McCall084e83d2011-03-24 11:26:52 +000048AttributeFactory::AttributeFactory() {
49 // Go ahead and configure all the inline capacity. This is just a memset.
50 FreeLists.resize(InlineFreeListsCapacity);
51}
Eugene Zelenko711964d2018-02-20 02:16:28 +000052AttributeFactory::~AttributeFactory() = default;
John McCall084e83d2011-03-24 11:26:52 +000053
54static size_t getFreeListIndexForSize(size_t size) {
55 assert(size >= sizeof(AttributeList));
56 assert((size % sizeof(void*)) == 0);
57 return ((size - sizeof(AttributeList)) / sizeof(void*));
58}
59
60void *AttributeFactory::allocate(size_t size) {
61 // Check for a previously reclaimed attribute.
62 size_t index = getFreeListIndexForSize(size);
Erich Keanec480f302018-07-12 21:09:05 +000063 if (index < FreeLists.size() && !FreeLists[index].empty()) {
64 AttributeList *attr = FreeLists[index].back();
65 FreeLists[index].pop_back();
66 return attr;
John McCall084e83d2011-03-24 11:26:52 +000067 }
68
69 // Otherwise, allocate something new.
Benjamin Kramerc3f89252016-10-20 14:27:22 +000070 return Alloc.Allocate(size, alignof(AttributeFactory));
John McCall084e83d2011-03-24 11:26:52 +000071}
72
Erich Keanec480f302018-07-12 21:09:05 +000073void AttributeFactory::deallocate(AttributeList *Attr) {
74 size_t size = Attr->allocated_size();
75 size_t freeListIndex = getFreeListIndexForSize(size);
John McCall084e83d2011-03-24 11:26:52 +000076
Erich Keanec480f302018-07-12 21:09:05 +000077 // Expand FreeLists to the appropriate size, if required.
78 if (freeListIndex >= FreeLists.size())
79 FreeLists.resize(freeListIndex + 1);
John McCall084e83d2011-03-24 11:26:52 +000080
Erich Keanec480f302018-07-12 21:09:05 +000081#if !NDEBUG
82 // In debug mode, zero out the attribute to help find memory overwriting.
83 memset(Attr, 0, size);
84#endif
John McCall084e83d2011-03-24 11:26:52 +000085
Erich Keanec480f302018-07-12 21:09:05 +000086 // Add 'Attr' to the appropriate free-list.
87 FreeLists[freeListIndex].push_back(Attr);
John McCall084e83d2011-03-24 11:26:52 +000088}
89
Erich Keanec480f302018-07-12 21:09:05 +000090void AttributeFactory::reclaimPool(AttributePool &cur) {
91 for (AttributeList *AL : cur.Attrs)
92 deallocate(AL);
93}
John McCall084e83d2011-03-24 11:26:52 +000094
Erich Keanec480f302018-07-12 21:09:05 +000095void AttributePool::takePool(AttributePool &pool) {
96 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
97 pool.Attrs.clear();
John McCall084e83d2011-03-24 11:26:52 +000098}
99
Douglas Gregor377f99b2012-05-02 17:33:51 +0000100#include "clang/Sema/AttrParsedAttrKinds.inc"
101
David Majnemera94e7b62015-08-25 16:44:38 +0000102static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
103 AttributeList::Syntax SyntaxUsed) {
104 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
105 // for GNU attributes.
106 bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
Aaron Ballman606093a2017-10-15 15:01:42 +0000107 ((SyntaxUsed == AttributeList::AS_CXX11 ||
108 SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu");
David Majnemera94e7b62015-08-25 16:44:38 +0000109 if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
110 AttrName.endswith("__"))
111 AttrName = AttrName.slice(2, AttrName.size() - 2);
112
113 return AttrName;
114}
115
Richard Smith84837d52012-05-03 18:27:39 +0000116AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
Alexis Hunta0e54d42012-06-18 16:13:52 +0000117 const IdentifierInfo *ScopeName,
118 Syntax SyntaxUsed) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000119 StringRef AttrName = Name->getName();
Chris Lattnerf18c7432008-02-20 23:14:47 +0000120
Aaron Ballmanc6988092013-12-11 22:27:44 +0000121 SmallString<64> FullName;
Richard Smith84837d52012-05-03 18:27:39 +0000122 if (ScopeName)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000123 FullName += ScopeName->getName();
124
David Majnemera94e7b62015-08-25 16:44:38 +0000125 AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000126
Alexis Hunta0e54d42012-06-18 16:13:52 +0000127 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
128 // unscoped.
Aaron Ballman606093a2017-10-15 15:01:42 +0000129 if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000130 FullName += "::";
131 FullName += AttrName;
Richard Smith84837d52012-05-03 18:27:39 +0000132
Aaron Ballman09e98ff2014-01-13 21:42:39 +0000133 return ::getAttrKind(FullName, SyntaxUsed);
Chris Lattnerf18c7432008-02-20 23:14:47 +0000134}
Michael Han99315932013-01-24 16:46:58 +0000135
136unsigned AttributeList::getAttributeSpellingListIndex() const {
137 // Both variables will be used in tablegen generated
138 // attribute spell list index matching code.
Michael Han99315932013-01-24 16:46:58 +0000139 StringRef Scope = ScopeName ? ScopeName->getName() : "";
David Majnemera94e7b62015-08-25 16:44:38 +0000140 StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
141 (AttributeList::Syntax)SyntaxUsed);
Michael Han99315932013-01-24 16:46:58 +0000142
143#include "clang/Sema/AttrSpellingListIndex.inc"
144
145}
146
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000147struct ParsedAttrInfo {
148 unsigned NumArgs : 4;
149 unsigned OptArgs : 4;
150 unsigned HasCustomParsing : 1;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000151 unsigned IsTargetSpecific : 1;
152 unsigned IsType : 1;
Richard Smith4f902c72016-03-08 00:32:55 +0000153 unsigned IsStmt : 1;
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000154 unsigned IsKnownToGCC : 1;
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000155 unsigned IsSupportedByPragmaAttribute : 1;
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000156
157 bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
158 const Decl *);
Aaron Ballman3aff6332013-12-02 19:30:36 +0000159 bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
Bob Wilson7c730832015-07-20 22:57:31 +0000160 bool (*ExistsInTarget)(const TargetInfo &Target);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000161 unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000162 void (*GetPragmaAttributeMatchRules)(
163 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
164 const LangOptions &LangOpts);
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000165};
166
167namespace {
Eugene Zelenko711964d2018-02-20 02:16:28 +0000168
169#include "clang/Sema/AttrParsedAttrImpl.inc"
170
171} // namespace
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000172
Benjamin Kramer602623f2013-09-28 15:08:41 +0000173static const ParsedAttrInfo &getInfo(const AttributeList &A) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000174 return AttrInfoMap[A.getKind()];
175}
176
177unsigned AttributeList::getMinArgs() const {
178 return getInfo(*this).NumArgs;
179}
180
181unsigned AttributeList::getMaxArgs() const {
182 return getMinArgs() + getInfo(*this).OptArgs;
183}
184
185bool AttributeList::hasCustomParsing() const {
186 return getInfo(*this).HasCustomParsing;
187}
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000188
189bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
190 return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
191}
Aaron Ballman3aff6332013-12-02 19:30:36 +0000192
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000193bool AttributeList::appliesToDecl(const Decl *D,
194 attr::SubjectMatchRule MatchRule) const {
195 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
196}
197
198void AttributeList::getMatchRules(
199 const LangOptions &LangOpts,
200 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
201 const {
202 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
203}
204
Aaron Ballman3aff6332013-12-02 19:30:36 +0000205bool AttributeList::diagnoseLangOpts(Sema &S) const {
206 return getInfo(*this).DiagLangOpts(S, *this);
207}
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000208
209bool AttributeList::isTargetSpecificAttr() const {
210 return getInfo(*this).IsTargetSpecific;
211}
212
213bool AttributeList::isTypeAttr() const {
214 return getInfo(*this).IsType;
215}
216
Richard Smith4f902c72016-03-08 00:32:55 +0000217bool AttributeList::isStmtAttr() const {
218 return getInfo(*this).IsStmt;
219}
220
Bob Wilson7c730832015-07-20 22:57:31 +0000221bool AttributeList::existsInTarget(const TargetInfo &Target) const {
222 return getInfo(*this).ExistsInTarget(Target);
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000223}
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000224
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000225bool AttributeList::isKnownToGCC() const {
226 return getInfo(*this).IsKnownToGCC;
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000227}
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000228
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000229bool AttributeList::isSupportedByPragmaAttribute() const {
230 return getInfo(*this).IsSupportedByPragmaAttribute;
231}
232
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000233unsigned AttributeList::getSemanticSpelling() const {
234 return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
235}
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000236
237bool AttributeList::hasVariadicArg() const {
238 // If the attribute has the maximum number of optional arguments, we will
239 // claim that as being variadic. If we someday get an attribute that
240 // legitimately bumps up against that maximum, we can use another bit to track
241 // whether it's truly variadic or not.
242 return getInfo(*this).OptArgs == 15;
243}