blob: 5c04443460bc27ea4b974733beddc89e82902575 [file] [log] [blame]
Erich Keanee891aa92018-07-13 15:07:47 +00001//======- ParsedAttr.cpp --------------------------------------------------===//
Steve Naroffb8371e12007-06-09 03:39:29 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Steve Naroffb8371e12007-06-09 03:39:29 +00006//
7//===----------------------------------------------------------------------===//
8//
Erich Keanee891aa92018-07-13 15:07:47 +00009// This file defines the ParsedAttr class implementation
Steve Naroffb8371e12007-06-09 03:39:29 +000010//
11//===----------------------------------------------------------------------===//
12
Erich Keanee891aa92018-07-13 15:07:47 +000013#include "clang/Sema/ParsedAttr.h"
Benjamin Kramer1ea8e092012-07-04 17:04:04 +000014#include "clang/AST/ASTContext.h"
Alex Lorenz9e7bf162017-04-18 14:33:39 +000015#include "clang/Basic/AttrSubjectMatchRules.h"
Chris Lattner7e0fe442009-04-11 18:48:18 +000016#include "clang/Basic/IdentifierTable.h"
Bob Wilson7c730832015-07-20 22:57:31 +000017#include "clang/Basic/TargetInfo.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000018#include "clang/Sema/SemaInternal.h"
Richard Smith84837d52012-05-03 18:27:39 +000019#include "llvm/ADT/SmallString.h"
Eugene Zelenko711964d2018-02-20 02:16:28 +000020#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringRef.h"
22#include <cassert>
23#include <cstddef>
24#include <utility>
25
Steve Naroffb8371e12007-06-09 03:39:29 +000026using namespace clang;
27
Richard Smithfeefaf52013-09-03 18:01:40 +000028IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
29 IdentifierInfo *Ident) {
30 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
31 Result->Loc = Loc;
32 Result->Ident = Ident;
33 return Result;
34}
35
Erich Keanee891aa92018-07-13 15:07:47 +000036size_t ParsedAttr::allocated_size() const {
John McCall084e83d2011-03-24 11:26:52 +000037 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
Dmitri Gribenkoe4a5a902012-08-17 00:08:38 +000038 else if (IsTypeTagForDatatype)
39 return AttributeFactory::TypeTagForDatatypeAllocSize;
John McCall5e77d762013-04-16 07:28:30 +000040 else if (IsProperty)
41 return AttributeFactory::PropertyAllocSize;
Erich Keane87cfcfd2018-06-22 17:34:44 +000042 else if (HasParsedType)
Erich Keane03406c52018-08-09 20:25:12 +000043 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
44 detail::TypeTagForDatatypeData, ParsedType,
45 detail::PropertyData>(0, 0, 0, 1, 0);
46 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47 detail::TypeTagForDatatypeData, ParsedType,
48 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
Steve Naroffb8371e12007-06-09 03:39:29 +000049}
Chris Lattnerf18c7432008-02-20 23:14:47 +000050
John McCall084e83d2011-03-24 11:26:52 +000051AttributeFactory::AttributeFactory() {
52 // Go ahead and configure all the inline capacity. This is just a memset.
53 FreeLists.resize(InlineFreeListsCapacity);
54}
Eugene Zelenko711964d2018-02-20 02:16:28 +000055AttributeFactory::~AttributeFactory() = default;
John McCall084e83d2011-03-24 11:26:52 +000056
57static size_t getFreeListIndexForSize(size_t size) {
Erich Keanee891aa92018-07-13 15:07:47 +000058 assert(size >= sizeof(ParsedAttr));
John McCall084e83d2011-03-24 11:26:52 +000059 assert((size % sizeof(void*)) == 0);
Erich Keanee891aa92018-07-13 15:07:47 +000060 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
John McCall084e83d2011-03-24 11:26:52 +000061}
62
63void *AttributeFactory::allocate(size_t size) {
64 // Check for a previously reclaimed attribute.
65 size_t index = getFreeListIndexForSize(size);
Erich Keanec480f302018-07-12 21:09:05 +000066 if (index < FreeLists.size() && !FreeLists[index].empty()) {
Erich Keanee891aa92018-07-13 15:07:47 +000067 ParsedAttr *attr = FreeLists[index].back();
Erich Keanec480f302018-07-12 21:09:05 +000068 FreeLists[index].pop_back();
69 return attr;
John McCall084e83d2011-03-24 11:26:52 +000070 }
71
72 // Otherwise, allocate something new.
Benjamin Kramerc3f89252016-10-20 14:27:22 +000073 return Alloc.Allocate(size, alignof(AttributeFactory));
John McCall084e83d2011-03-24 11:26:52 +000074}
75
Erich Keanee891aa92018-07-13 15:07:47 +000076void AttributeFactory::deallocate(ParsedAttr *Attr) {
Erich Keanec480f302018-07-12 21:09:05 +000077 size_t size = Attr->allocated_size();
78 size_t freeListIndex = getFreeListIndexForSize(size);
John McCall084e83d2011-03-24 11:26:52 +000079
Erich Keanec480f302018-07-12 21:09:05 +000080 // Expand FreeLists to the appropriate size, if required.
81 if (freeListIndex >= FreeLists.size())
82 FreeLists.resize(freeListIndex + 1);
John McCall084e83d2011-03-24 11:26:52 +000083
Sven van Haastregt7b39a082018-09-24 12:12:03 +000084#ifndef NDEBUG
Erich Keanec480f302018-07-12 21:09:05 +000085 // In debug mode, zero out the attribute to help find memory overwriting.
86 memset(Attr, 0, size);
87#endif
John McCall084e83d2011-03-24 11:26:52 +000088
Erich Keanec480f302018-07-12 21:09:05 +000089 // Add 'Attr' to the appropriate free-list.
90 FreeLists[freeListIndex].push_back(Attr);
John McCall084e83d2011-03-24 11:26:52 +000091}
92
Erich Keanec480f302018-07-12 21:09:05 +000093void AttributeFactory::reclaimPool(AttributePool &cur) {
Erich Keanee891aa92018-07-13 15:07:47 +000094 for (ParsedAttr *AL : cur.Attrs)
Erich Keanec480f302018-07-12 21:09:05 +000095 deallocate(AL);
96}
John McCall084e83d2011-03-24 11:26:52 +000097
Erich Keanec480f302018-07-12 21:09:05 +000098void AttributePool::takePool(AttributePool &pool) {
99 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100 pool.Attrs.clear();
John McCall084e83d2011-03-24 11:26:52 +0000101}
102
Douglas Gregor377f99b2012-05-02 17:33:51 +0000103#include "clang/Sema/AttrParsedAttrKinds.inc"
104
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000105static StringRef normalizeAttrScopeName(StringRef ScopeName,
106 ParsedAttr::Syntax SyntaxUsed) {
Aaron Ballmanc44c17422018-11-09 17:19:45 +0000107 // 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 }
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000116 return ScopeName;
117}
118
119static StringRef normalizeAttrName(StringRef AttrName,
120 StringRef NormalizedScopeName,
Erich Keanee891aa92018-07-13 15:07:47 +0000121 ParsedAttr::Syntax SyntaxUsed) {
David Majnemera94e7b62015-08-25 16:44:38 +0000122 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000123 // for GNU attributes, and attributes using the double square bracket syntax.
Aaron Ballmanac77dcd2018-11-09 19:37:18 +0000124 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("__") &&
David Majnemera94e7b62015-08-25 16:44:38 +0000130 AttrName.endswith("__"))
131 AttrName = AttrName.slice(2, AttrName.size() - 2);
132
133 return AttrName;
134}
135
Erich Keanee891aa92018-07-13 15:07:47 +0000136ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
137 const IdentifierInfo *ScopeName,
138 Syntax SyntaxUsed) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000139 StringRef AttrName = Name->getName();
Chris Lattnerf18c7432008-02-20 23:14:47 +0000140
Aaron Ballmanc6988092013-12-11 22:27:44 +0000141 SmallString<64> FullName;
Richard Smith84837d52012-05-03 18:27:39 +0000142 if (ScopeName)
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000143 FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000144
David Majnemera94e7b62015-08-25 16:44:38 +0000145 AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000146
Alexis Hunta0e54d42012-06-18 16:13:52 +0000147 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
148 // unscoped.
Aaron Ballman606093a2017-10-15 15:01:42 +0000149 if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000150 FullName += "::";
151 FullName += AttrName;
Richard Smith84837d52012-05-03 18:27:39 +0000152
Aaron Ballman09e98ff2014-01-13 21:42:39 +0000153 return ::getAttrKind(FullName, SyntaxUsed);
Chris Lattnerf18c7432008-02-20 23:14:47 +0000154}
Michael Han99315932013-01-24 16:46:58 +0000155
Erich Keanee891aa92018-07-13 15:07:47 +0000156unsigned ParsedAttr::getAttributeSpellingListIndex() const {
Michael Han99315932013-01-24 16:46:58 +0000157 // Both variables will be used in tablegen generated
158 // attribute spell list index matching code.
Aaron Ballmanad672ff2018-10-24 12:26:23 +0000159 auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed);
160 StringRef Scope =
161 ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : "";
162 StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax);
Michael Han99315932013-01-24 16:46:58 +0000163
164#include "clang/Sema/AttrSpellingListIndex.inc"
165
166}
167
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000168struct ParsedAttrInfo {
169 unsigned NumArgs : 4;
170 unsigned OptArgs : 4;
171 unsigned HasCustomParsing : 1;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000172 unsigned IsTargetSpecific : 1;
173 unsigned IsType : 1;
Richard Smith4f902c72016-03-08 00:32:55 +0000174 unsigned IsStmt : 1;
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000175 unsigned IsKnownToGCC : 1;
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000176 unsigned IsSupportedByPragmaAttribute : 1;
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000177
Erich Keanee891aa92018-07-13 15:07:47 +0000178 bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
179 bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
Bob Wilson7c730832015-07-20 22:57:31 +0000180 bool (*ExistsInTarget)(const TargetInfo &Target);
Erich Keanee891aa92018-07-13 15:07:47 +0000181 unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000182 void (*GetPragmaAttributeMatchRules)(
183 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
184 const LangOptions &LangOpts);
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000185};
186
187namespace {
Eugene Zelenko711964d2018-02-20 02:16:28 +0000188
189#include "clang/Sema/AttrParsedAttrImpl.inc"
190
191} // namespace
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000192
Erich Keanee891aa92018-07-13 15:07:47 +0000193static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000194 return AttrInfoMap[A.getKind()];
195}
196
Erich Keanee891aa92018-07-13 15:07:47 +0000197unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000198
Erich Keanee891aa92018-07-13 15:07:47 +0000199unsigned ParsedAttr::getMaxArgs() const {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000200 return getMinArgs() + getInfo(*this).OptArgs;
201}
202
Erich Keanee891aa92018-07-13 15:07:47 +0000203bool ParsedAttr::hasCustomParsing() const {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000204 return getInfo(*this).HasCustomParsing;
205}
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000206
Erich Keanee891aa92018-07-13 15:07:47 +0000207bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000208 return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
209}
Aaron Ballman3aff6332013-12-02 19:30:36 +0000210
Erich Keanee891aa92018-07-13 15:07:47 +0000211bool ParsedAttr::appliesToDecl(const Decl *D,
212 attr::SubjectMatchRule MatchRule) const {
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000213 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
214}
215
Erich Keanee891aa92018-07-13 15:07:47 +0000216void ParsedAttr::getMatchRules(
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000217 const LangOptions &LangOpts,
218 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
219 const {
220 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
221}
222
Erich Keanee891aa92018-07-13 15:07:47 +0000223bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
Aaron Ballman3aff6332013-12-02 19:30:36 +0000224 return getInfo(*this).DiagLangOpts(S, *this);
225}
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000226
Erich Keanee891aa92018-07-13 15:07:47 +0000227bool ParsedAttr::isTargetSpecificAttr() const {
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000228 return getInfo(*this).IsTargetSpecific;
229}
230
Erich Keanee891aa92018-07-13 15:07:47 +0000231bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000232
Erich Keanee891aa92018-07-13 15:07:47 +0000233bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
Richard Smith4f902c72016-03-08 00:32:55 +0000234
Erich Keanee891aa92018-07-13 15:07:47 +0000235bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
Bob Wilson7c730832015-07-20 22:57:31 +0000236 return getInfo(*this).ExistsInTarget(Target);
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000237}
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000238
Erich Keanee891aa92018-07-13 15:07:47 +0000239bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000240
Erich Keanee891aa92018-07-13 15:07:47 +0000241bool ParsedAttr::isSupportedByPragmaAttribute() const {
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000242 return getInfo(*this).IsSupportedByPragmaAttribute;
243}
244
Erich Keanee891aa92018-07-13 15:07:47 +0000245unsigned ParsedAttr::getSemanticSpelling() const {
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000246 return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
247}
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000248
Erich Keanee891aa92018-07-13 15:07:47 +0000249bool ParsedAttr::hasVariadicArg() const {
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000250 // 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}