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