Attr.h revision 194179
1//===--- Attr.h - Classes for representing expressions ----------*- 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 <cassert>
18#include <cstring>
19#include <string>
20#include <algorithm>
21
22namespace clang {
23  class ASTContext;
24}
25
26
27// Defined in ASTContext.h
28void *operator new(size_t Bytes, clang::ASTContext &C,
29                   size_t Alignment = 16) throw ();
30
31// It is good practice to pair new/delete operators.  Also, MSVC gives many
32// warnings if a matching delete overload is not declared, even though the
33// throw() spec guarantees it will not be implicitly called.
34void operator delete(void *Ptr, clang::ASTContext &C, size_t)
35              throw ();
36
37namespace clang {
38
39/// Attr - This represents one attribute.
40class Attr {
41public:
42  enum Kind {
43    Alias,
44    Aligned,
45    AlwaysInline,
46    AnalyzerNoReturn, // Clang-specific.
47    Annotate,
48    AsmLabel, // Represent GCC asm label extension.
49    Blocks,
50    Cleanup,
51    Const,
52    Constructor,
53    DLLExport,
54    DLLImport,
55    Deprecated,
56    Destructor,
57    FastCall,
58    Format,
59    FormatArg,
60    GNUInline,
61    IBOutletKind, // Clang-specific.  Use "Kind" suffix to not conflict with
62    NoReturn,
63    NoThrow,
64    Nodebug,
65    Noinline,
66    NonNull,
67    ObjCException,
68    ObjCNSObject,
69    CFReturnsRetained,   // Clang/Checker-specific.
70    NSReturnsRetained,   // Clang/Checker-specific.
71    Overloadable, // Clang-specific
72    Packed,
73    Pure,
74    Regparm,
75    Section,
76    Sentinel,
77    StdCall,
78    TransparentUnion,
79    Unavailable,
80    Unused,
81    Used,
82    Visibility,
83    WarnUnusedResult,
84    Weak,
85    WeakImport
86  };
87
88private:
89  Attr *Next;
90  Kind AttrKind;
91  bool Inherited : 1;
92
93protected:
94  void* operator new(size_t bytes) throw() {
95    assert(0 && "Attrs cannot be allocated with regular 'new'.");
96    return 0;
97  }
98  void operator delete(void* data) throw() {
99    assert(0 && "Attrs cannot be released with regular 'delete'.");
100  }
101
102protected:
103  Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
104  virtual ~Attr() {
105    assert(Next == 0 && "Destroy didn't work");
106  }
107public:
108
109  void Destroy(ASTContext &C);
110
111  /// \brief Whether this attribute should be merged to new
112  /// declarations.
113  virtual bool isMerged() const { return true; }
114
115  Kind getKind() const { return AttrKind; }
116
117  Attr *getNext() { return Next; }
118  const Attr *getNext() const { return Next; }
119  void setNext(Attr *next) { Next = next; }
120
121  bool isInherited() const { return Inherited; }
122  void setInherited(bool value) { Inherited = value; }
123
124  void addAttr(Attr *attr) {
125    assert((attr != 0) && "addAttr(): attr is null");
126
127    // FIXME: This doesn't preserve the order in any way.
128    attr->Next = Next;
129    Next = attr;
130  }
131
132  // Clone this attribute.
133  virtual Attr* clone(ASTContext &C) const = 0;
134
135  // Implement isa/cast/dyncast/etc.
136  static bool classof(const Attr *) { return true; }
137};
138
139#define DEF_SIMPLE_ATTR(ATTR)                                           \
140class ATTR##Attr : public Attr {                                        \
141public:                                                                 \
142  ATTR##Attr() : Attr(ATTR) {}                                          \
143  virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\
144  static bool classof(const Attr *A) { return A->getKind() == ATTR; }   \
145  static bool classof(const ATTR##Attr *A) { return true; }             \
146}
147
148class PackedAttr : public Attr {
149  unsigned Alignment;
150
151public:
152  PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {}
153
154  /// getAlignment - The specified alignment in bits.
155  unsigned getAlignment() const { return Alignment; }
156
157  virtual Attr* clone(ASTContext &C) const {
158    return ::new (C) PackedAttr(Alignment);
159  }
160
161  // Implement isa/cast/dyncast/etc.
162  static bool classof(const Attr *A) {
163    return A->getKind() == Packed;
164  }
165  static bool classof(const PackedAttr *A) { return true; }
166};
167
168class AlignedAttr : public Attr {
169  unsigned Alignment;
170public:
171  AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
172
173  /// getAlignment - The specified alignment in bits.
174  unsigned getAlignment() const { return Alignment; }
175
176  virtual Attr* clone(ASTContext &C) const { return ::new (C) AlignedAttr(Alignment); }
177
178  // Implement isa/cast/dyncast/etc.
179  static bool classof(const Attr *A) {
180    return A->getKind() == Aligned;
181  }
182  static bool classof(const AlignedAttr *A) { return true; }
183};
184
185class AnnotateAttr : public Attr {
186  std::string Annotation;
187public:
188  AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {}
189
190  const std::string& getAnnotation() const { return Annotation; }
191
192  virtual Attr* clone(ASTContext &C) const { return ::new (C) AnnotateAttr(Annotation); }
193
194  // Implement isa/cast/dyncast/etc.
195  static bool classof(const Attr *A) {
196    return A->getKind() == Annotate;
197  }
198  static bool classof(const AnnotateAttr *A) { return true; }
199};
200
201class AsmLabelAttr : public Attr {
202  std::string Label;
203public:
204  AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {}
205
206  const std::string& getLabel() const { return Label; }
207
208  virtual Attr* clone(ASTContext &C) const { return ::new (C) AsmLabelAttr(Label); }
209
210  // Implement isa/cast/dyncast/etc.
211  static bool classof(const Attr *A) {
212    return A->getKind() == AsmLabel;
213  }
214  static bool classof(const AsmLabelAttr *A) { return true; }
215};
216
217DEF_SIMPLE_ATTR(AlwaysInline);
218
219class AliasAttr : public Attr {
220  std::string Aliasee;
221public:
222  AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {}
223
224  const std::string& getAliasee() const { return Aliasee; }
225
226  virtual Attr *clone(ASTContext &C) const { return ::new (C) AliasAttr(Aliasee); }
227
228  // Implement isa/cast/dyncast/etc.
229  static bool classof(const Attr *A) { return A->getKind() == Alias; }
230  static bool classof(const AliasAttr *A) { return true; }
231};
232
233class ConstructorAttr : public Attr {
234  int priority;
235public:
236  ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
237
238  int getPriority() const { return priority; }
239
240  virtual Attr *clone(ASTContext &C) const { return ::new (C) ConstructorAttr(priority); }
241
242  // Implement isa/cast/dyncast/etc.
243  static bool classof(const Attr *A) { return A->getKind() == Constructor; }
244  static bool classof(const ConstructorAttr *A) { return true; }
245};
246
247class DestructorAttr : public Attr {
248  int priority;
249public:
250  DestructorAttr(int p) : Attr(Destructor), priority(p) {}
251
252  int getPriority() const { return priority; }
253
254  virtual Attr *clone(ASTContext &C) const { return ::new (C) DestructorAttr(priority); }
255
256  // Implement isa/cast/dyncast/etc.
257  static bool classof(const Attr *A) { return A->getKind() == Destructor; }
258  static bool classof(const DestructorAttr *A) { return true; }
259};
260
261class GNUInlineAttr : public Attr {
262public:
263  GNUInlineAttr() : Attr(GNUInline) {}
264
265  virtual Attr *clone(ASTContext &C) const { return ::new (C) GNUInlineAttr; }
266
267  // Implement isa/cast/dyncast/etc.
268  static bool classof(const Attr *A) {
269    return A->getKind() == GNUInline;
270  }
271  static bool classof(const GNUInlineAttr *A) { return true; }
272};
273
274class IBOutletAttr : public Attr {
275public:
276  IBOutletAttr() : Attr(IBOutletKind) {}
277
278  virtual Attr *clone(ASTContext &C) const { return ::new (C) IBOutletAttr; }
279
280  // Implement isa/cast/dyncast/etc.
281  static bool classof(const Attr *A) {
282    return A->getKind() == IBOutletKind;
283  }
284  static bool classof(const IBOutletAttr *A) { return true; }
285};
286
287DEF_SIMPLE_ATTR(NoReturn);
288DEF_SIMPLE_ATTR(AnalyzerNoReturn);
289DEF_SIMPLE_ATTR(Deprecated);
290
291class SectionAttr : public Attr {
292  std::string Name;
293public:
294  SectionAttr(const std::string &N) : Attr(Section), Name(N) {}
295
296  const std::string& getName() const { return Name; }
297
298  virtual Attr *clone(ASTContext &C) const { return ::new (C) SectionAttr(Name); }
299
300  // Implement isa/cast/dyncast/etc.
301  static bool classof(const Attr *A) {
302    return A->getKind() == Section;
303  }
304  static bool classof(const SectionAttr *A) { return true; }
305};
306
307DEF_SIMPLE_ATTR(Unavailable);
308DEF_SIMPLE_ATTR(Unused);
309DEF_SIMPLE_ATTR(Used);
310DEF_SIMPLE_ATTR(Weak);
311DEF_SIMPLE_ATTR(WeakImport);
312DEF_SIMPLE_ATTR(NoThrow);
313DEF_SIMPLE_ATTR(Const);
314DEF_SIMPLE_ATTR(Pure);
315
316class NonNullAttr : public Attr {
317  unsigned* ArgNums;
318  unsigned Size;
319public:
320  NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
321    ArgNums(0), Size(0) {
322
323    if (size == 0) return;
324    assert(arg_nums);
325    ArgNums = new unsigned[size];
326    Size = size;
327    memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
328  }
329
330  virtual ~NonNullAttr() {
331    delete [] ArgNums;
332  }
333
334  typedef const unsigned *iterator;
335  iterator begin() const { return ArgNums; }
336  iterator end() const { return ArgNums + Size; }
337  unsigned size() const { return Size; }
338
339  bool isNonNull(unsigned arg) const {
340    return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
341  }
342
343  virtual Attr *clone(ASTContext &C) const { return ::new (C) NonNullAttr(ArgNums, Size); }
344
345  static bool classof(const Attr *A) { return A->getKind() == NonNull; }
346  static bool classof(const NonNullAttr *A) { return true; }
347};
348
349class FormatAttr : public Attr {
350  std::string Type;
351  int formatIdx, firstArg;
352public:
353  FormatAttr(const std::string &type, int idx, int first) : Attr(Format),
354             Type(type), formatIdx(idx), firstArg(first) {}
355
356  const std::string& getType() const { return Type; }
357  void setType(const std::string &type) { Type = type; }
358  int getFormatIdx() const { return formatIdx; }
359  int getFirstArg() const { return firstArg; }
360
361  virtual Attr *clone(ASTContext &C) const {
362    return ::new (C) FormatAttr(Type, formatIdx, firstArg);
363  }
364
365  // Implement isa/cast/dyncast/etc.
366  static bool classof(const Attr *A) { return A->getKind() == Format; }
367  static bool classof(const FormatAttr *A) { return true; }
368};
369
370class FormatArgAttr : public Attr {
371  int formatIdx;
372public:
373  FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {}
374  int getFormatIdx() const { return formatIdx; }
375
376  virtual Attr *clone(ASTContext &C) const {
377    return ::new (C) FormatArgAttr(formatIdx);
378  }
379
380  // Implement isa/cast/dyncast/etc.
381  static bool classof(const Attr *A) { return A->getKind() == FormatArg; }
382  static bool classof(const FormatArgAttr *A) { return true; }
383};
384
385class SentinelAttr : public Attr {
386  int sentinel, NullPos;
387public:
388  SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel),
389               sentinel(sentinel_val), NullPos(nullPos) {}
390  int getSentinel() const { return sentinel; }
391  int getNullPos() const { return NullPos; }
392
393  virtual Attr *clone(ASTContext &C) const {
394    return ::new (C) SentinelAttr(sentinel, NullPos);
395  }
396
397  // Implement isa/cast/dyncast/etc.
398  static bool classof(const Attr *A) { return A->getKind() == Sentinel; }
399  static bool classof(const SentinelAttr *A) { return true; }
400};
401
402class VisibilityAttr : public Attr {
403public:
404  /// @brief An enumeration for the kinds of visibility of symbols.
405  enum VisibilityTypes {
406    DefaultVisibility = 0,
407    HiddenVisibility,
408    ProtectedVisibility
409  };
410private:
411  VisibilityTypes VisibilityType;
412public:
413  VisibilityAttr(VisibilityTypes v) : Attr(Visibility),
414                 VisibilityType(v) {}
415
416  VisibilityTypes getVisibility() const { return VisibilityType; }
417
418  virtual Attr *clone(ASTContext &C) const { return ::new (C) VisibilityAttr(VisibilityType); }
419
420  // Implement isa/cast/dyncast/etc.
421  static bool classof(const Attr *A) { return A->getKind() == Visibility; }
422  static bool classof(const VisibilityAttr *A) { return true; }
423};
424
425DEF_SIMPLE_ATTR(DLLImport);
426DEF_SIMPLE_ATTR(DLLExport);
427DEF_SIMPLE_ATTR(FastCall);
428DEF_SIMPLE_ATTR(StdCall);
429DEF_SIMPLE_ATTR(TransparentUnion);
430DEF_SIMPLE_ATTR(ObjCNSObject);
431DEF_SIMPLE_ATTR(ObjCException);
432
433class OverloadableAttr : public Attr {
434public:
435  OverloadableAttr() : Attr(Overloadable) { }
436
437  virtual bool isMerged() const { return false; }
438
439  virtual Attr *clone(ASTContext &C) const {
440    return ::new (C) OverloadableAttr;
441  }
442
443  static bool classof(const Attr *A) { return A->getKind() == Overloadable; }
444  static bool classof(const OverloadableAttr *) { return true; }
445};
446
447class BlocksAttr : public Attr {
448public:
449  enum BlocksAttrTypes {
450    ByRef = 0
451  };
452private:
453  BlocksAttrTypes BlocksAttrType;
454public:
455  BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {}
456
457  BlocksAttrTypes getType() const { return BlocksAttrType; }
458
459  virtual Attr *clone(ASTContext &C) const { return ::new (C) BlocksAttr(BlocksAttrType); }
460
461  // Implement isa/cast/dyncast/etc.
462  static bool classof(const Attr *A) { return A->getKind() == Blocks; }
463  static bool classof(const BlocksAttr *A) { return true; }
464};
465
466class FunctionDecl;
467
468class CleanupAttr : public Attr {
469  FunctionDecl *FD;
470
471public:
472  CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
473
474  const FunctionDecl *getFunctionDecl() const { return FD; }
475
476  virtual Attr *clone(ASTContext &C) const { return ::new (C) CleanupAttr(FD); }
477
478  // Implement isa/cast/dyncast/etc.
479  static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
480  static bool classof(const CleanupAttr *A) { return true; }
481};
482
483DEF_SIMPLE_ATTR(Nodebug);
484DEF_SIMPLE_ATTR(WarnUnusedResult);
485DEF_SIMPLE_ATTR(Noinline);
486
487class RegparmAttr : public Attr {
488  unsigned NumParams;
489
490public:
491  RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {}
492
493  unsigned getNumParams() const { return NumParams; }
494
495  virtual Attr *clone(ASTContext &C) const {
496    return ::new (C) RegparmAttr(NumParams);
497  }
498
499  // Implement isa/cast/dyncast/etc.
500  static bool classof(const Attr *A) { return A->getKind() == Regparm; }
501  static bool classof(const RegparmAttr *A) { return true; }
502};
503
504// Checker-specific attributes.
505DEF_SIMPLE_ATTR(CFReturnsRetained);
506DEF_SIMPLE_ATTR(NSReturnsRetained);
507
508#undef DEF_SIMPLE_ATTR
509
510}  // end namespace clang
511
512#endif
513