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