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