1//===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
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 Attr interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_ATTR_H
15#define LLVM_CLANG_AST_ATTR_H
16
17#include "clang/AST/AttrIterator.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/Type.h"
21#include "clang/Basic/AttrKinds.h"
22#include "clang/Basic/LLVM.h"
23#include "clang/Basic/OpenMPKinds.h"
24#include "clang/Basic/Sanitizers.h"
25#include "clang/Basic/SourceLocation.h"
26#include "clang/Basic/VersionTuple.h"
27#include "llvm/ADT/StringSwitch.h"
28#include "llvm/Support/ErrorHandling.h"
29#include "llvm/Support/raw_ostream.h"
30#include <algorithm>
31#include <cassert>
32
33namespace clang {
34  class ASTContext;
35  class IdentifierInfo;
36  class ObjCInterfaceDecl;
37  class Expr;
38  class QualType;
39  class FunctionDecl;
40  class TypeSourceInfo;
41
42/// Attr - This represents one attribute.
43class Attr {
44private:
45  SourceRange Range;
46  unsigned AttrKind : 16;
47
48protected:
49  /// An index into the spelling list of an
50  /// attribute defined in Attr.td file.
51  unsigned SpellingListIndex : 4;
52  unsigned Inherited : 1;
53  unsigned IsPackExpansion : 1;
54  unsigned Implicit : 1;
55  unsigned IsLateParsed : 1;
56  unsigned DuplicatesAllowed : 1;
57
58  void *operator new(size_t bytes) noexcept {
59    llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
60  }
61  void operator delete(void *data) noexcept {
62    llvm_unreachable("Attrs cannot be released with regular 'delete'.");
63  }
64
65public:
66  // Forward so that the regular new and delete do not hide global ones.
67  void *operator new(size_t Bytes, ASTContext &C,
68                     size_t Alignment = 8) noexcept {
69    return ::operator new(Bytes, C, Alignment);
70  }
71  void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
72    return ::operator delete(Ptr, C, Alignment);
73  }
74
75protected:
76  Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
77       bool IsLateParsed, bool DuplicatesAllowed)
78    : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
79      Inherited(false), IsPackExpansion(false), Implicit(false),
80      IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
81
82public:
83
84  attr::Kind getKind() const {
85    return static_cast<attr::Kind>(AttrKind);
86  }
87
88  unsigned getSpellingListIndex() const { return SpellingListIndex; }
89  const char *getSpelling() const;
90
91  SourceLocation getLocation() const { return Range.getBegin(); }
92  SourceRange getRange() const { return Range; }
93  void setRange(SourceRange R) { Range = R; }
94
95  bool isInherited() const { return Inherited; }
96
97  /// \brief Returns true if the attribute has been implicitly created instead
98  /// of explicitly written by the user.
99  bool isImplicit() const { return Implicit; }
100  void setImplicit(bool I) { Implicit = I; }
101
102  void setPackExpansion(bool PE) { IsPackExpansion = PE; }
103  bool isPackExpansion() const { return IsPackExpansion; }
104
105  // Clone this attribute.
106  Attr *clone(ASTContext &C) const;
107
108  bool isLateParsed() const { return IsLateParsed; }
109
110  // Pretty print this attribute.
111  void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
112
113  /// \brief By default, attributes cannot be duplicated when being merged;
114  /// however, an attribute can override this. Returns true if the attribute
115  /// can be duplicated when merging.
116  bool duplicatesAllowed() const { return DuplicatesAllowed; }
117};
118
119class StmtAttr : public Attr {
120protected:
121  StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
122                  bool IsLateParsed, bool DuplicatesAllowed)
123      : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
124
125public:
126  static bool classof(const Attr *A) {
127    return A->getKind() >= attr::FirstStmtAttr &&
128           A->getKind() <= attr::LastStmtAttr;
129  }
130};
131
132class InheritableAttr : public Attr {
133protected:
134  InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
135                  bool IsLateParsed, bool DuplicatesAllowed)
136      : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
137
138public:
139  void setInherited(bool I) { Inherited = I; }
140
141  // Implement isa/cast/dyncast/etc.
142  static bool classof(const Attr *A) {
143    return A->getKind() >= attr::FirstInheritableAttr &&
144           A->getKind() <= attr::LastInheritableAttr;
145  }
146};
147
148class InheritableParamAttr : public InheritableAttr {
149protected:
150  InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
151                       bool IsLateParsed, bool DuplicatesAllowed)
152      : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
153                        DuplicatesAllowed) {}
154
155public:
156  // Implement isa/cast/dyncast/etc.
157  static bool classof(const Attr *A) {
158    return A->getKind() >= attr::FirstInheritableParamAttr &&
159           A->getKind() <= attr::LastInheritableParamAttr;
160  }
161};
162
163/// A parameter attribute which changes the argument-passing ABI rule
164/// for the parameter.
165class ParameterABIAttr : public InheritableParamAttr {
166protected:
167  ParameterABIAttr(attr::Kind AK, SourceRange R,
168                   unsigned SpellingListIndex, bool IsLateParsed,
169                   bool DuplicatesAllowed)
170    : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed,
171                           DuplicatesAllowed) {}
172
173public:
174  ParameterABI getABI() const {
175    switch (getKind()) {
176    case attr::SwiftContext:
177      return ParameterABI::SwiftContext;
178    case attr::SwiftErrorResult:
179      return ParameterABI::SwiftErrorResult;
180    case attr::SwiftIndirectResult:
181      return ParameterABI::SwiftIndirectResult;
182    default:
183      llvm_unreachable("bad parameter ABI attribute kind");
184    }
185  }
186
187  static bool classof(const Attr *A) {
188    return A->getKind() >= attr::FirstParameterABIAttr &&
189           A->getKind() <= attr::LastParameterABIAttr;
190   }
191};
192
193#include "clang/AST/Attrs.inc"
194
195inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
196                                           const Attr *At) {
197  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At),
198                  DiagnosticsEngine::ak_attr);
199  return DB;
200}
201
202inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
203                                           const Attr *At) {
204  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At),
205                  DiagnosticsEngine::ak_attr);
206  return PD;
207}
208}  // end namespace clang
209
210#endif
211