blob: 59e5aab677a9e5f85e9683f1a95e11dd86157b56 [file] [log] [blame]
Erich Keanee891aa92018-07-13 15:07:47 +00001//======- ParsedAttr.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//
Erich Keanee891aa92018-07-13 15:07:47 +000010// This file defines the ParsedAttr class implementation
Steve Naroffb8371e12007-06-09 03:39:29 +000011//
12//===----------------------------------------------------------------------===//
13
Erich Keanee891aa92018-07-13 15:07:47 +000014#include "clang/Sema/ParsedAttr.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
Erich Keanee891aa92018-07-13 15:07:47 +000037size_t ParsedAttr::allocated_size() const {
John McCall084e83d2011-03-24 11:26:52 +000038 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)
Erich Keane03406c52018-08-09 20:25:12 +000044 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
45 detail::TypeTagForDatatypeData, ParsedType,
46 detail::PropertyData>(0, 0, 0, 1, 0);
47 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
48 detail::TypeTagForDatatypeData, ParsedType,
49 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
Steve Naroffb8371e12007-06-09 03:39:29 +000050}
Chris Lattnerf18c7432008-02-20 23:14:47 +000051
John McCall084e83d2011-03-24 11:26:52 +000052AttributeFactory::AttributeFactory() {
53 // Go ahead and configure all the inline capacity. This is just a memset.
54 FreeLists.resize(InlineFreeListsCapacity);
55}
Eugene Zelenko711964d2018-02-20 02:16:28 +000056AttributeFactory::~AttributeFactory() = default;
John McCall084e83d2011-03-24 11:26:52 +000057
58static size_t getFreeListIndexForSize(size_t size) {
Erich Keanee891aa92018-07-13 15:07:47 +000059 assert(size >= sizeof(ParsedAttr));
John McCall084e83d2011-03-24 11:26:52 +000060 assert((size % sizeof(void*)) == 0);
Erich Keanee891aa92018-07-13 15:07:47 +000061 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
John McCall084e83d2011-03-24 11:26:52 +000062}
63
64void *AttributeFactory::allocate(size_t size) {
65 // Check for a previously reclaimed attribute.
66 size_t index = getFreeListIndexForSize(size);
Erich Keanec480f302018-07-12 21:09:05 +000067 if (index < FreeLists.size() && !FreeLists[index].empty()) {
Erich Keanee891aa92018-07-13 15:07:47 +000068 ParsedAttr *attr = FreeLists[index].back();
Erich Keanec480f302018-07-12 21:09:05 +000069 FreeLists[index].pop_back();
70 return attr;
John McCall084e83d2011-03-24 11:26:52 +000071 }
72
73 // Otherwise, allocate something new.
Benjamin Kramerc3f89252016-10-20 14:27:22 +000074 return Alloc.Allocate(size, alignof(AttributeFactory));
John McCall084e83d2011-03-24 11:26:52 +000075}
76
Erich Keanee891aa92018-07-13 15:07:47 +000077void AttributeFactory::deallocate(ParsedAttr *Attr) {
Erich Keanec480f302018-07-12 21:09:05 +000078 size_t size = Attr->allocated_size();
79 size_t freeListIndex = getFreeListIndexForSize(size);
John McCall084e83d2011-03-24 11:26:52 +000080
Erich Keanec480f302018-07-12 21:09:05 +000081 // Expand FreeLists to the appropriate size, if required.
82 if (freeListIndex >= FreeLists.size())
83 FreeLists.resize(freeListIndex + 1);
John McCall084e83d2011-03-24 11:26:52 +000084
Sven van Haastregt7b39a082018-09-24 12:12:03 +000085#ifndef NDEBUG
Erich Keanec480f302018-07-12 21:09:05 +000086 // In debug mode, zero out the attribute to help find memory overwriting.
87 memset(Attr, 0, size);
88#endif
John McCall084e83d2011-03-24 11:26:52 +000089
Erich Keanec480f302018-07-12 21:09:05 +000090 // Add 'Attr' to the appropriate free-list.
91 FreeLists[freeListIndex].push_back(Attr);
John McCall084e83d2011-03-24 11:26:52 +000092}
93
Erich Keanec480f302018-07-12 21:09:05 +000094void AttributeFactory::reclaimPool(AttributePool &cur) {
Erich Keanee891aa92018-07-13 15:07:47 +000095 for (ParsedAttr *AL : cur.Attrs)
Erich Keanec480f302018-07-12 21:09:05 +000096 deallocate(AL);
97}
John McCall084e83d2011-03-24 11:26:52 +000098
Erich Keanec480f302018-07-12 21:09:05 +000099void AttributePool::takePool(AttributePool &pool) {
100 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
101 pool.Attrs.clear();
John McCall084e83d2011-03-24 11:26:52 +0000102}
103
Douglas Gregor377f99b2012-05-02 17:33:51 +0000104#include "clang/Sema/AttrParsedAttrKinds.inc"
105
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000106static StringRef normalizeAttrScopeName(StringRef ScopeName,
107 ParsedAttr::Syntax SyntaxUsed) {
Aaron Ballmanc44c17422018-11-09 17:19:45 +0000108 // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name
109 // to be "clang".
110 if (SyntaxUsed == ParsedAttr::AS_CXX11 ||
111 SyntaxUsed == ParsedAttr::AS_C2x) {
112 if (ScopeName == "__gnu__")
113 ScopeName = "gnu";
114 else if (ScopeName == "_Clang")
115 ScopeName = "clang";
116 }
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000117 return ScopeName;
118}
119
120static StringRef normalizeAttrName(StringRef AttrName,
121 StringRef NormalizedScopeName,
Erich Keanee891aa92018-07-13 15:07:47 +0000122 ParsedAttr::Syntax SyntaxUsed) {
David Majnemera94e7b62015-08-25 16:44:38 +0000123 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000124 // for GNU attributes, and attributes using the double square bracket syntax.
Aaron Ballmanac77dcd2018-11-09 19:37:18 +0000125 bool ShouldNormalize =
126 SyntaxUsed == ParsedAttr::AS_GNU ||
127 ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
128 SyntaxUsed == ParsedAttr::AS_C2x) &&
129 (NormalizedScopeName == "gnu" || NormalizedScopeName == "clang"));
130 if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") &&
David Majnemera94e7b62015-08-25 16:44:38 +0000131 AttrName.endswith("__"))
132 AttrName = AttrName.slice(2, AttrName.size() - 2);
133
134 return AttrName;
135}
136
Erich Keanee891aa92018-07-13 15:07:47 +0000137ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
138 const IdentifierInfo *ScopeName,
139 Syntax SyntaxUsed) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000140 StringRef AttrName = Name->getName();
Chris Lattnerf18c7432008-02-20 23:14:47 +0000141
Aaron Ballmanc6988092013-12-11 22:27:44 +0000142 SmallString<64> FullName;
Richard Smith84837d52012-05-03 18:27:39 +0000143 if (ScopeName)
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000144 FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000145
David Majnemera94e7b62015-08-25 16:44:38 +0000146 AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000147
Alexis Hunta0e54d42012-06-18 16:13:52 +0000148 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
149 // unscoped.
Aaron Ballman606093a2017-10-15 15:01:42 +0000150 if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000151 FullName += "::";
152 FullName += AttrName;
Richard Smith84837d52012-05-03 18:27:39 +0000153
Aaron Ballman09e98ff2014-01-13 21:42:39 +0000154 return ::getAttrKind(FullName, SyntaxUsed);
Chris Lattnerf18c7432008-02-20 23:14:47 +0000155}
Michael Han99315932013-01-24 16:46:58 +0000156
Erich Keanee891aa92018-07-13 15:07:47 +0000157unsigned ParsedAttr::getAttributeSpellingListIndex() const {
Michael Han99315932013-01-24 16:46:58 +0000158 // Both variables will be used in tablegen generated
159 // attribute spell list index matching code.
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000160 auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
161 StringRef Scope =
162 ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
163 StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
Michael Han99315932013-01-24 16:46:58 +0000164
165#include "clang/Sema/AttrSpellingListIndex.inc"
166
167}
168
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000169struct ParsedAttrInfo {
170 unsigned NumArgs : 4;
171 unsigned OptArgs : 4;
172 unsigned HasCustomParsing : 1;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000173 unsigned IsTargetSpecific : 1;
174 unsigned IsType : 1;
Richard Smith4f902c72016-03-08 00:32:55 +0000175 unsigned IsStmt : 1;
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000176 unsigned IsKnownToGCC : 1;
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000177 unsigned IsSupportedByPragmaAttribute : 1;
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000178
Erich Keanee891aa92018-07-13 15:07:47 +0000179 bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
180 bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
Bob Wilson7c730832015-07-20 22:57:31 +0000181 bool (*ExistsInTarget)(const TargetInfo &Target);
Erich Keanee891aa92018-07-13 15:07:47 +0000182 unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000183 void (*GetPragmaAttributeMatchRules)(
184 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
185 const LangOptions &LangOpts);
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000186};
187
188namespace {
Eugene Zelenko711964d2018-02-20 02:16:28 +0000189
190#include "clang/Sema/AttrParsedAttrImpl.inc"
191
192} // namespace
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000193
Erich Keanee891aa92018-07-13 15:07:47 +0000194static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000195 return AttrInfoMap[A.getKind()];
196}
197
Erich Keanee891aa92018-07-13 15:07:47 +0000198unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000199
Erich Keanee891aa92018-07-13 15:07:47 +0000200unsigned ParsedAttr::getMaxArgs() const {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000201 return getMinArgs() + getInfo(*this).OptArgs;
202}
203
Erich Keanee891aa92018-07-13 15:07:47 +0000204bool ParsedAttr::hasCustomParsing() const {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000205 return getInfo(*this).HasCustomParsing;
206}
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000207
Erich Keanee891aa92018-07-13 15:07:47 +0000208bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000209 return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
210}
Aaron Ballman3aff6332013-12-02 19:30:36 +0000211
Erich Keanee891aa92018-07-13 15:07:47 +0000212bool ParsedAttr::appliesToDecl(const Decl *D,
213 attr::SubjectMatchRule MatchRule) const {
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000214 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
215}
216
Erich Keanee891aa92018-07-13 15:07:47 +0000217void ParsedAttr::getMatchRules(
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000218 const LangOptions &LangOpts,
219 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
220 const {
221 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
222}
223
Erich Keanee891aa92018-07-13 15:07:47 +0000224bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
Aaron Ballman3aff6332013-12-02 19:30:36 +0000225 return getInfo(*this).DiagLangOpts(S, *this);
226}
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000227
Erich Keanee891aa92018-07-13 15:07:47 +0000228bool ParsedAttr::isTargetSpecificAttr() const {
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000229 return getInfo(*this).IsTargetSpecific;
230}
231
Erich Keanee891aa92018-07-13 15:07:47 +0000232bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000233
Erich Keanee891aa92018-07-13 15:07:47 +0000234bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
Richard Smith4f902c72016-03-08 00:32:55 +0000235
Erich Keanee891aa92018-07-13 15:07:47 +0000236bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
Bob Wilson7c730832015-07-20 22:57:31 +0000237 return getInfo(*this).ExistsInTarget(Target);
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000238}
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000239
Erich Keanee891aa92018-07-13 15:07:47 +0000240bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000241
Erich Keanee891aa92018-07-13 15:07:47 +0000242bool ParsedAttr::isSupportedByPragmaAttribute() const {
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000243 return getInfo(*this).IsSupportedByPragmaAttribute;
244}
245
Erich Keanee891aa92018-07-13 15:07:47 +0000246unsigned ParsedAttr::getSemanticSpelling() const {
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000247 return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
248}
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000249
Erich Keanee891aa92018-07-13 15:07:47 +0000250bool ParsedAttr::hasVariadicArg() const {
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000251 // If the attribute has the maximum number of optional arguments, we will
252 // claim that as being variadic. If we someday get an attribute that
253 // legitimately bumps up against that maximum, we can use another bit to track
254 // whether it's truly variadic or not.
255 return getInfo(*this).OptArgs == 15;
256}