SemaDeclAttr.cpp revision 52a425b852e4641d46073a697a48a457c8f655e2
1//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
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 implements decl-related attribute processing.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/DeclObjC.h"
17#include "clang/AST/Expr.h"
18#include "clang/Basic/DiagnosticSema.h"
19#include "clang/Basic/TargetInfo.h"
20#include "clang/Parse/DeclSpec.h"
21#include <llvm/ADT/StringExtras.h>
22using namespace clang;
23
24//===----------------------------------------------------------------------===//
25//  Helper functions
26//===----------------------------------------------------------------------===//
27
28static const FunctionType *getFunctionType(Decl *d) {
29  QualType Ty;
30  if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
31    Ty = decl->getType();
32  else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
33    Ty = decl->getType();
34  else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
35    Ty = decl->getUnderlyingType();
36  else
37    return 0;
38
39  if (Ty->isFunctionPointerType())
40    Ty = Ty->getAsPointerType()->getPointeeType();
41
42  return Ty->getAsFunctionType();
43}
44
45// FIXME: We should provide an abstraction around a method or function
46// to provide the following bits of information.
47
48/// isFunctionOrMethod - Return true if the given decl has function
49/// type (function or function-typed variable) or an Objective-C
50/// method.
51static bool isFunctionOrMethod(Decl *d) {
52  return getFunctionType(d) || isa<ObjCMethodDecl>(d);
53}
54
55/// hasFunctionProto - Return true if the given decl has a argument
56/// information. This decl should have already passed
57/// isFunctionOrMethod.
58static bool hasFunctionProto(Decl *d) {
59  if (const FunctionType *FnTy = getFunctionType(d)) {
60    return isa<FunctionTypeProto>(FnTy);
61  } else {
62    assert(isa<ObjCMethodDecl>(d));
63    return true;
64  }
65}
66
67/// getFunctionOrMethodNumArgs - Return number of function or method
68/// arguments. It is an error to call this on a K&R function (use
69/// hasFunctionProto first).
70static unsigned getFunctionOrMethodNumArgs(Decl *d) {
71  if (const FunctionType *FnTy = getFunctionType(d)) {
72    const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
73    return proto->getNumArgs();
74  } else {
75    return cast<ObjCMethodDecl>(d)->getNumParams();
76  }
77}
78
79static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) {
80  if (const FunctionType *FnTy = getFunctionType(d)) {
81    const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
82    return proto->getArgType(Idx);
83  } else {
84    return cast<ObjCMethodDecl>(d)->getParamDecl(Idx)->getType();
85  }
86}
87
88static bool isFunctionOrMethodVariadic(Decl *d) {
89  if (const FunctionType *FnTy = getFunctionType(d)) {
90    const FunctionTypeProto *proto = cast<FunctionTypeProto>(FnTy);
91    return proto->isVariadic();
92  } else {
93    return cast<ObjCMethodDecl>(d)->isVariadic();
94  }
95}
96
97static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
98  const PointerType *PT = T->getAsPointerType();
99  if (!PT)
100    return false;
101
102  const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAsObjCInterfaceType();
103  if (!ClsT)
104    return false;
105
106  IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
107
108  // FIXME: Should we walk the chain of classes?
109  return ClsName == &Ctx.Idents.get("NSString") ||
110         ClsName == &Ctx.Idents.get("NSMutableString");
111}
112
113static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
114  const PointerType *PT = T->getAsPointerType();
115  if (!PT)
116    return false;
117
118  const RecordType *RT = PT->getPointeeType()->getAsRecordType();
119  if (!RT)
120    return false;
121
122  const RecordDecl *RD = RT->getDecl();
123  if (RD->getTagKind() != TagDecl::TK_struct)
124    return false;
125
126  return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
127}
128
129//===----------------------------------------------------------------------===//
130// Attribute Implementations
131//===----------------------------------------------------------------------===//
132
133// FIXME: All this manual attribute parsing code is gross. At the
134// least add some helper functions to check most argument patterns (#
135// and types of args).
136
137static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
138                                    Sema &S) {
139  TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
140  if (tDecl == 0) {
141    S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
142    return;
143  }
144
145  QualType curType = tDecl->getUnderlyingType();
146  // check the attribute arguments.
147  if (Attr.getNumArgs() != 1) {
148    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
149    return;
150  }
151  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
152  llvm::APSInt vecSize(32);
153  if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
154    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
155      << "ext_vector_type" << sizeExpr->getSourceRange();
156    return;
157  }
158  // unlike gcc's vector_size attribute, we do not allow vectors to be defined
159  // in conjunction with complex types (pointers, arrays, functions, etc.).
160  if (!curType->isIntegerType() && !curType->isRealFloatingType()) {
161    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType;
162    return;
163  }
164  // unlike gcc's vector_size attribute, the size is specified as the
165  // number of elements, not the number of bytes.
166  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
167
168  if (vectorSize == 0) {
169    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
170      << sizeExpr->getSourceRange();
171    return;
172  }
173  // Instantiate/Install the vector type, the number of elements is > 0.
174  tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
175  // Remember this typedef decl, we will need it later for diagnostics.
176  S.ExtVectorDecls.push_back(tDecl);
177}
178
179
180/// HandleVectorSizeAttribute - this attribute is only applicable to
181/// integral and float scalars, although arrays, pointers, and function
182/// return values are allowed in conjunction with this construct. Aggregates
183/// with this attribute are invalid, even if they are of the same size as a
184/// corresponding scalar.
185/// The raw attribute should contain precisely 1 argument, the vector size
186/// for the variable, measured in bytes. If curType and rawAttr are well
187/// formed, this routine will return a new vector type.
188static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
189  QualType CurType;
190  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
191    CurType = VD->getType();
192  else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
193    CurType = TD->getUnderlyingType();
194  else {
195    S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
196      << "vector_size" << SourceRange(Attr.getLoc(), Attr.getLoc());
197    return;
198  }
199
200  // Check the attribute arugments.
201  if (Attr.getNumArgs() != 1) {
202    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
203    return;
204  }
205  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
206  llvm::APSInt vecSize(32);
207  if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
208    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
209      << "vector_size" << sizeExpr->getSourceRange();
210    return;
211  }
212  // navigate to the base type - we need to provide for vector pointers,
213  // vector arrays, and functions returning vectors.
214  if (CurType->isPointerType() || CurType->isArrayType() ||
215      CurType->isFunctionType()) {
216    assert(0 && "HandleVector(): Complex type construction unimplemented");
217    /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
218     do {
219     if (PointerType *PT = dyn_cast<PointerType>(canonType))
220     canonType = PT->getPointeeType().getTypePtr();
221     else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
222     canonType = AT->getElementType().getTypePtr();
223     else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
224     canonType = FT->getResultType().getTypePtr();
225     } while (canonType->isPointerType() || canonType->isArrayType() ||
226     canonType->isFunctionType());
227     */
228  }
229  // the base type must be integer or float.
230  if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
231    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
232    return;
233  }
234  unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
235  // vecSize is specified in bytes - convert to bits.
236  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
237
238  // the vector size needs to be an integral multiple of the type size.
239  if (vectorSize % typeSize) {
240    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
241      << sizeExpr->getSourceRange();
242    return;
243  }
244  if (vectorSize == 0) {
245    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
246      << sizeExpr->getSourceRange();
247    return;
248  }
249
250  // Success! Instantiate the vector type, the number of elements is > 0, and
251  // not required to be a power of 2, unlike GCC.
252  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
253
254  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
255    VD->setType(CurType);
256  else
257    cast<TypedefDecl>(D)->setUnderlyingType(CurType);
258}
259
260static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
261  // check the attribute arguments.
262  if (Attr.getNumArgs() > 0) {
263    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
264    return;
265  }
266
267  if (TagDecl *TD = dyn_cast<TagDecl>(d))
268    TD->addAttr(new PackedAttr(1));
269  else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
270    // If the alignment is less than or equal to 8 bits, the packed attribute
271    // has no effect.
272    if (!FD->getType()->isIncompleteType() &&
273        S.Context.getTypeAlign(FD->getType()) <= 8)
274      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
275        << Attr.getName() << FD->getType();
276    else
277      FD->addAttr(new PackedAttr(1));
278  } else
279    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
280}
281
282static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
283  // check the attribute arguments.
284  if (Attr.getNumArgs() > 0) {
285    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
286    return;
287  }
288
289  // The IBOutlet attribute only applies to instance variables of Objective-C
290  // classes.
291  if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
292    ID->addAttr(new IBOutletAttr());
293  else
294    S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
295}
296
297static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
298  // GCC ignores the nonnull attribute on K&R style function
299  // prototypes, so we ignore it as well
300  if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
301    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
302      << "nonnull" << "function";
303    return;
304  }
305
306  unsigned NumArgs = getFunctionOrMethodNumArgs(d);
307
308  // The nonnull attribute only applies to pointers.
309  llvm::SmallVector<unsigned, 10> NonNullArgs;
310
311  for (AttributeList::arg_iterator I=Attr.arg_begin(),
312                                   E=Attr.arg_end(); I!=E; ++I) {
313
314
315    // The argument must be an integer constant expression.
316    Expr *Ex = static_cast<Expr *>(*I);
317    llvm::APSInt ArgNum(32);
318    if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
319      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
320        << "nonnull" << Ex->getSourceRange();
321      return;
322    }
323
324    unsigned x = (unsigned) ArgNum.getZExtValue();
325
326    if (x < 1 || x > NumArgs) {
327      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
328       << "nonnull" << I.getArgNum() << Ex->getSourceRange();
329      return;
330    }
331
332    --x;
333
334    // Is the function argument a pointer type?
335    QualType T = getFunctionOrMethodArgType(d, x);
336    if (!T->isPointerType() && !T->isBlockPointerType()) {
337      // FIXME: Should also highlight argument in decl.
338      S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only)
339        << "nonnull" << Ex->getSourceRange();
340      continue;
341    }
342
343    NonNullArgs.push_back(x);
344  }
345
346  // If no arguments were specified to __attribute__((nonnull)) then all
347  // pointer arguments have a nonnull attribute.
348  if (NonNullArgs.empty()) {
349    for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
350      QualType T = getFunctionOrMethodArgType(d, I);
351      if (T->isPointerType() || T->isBlockPointerType())
352        NonNullArgs.push_back(I);
353    }
354
355    if (NonNullArgs.empty()) {
356      S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
357      return;
358    }
359  }
360
361  unsigned* start = &NonNullArgs[0];
362  unsigned size = NonNullArgs.size();
363  std::sort(start, start + size);
364  d->addAttr(new NonNullAttr(start, size));
365}
366
367static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
368  // check the attribute arguments.
369  if (Attr.getNumArgs() != 1) {
370    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
371    return;
372  }
373
374  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
375  Arg = Arg->IgnoreParenCasts();
376  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
377
378  if (Str == 0 || Str->isWide()) {
379    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
380      << "alias" << 1;
381    return;
382  }
383
384  const char *Alias = Str->getStrData();
385  unsigned AliasLen = Str->getByteLength();
386
387  // FIXME: check if target symbol exists in current file
388
389  d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
390}
391
392static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
393                                   Sema &S) {
394  // check the attribute arguments.
395  if (Attr.getNumArgs() != 0) {
396    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
397    return;
398  }
399
400  d->addAttr(new AlwaysInlineAttr());
401}
402
403static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
404  // check the attribute arguments.
405  if (Attr.getNumArgs() != 0) {
406    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
407    return;
408  }
409
410  if (!isFunctionOrMethod(d)) {
411    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
412      << "noreturn" << "function";
413    return;
414  }
415
416  d->addAttr(new NoReturnAttr());
417}
418
419static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
420  // check the attribute arguments.
421  if (Attr.getNumArgs() != 0) {
422    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
423    return;
424  }
425
426  if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
427    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
428      << "unused" << "variable and function";
429    return;
430  }
431
432  d->addAttr(new UnusedAttr());
433}
434
435static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
436  // check the attribute arguments.
437  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
438    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
439      << "0 or 1";
440    return;
441  }
442
443  int priority = 65535; // FIXME: Do not hardcode such constants.
444  if (Attr.getNumArgs() > 0) {
445    Expr *E = static_cast<Expr *>(Attr.getArg(0));
446    llvm::APSInt Idx(32);
447    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
448      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
449        << "constructor" << 1 << E->getSourceRange();
450      return;
451    }
452    priority = Idx.getZExtValue();
453  }
454
455  FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
456  if (!Fn) {
457    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
458      << "constructor" << "function";
459    return;
460  }
461
462  d->addAttr(new ConstructorAttr(priority));
463}
464
465static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
466  // check the attribute arguments.
467  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
468    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
469       << "0 or 1";
470    return;
471  }
472
473  int priority = 65535; // FIXME: Do not hardcode such constants.
474  if (Attr.getNumArgs() > 0) {
475    Expr *E = static_cast<Expr *>(Attr.getArg(0));
476    llvm::APSInt Idx(32);
477    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
478      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
479        << "destructor" << 1 << E->getSourceRange();
480      return;
481    }
482    priority = Idx.getZExtValue();
483  }
484
485  if (!isa<FunctionDecl>(d)) {
486    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
487      << "destructor" << "function";
488    return;
489  }
490
491  d->addAttr(new DestructorAttr(priority));
492}
493
494static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
495  // check the attribute arguments.
496  if (Attr.getNumArgs() != 0) {
497    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
498    return;
499  }
500
501  d->addAttr(new DeprecatedAttr());
502}
503
504static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
505  // check the attribute arguments.
506  if (Attr.getNumArgs() != 0) {
507    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
508    return;
509  }
510
511  d->addAttr(new UnavailableAttr());
512}
513
514static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
515  // check the attribute arguments.
516  if (Attr.getNumArgs() != 1) {
517    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
518    return;
519  }
520
521  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
522  Arg = Arg->IgnoreParenCasts();
523  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
524
525  if (Str == 0 || Str->isWide()) {
526    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
527      << "visibility" << 1;
528    return;
529  }
530
531  const char *TypeStr = Str->getStrData();
532  unsigned TypeLen = Str->getByteLength();
533  VisibilityAttr::VisibilityTypes type;
534
535  if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
536    type = VisibilityAttr::DefaultVisibility;
537  else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
538    type = VisibilityAttr::HiddenVisibility;
539  else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
540    type = VisibilityAttr::HiddenVisibility; // FIXME
541  else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
542    type = VisibilityAttr::ProtectedVisibility;
543  else {
544    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
545    return;
546  }
547
548  d->addAttr(new VisibilityAttr(type));
549}
550
551static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
552  if (!Attr.getParameterName()) {
553    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
554      << "objc_gc" << 1;
555    return;
556  }
557
558  if (Attr.getNumArgs() != 0) {
559    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
560    return;
561  }
562
563
564  ObjCGCAttr::GCAttrTypes type;
565  if (Attr.getParameterName()->isStr("weak")) {
566    if (isa<FieldDecl>(d) && !isa<ObjCIvarDecl>(d))
567      S.Diag(Attr.getLoc(), diag::warn_attribute_weak_on_field);
568    type = ObjCGCAttr::Weak;
569  }
570  else if (Attr.getParameterName()->isStr("strong"))
571    type = ObjCGCAttr::Strong;
572  else {
573    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
574      << "objc_gc" << Attr.getParameterName();
575    return;
576  }
577
578  d->addAttr(new ObjCGCAttr(type));
579}
580
581static void HandleObjCNSObject(Decl *d, const AttributeList &Attr, Sema &S) {
582  if (Attr.getNumArgs() != 0) {
583    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
584    return;
585  }
586  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(d)) {
587    QualType T = TD->getUnderlyingType();
588    if (!T->isPointerType() ||
589        !T->getAsPointerType()->getPointeeType()->isRecordType()) {
590      S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
591      return;
592    }
593  }
594  d->addAttr(new ObjCNSObjectAttr);
595}
596
597static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
598  if (!Attr.getParameterName()) {
599    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
600      << "blocks" << 1;
601    return;
602  }
603
604  if (Attr.getNumArgs() != 0) {
605    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
606    return;
607  }
608
609  BlocksAttr::BlocksAttrTypes type;
610  if (Attr.getParameterName()->isStr("byref"))
611    type = BlocksAttr::ByRef;
612  else {
613    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
614      << "blocks" << Attr.getParameterName();
615    return;
616  }
617
618  d->addAttr(new BlocksAttr(type));
619}
620
621static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
622  // check the attribute arguments.
623  if (Attr.getNumArgs() > 2) {
624    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
625      << "0, 1 or 2";
626    return;
627  }
628
629  int sentinel = 0;
630  if (Attr.getNumArgs() > 0) {
631    Expr *E = static_cast<Expr *>(Attr.getArg(0));
632    llvm::APSInt Idx(32);
633    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
634      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
635       << "sentinel" << 1 << E->getSourceRange();
636      return;
637    }
638    sentinel = Idx.getZExtValue();
639
640    if (sentinel < 0) {
641      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
642        << E->getSourceRange();
643      return;
644    }
645  }
646
647  int nullPos = 0;
648  if (Attr.getNumArgs() > 1) {
649    Expr *E = static_cast<Expr *>(Attr.getArg(1));
650    llvm::APSInt Idx(32);
651    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
652      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
653        << "sentinel" << 2 << E->getSourceRange();
654      return;
655    }
656    nullPos = Idx.getZExtValue();
657
658    if (nullPos > 1 || nullPos < 0) {
659      // FIXME: This error message could be improved, it would be nice
660      // to say what the bounds actually are.
661      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
662        << E->getSourceRange();
663      return;
664    }
665  }
666
667  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
668    QualType FT = FD->getType();
669    if (!FT->getAsFunctionTypeProto()->isVariadic()) {
670      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
671      return;
672    }
673  } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
674    if (!MD->isVariadic()) {
675      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
676      return;
677    }
678  } else {
679    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
680      << "sentinel" << "function or method";
681    return;
682  }
683
684  // FIXME: Actually create the attribute.
685}
686
687static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
688  // check the attribute arguments.
689  if (Attr.getNumArgs() != 0) {
690    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
691    return;
692  }
693
694  d->addAttr(new WeakAttr());
695}
696
697static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
698  // check the attribute arguments.
699  if (Attr.getNumArgs() != 0) {
700    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
701    return;
702  }
703
704  // Attribute can be applied only to functions or variables.
705  if (isa<VarDecl>(d)) {
706    d->addAttr(new DLLImportAttr());
707    return;
708  }
709
710  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
711  if (!FD) {
712    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
713      << "dllimport" << "function or variable";
714    return;
715  }
716
717  // Currently, the dllimport attribute is ignored for inlined functions.
718  // Warning is emitted.
719  if (FD->isInline()) {
720    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
721    return;
722  }
723
724  // The attribute is also overridden by a subsequent declaration as dllexport.
725  // Warning is emitted.
726  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
727       nextAttr = nextAttr->getNext()) {
728    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
729      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
730      return;
731    }
732  }
733
734  if (d->getAttr<DLLExportAttr>()) {
735    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
736    return;
737  }
738
739  d->addAttr(new DLLImportAttr());
740}
741
742static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
743  // check the attribute arguments.
744  if (Attr.getNumArgs() != 0) {
745    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
746    return;
747  }
748
749  // Attribute can be applied only to functions or variables.
750  if (isa<VarDecl>(d)) {
751    d->addAttr(new DLLExportAttr());
752    return;
753  }
754
755  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
756  if (!FD) {
757    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
758      << "dllexport" << "function or variable";
759    return;
760  }
761
762  // Currently, the dllexport attribute is ignored for inlined functions,
763  // unless the -fkeep-inline-functions flag has been used. Warning is emitted;
764  if (FD->isInline()) {
765    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
766    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
767    return;
768  }
769
770  d->addAttr(new DLLExportAttr());
771}
772
773static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
774  // Attribute has no arguments.
775  if (Attr.getNumArgs() != 0) {
776    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
777    return;
778  }
779
780  // Attribute can be applied only to functions.
781  if (!isa<FunctionDecl>(d)) {
782    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
783      << "stdcall" << "function";
784    return;
785  }
786
787  // stdcall and fastcall attributes are mutually incompatible.
788  if (d->getAttr<FastCallAttr>()) {
789    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
790      << "stdcall" << "fastcall";
791    return;
792  }
793
794  d->addAttr(new StdCallAttr());
795}
796
797static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
798  // Attribute has no arguments.
799  if (Attr.getNumArgs() != 0) {
800    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
801    return;
802  }
803
804  if (!isa<FunctionDecl>(d)) {
805    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
806      << "fastcall" << "function";
807    return;
808  }
809
810  // stdcall and fastcall attributes are mutually incompatible.
811  if (d->getAttr<StdCallAttr>()) {
812    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
813      << "fastcall" << "stdcall";
814    return;
815  }
816
817  d->addAttr(new FastCallAttr());
818}
819
820static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
821  // check the attribute arguments.
822  if (Attr.getNumArgs() != 0) {
823    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
824    return;
825  }
826
827  d->addAttr(new NoThrowAttr());
828}
829
830static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
831  // check the attribute arguments.
832  if (Attr.getNumArgs() != 0) {
833    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
834    return;
835  }
836
837  d->addAttr(new ConstAttr());
838}
839
840static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
841  // check the attribute arguments.
842  if (Attr.getNumArgs() != 0) {
843    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
844    return;
845  }
846
847  d->addAttr(new PureAttr());
848}
849
850/// Handle __attribute__((format(type,idx,firstarg))) attributes
851/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
852static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
853
854  if (!Attr.getParameterName()) {
855    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
856      << "format" << 1;
857    return;
858  }
859
860  if (Attr.getNumArgs() != 2) {
861    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
862    return;
863  }
864
865  if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
866    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
867      << "format" << "function";
868    return;
869  }
870
871  // FIXME: in C++ the implicit 'this' function parameter also counts.
872  // this is needed in order to be compatible with GCC
873  // the index must start in 1 and the limit is numargs+1
874  unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
875  unsigned FirstIdx = 1;
876
877  const char *Format = Attr.getParameterName()->getName();
878  unsigned FormatLen = Attr.getParameterName()->getLength();
879
880  // Normalize the argument, __foo__ becomes foo.
881  if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
882      Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
883    Format += 2;
884    FormatLen -= 4;
885  }
886
887  bool Supported = false;
888  bool is_NSString = false;
889  bool is_strftime = false;
890  bool is_CFString = false;
891
892  switch (FormatLen) {
893  default: break;
894  case 5: Supported = !memcmp(Format, "scanf", 5); break;
895  case 6: Supported = !memcmp(Format, "printf", 6); break;
896  case 7: Supported = !memcmp(Format, "strfmon", 7); break;
897  case 8:
898    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
899                (is_NSString = !memcmp(Format, "NSString", 8)) ||
900                (is_CFString = !memcmp(Format, "CFString", 8));
901    break;
902  }
903
904  if (!Supported) {
905    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
906      << "format" << Attr.getParameterName()->getName();
907    return;
908  }
909
910  // checks for the 2nd argument
911  Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
912  llvm::APSInt Idx(32);
913  if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
914    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
915      << "format" << 2 << IdxExpr->getSourceRange();
916    return;
917  }
918
919  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
920    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
921      << "format" << 2 << IdxExpr->getSourceRange();
922    return;
923  }
924
925  // FIXME: Do we need to bounds check?
926  unsigned ArgIdx = Idx.getZExtValue() - 1;
927
928  // make sure the format string is really a string
929  QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
930
931  if (is_CFString) {
932    if (!isCFStringType(Ty, S.Context)) {
933      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
934        << "a CFString" << IdxExpr->getSourceRange();
935      return;
936    }
937  } else if (is_NSString) {
938    // FIXME: do we need to check if the type is NSString*?  What are
939    //  the semantics?
940    if (!isNSStringType(Ty, S.Context)) {
941      // FIXME: Should highlight the actual expression that has the
942      // wrong type.
943      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
944        << "an NSString" << IdxExpr->getSourceRange();
945      return;
946    }
947  } else if (!Ty->isPointerType() ||
948             !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
949    // FIXME: Should highlight the actual expression that has the
950    // wrong type.
951    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
952      << "a string type" << IdxExpr->getSourceRange();
953    return;
954  }
955
956  // check the 3rd argument
957  Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
958  llvm::APSInt FirstArg(32);
959  if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
960    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
961      << "format" << 3 << FirstArgExpr->getSourceRange();
962    return;
963  }
964
965  // check if the function is variadic if the 3rd argument non-zero
966  if (FirstArg != 0) {
967    if (isFunctionOrMethodVariadic(d)) {
968      ++NumArgs; // +1 for ...
969    } else {
970      S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
971      return;
972    }
973  }
974
975  // strftime requires FirstArg to be 0 because it doesn't read from any
976  // variable the input is just the current time + the format string.
977  if (is_strftime) {
978    if (FirstArg != 0) {
979      S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
980        << FirstArgExpr->getSourceRange();
981      return;
982    }
983  // if 0 it disables parameter checking (to use with e.g. va_list)
984  } else if (FirstArg != 0 && FirstArg != NumArgs) {
985    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
986      << "format" << 3 << FirstArgExpr->getSourceRange();
987    return;
988  }
989
990  d->addAttr(new FormatAttr(std::string(Format, FormatLen),
991                            Idx.getZExtValue(), FirstArg.getZExtValue()));
992}
993
994static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
995                                       Sema &S) {
996  // check the attribute arguments.
997  if (Attr.getNumArgs() != 0) {
998    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
999    return;
1000  }
1001
1002  // FIXME: This shouldn't be restricted to typedefs
1003  TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
1004  if (!TD || !TD->getUnderlyingType()->isUnionType()) {
1005    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1006      << "transparent_union" << "union";
1007    return;
1008  }
1009
1010  RecordDecl* RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
1011
1012  // FIXME: Should we do a check for RD->isDefinition()?
1013
1014  // FIXME: This isn't supposed to be restricted to pointers, but otherwise
1015  // we might silently generate incorrect code; see following code
1016  for (RecordDecl::field_iterator Field = RD->field_begin(),
1017                               FieldEnd = RD->field_end();
1018       Field != FieldEnd; ++Field) {
1019    if (!Field->getType()->isPointerType()) {
1020      S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);
1021      return;
1022    }
1023  }
1024
1025  // FIXME: This is a complete hack; we should be properly propagating
1026  // transparent_union through Sema.  That said, this is close enough to
1027  // correctly compile all the common cases of transparent_union without
1028  // errors or warnings
1029  QualType NewTy = S.Context.VoidPtrTy;
1030  NewTy.addConst();
1031  TD->setUnderlyingType(NewTy);
1032}
1033
1034static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1035  // check the attribute arguments.
1036  if (Attr.getNumArgs() != 1) {
1037    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1038    return;
1039  }
1040  Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
1041  StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
1042
1043  // Make sure that there is a string literal as the annotation's single
1044  // argument.
1045  if (!SE) {
1046    S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
1047    return;
1048  }
1049  d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
1050                                          SE->getByteLength())));
1051}
1052
1053static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1054  // check the attribute arguments.
1055  if (Attr.getNumArgs() > 1) {
1056    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1057    return;
1058  }
1059
1060  unsigned Align = 0;
1061  if (Attr.getNumArgs() == 0) {
1062    // FIXME: This should be the target specific maximum alignment.
1063    // (For now we just use 128 bits which is the maximum on X86.
1064    Align = 128;
1065    return;
1066  }
1067
1068  Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
1069  llvm::APSInt Alignment(32);
1070  if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
1071    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1072      << "aligned" << alignmentExpr->getSourceRange();
1073    return;
1074  }
1075  d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
1076}
1077
1078/// HandleModeAttr - This attribute modifies the width of a decl with
1079/// primitive type.
1080///
1081/// Despite what would be logical, the mode attribute is a decl attribute,
1082/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
1083/// 'G' be HImode, not an intermediate pointer.
1084///
1085static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
1086  // This attribute isn't documented, but glibc uses it.  It changes
1087  // the width of an int or unsigned int to the specified size.
1088
1089  // Check that there aren't any arguments
1090  if (Attr.getNumArgs() != 0) {
1091    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1092    return;
1093  }
1094
1095  IdentifierInfo *Name = Attr.getParameterName();
1096  if (!Name) {
1097    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
1098    return;
1099  }
1100  const char *Str = Name->getName();
1101  unsigned Len = Name->getLength();
1102
1103  // Normalize the attribute name, __foo__ becomes foo.
1104  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
1105      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
1106    Str += 2;
1107    Len -= 4;
1108  }
1109
1110  unsigned DestWidth = 0;
1111  bool IntegerMode = true;
1112  switch (Len) {
1113  case 2:
1114    if (!memcmp(Str, "QI", 2)) { DestWidth =  8; break; }
1115    if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
1116    if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
1117    if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
1118    if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
1119    if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
1120    if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
1121    if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
1122    if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
1123    break;
1124  case 4:
1125    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
1126    // pointer on PIC16 and other embedded platforms.
1127    if (!memcmp(Str, "word", 4))
1128      DestWidth = S.Context.Target.getPointerWidth(0);
1129    if (!memcmp(Str, "byte", 4))
1130      DestWidth = S.Context.Target.getCharWidth();
1131    break;
1132  case 7:
1133    if (!memcmp(Str, "pointer", 7))
1134      DestWidth = S.Context.Target.getPointerWidth(0);
1135    break;
1136  }
1137
1138  QualType OldTy;
1139  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
1140    OldTy = TD->getUnderlyingType();
1141  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
1142    OldTy = VD->getType();
1143  else {
1144    S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
1145      << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
1146    return;
1147  }
1148
1149  // FIXME: Need proper fixed-width types
1150  QualType NewTy;
1151  switch (DestWidth) {
1152  case 0:
1153    S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
1154    return;
1155  default:
1156    S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1157    return;
1158  case 8:
1159    assert(IntegerMode);
1160    if (OldTy->isSignedIntegerType())
1161      NewTy = S.Context.SignedCharTy;
1162    else
1163      NewTy = S.Context.UnsignedCharTy;
1164    break;
1165  case 16:
1166    assert(IntegerMode);
1167    if (OldTy->isSignedIntegerType())
1168      NewTy = S.Context.ShortTy;
1169    else
1170      NewTy = S.Context.UnsignedShortTy;
1171    break;
1172  case 32:
1173    if (!IntegerMode)
1174      NewTy = S.Context.FloatTy;
1175    else if (OldTy->isSignedIntegerType())
1176      NewTy = S.Context.IntTy;
1177    else
1178      NewTy = S.Context.UnsignedIntTy;
1179    break;
1180  case 64:
1181    if (!IntegerMode)
1182      NewTy = S.Context.DoubleTy;
1183    else if (OldTy->isSignedIntegerType())
1184      NewTy = S.Context.LongLongTy;
1185    else
1186      NewTy = S.Context.UnsignedLongLongTy;
1187    break;
1188  }
1189
1190  if (!OldTy->getAsBuiltinType())
1191    S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
1192  else if (!(IntegerMode && OldTy->isIntegerType()) &&
1193           !(!IntegerMode && OldTy->isFloatingType())) {
1194    S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
1195  }
1196
1197  // Install the new type.
1198  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
1199    TD->setUnderlyingType(NewTy);
1200  else
1201    cast<ValueDecl>(D)->setType(NewTy);
1202}
1203
1204//===----------------------------------------------------------------------===//
1205// Top Level Sema Entry Points
1206//===----------------------------------------------------------------------===//
1207
1208/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
1209/// the attribute applies to decls.  If the attribute is a type attribute, just
1210/// silently ignore it.
1211static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
1212  switch (Attr.getKind()) {
1213  case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
1214  case AttributeList::AT_address_space:
1215    // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
1216    break;
1217  case AttributeList::AT_alias:       HandleAliasAttr     (D, Attr, S); break;
1218  case AttributeList::AT_aligned:     HandleAlignedAttr   (D, Attr, S); break;
1219  case AttributeList::AT_always_inline:
1220    HandleAlwaysInlineAttr  (D, Attr, S); break;
1221  case AttributeList::AT_annotate:    HandleAnnotateAttr  (D, Attr, S); break;
1222  case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
1223  case AttributeList::AT_deprecated:  HandleDeprecatedAttr(D, Attr, S); break;
1224  case AttributeList::AT_destructor:  HandleDestructorAttr(D, Attr, S); break;
1225  case AttributeList::AT_dllexport:   HandleDLLExportAttr (D, Attr, S); break;
1226  case AttributeList::AT_dllimport:   HandleDLLImportAttr (D, Attr, S); break;
1227  case AttributeList::AT_ext_vector_type:
1228    HandleExtVectorTypeAttr(D, Attr, S);
1229    break;
1230  case AttributeList::AT_fastcall:    HandleFastCallAttr  (D, Attr, S); break;
1231  case AttributeList::AT_format:      HandleFormatAttr    (D, Attr, S); break;
1232  case AttributeList::AT_mode:        HandleModeAttr      (D, Attr, S); break;
1233  case AttributeList::AT_nonnull:     HandleNonNullAttr   (D, Attr, S); break;
1234  case AttributeList::AT_noreturn:    HandleNoReturnAttr  (D, Attr, S); break;
1235  case AttributeList::AT_nothrow:     HandleNothrowAttr   (D, Attr, S); break;
1236  case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
1237  case AttributeList::AT_stdcall:     HandleStdCallAttr   (D, Attr, S); break;
1238  case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break;
1239  case AttributeList::AT_unused:      HandleUnusedAttr    (D, Attr, S); break;
1240  case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
1241  case AttributeList::AT_visibility:  HandleVisibilityAttr(D, Attr, S); break;
1242  case AttributeList::AT_weak:        HandleWeakAttr      (D, Attr, S); break;
1243  case AttributeList::AT_transparent_union:
1244    HandleTransparentUnionAttr(D, Attr, S);
1245    break;
1246  case AttributeList::AT_objc_gc:     HandleObjCGCAttr    (D, Attr, S); break;
1247  case AttributeList::AT_nsobject:    HandleObjCNSObject  (D, Attr, S); break;
1248  case AttributeList::AT_blocks:      HandleBlocksAttr    (D, Attr, S); break;
1249  case AttributeList::AT_sentinel:    HandleSentinelAttr  (D, Attr, S); break;
1250  case AttributeList::AT_const:       HandleConstAttr     (D, Attr, S); break;
1251  case AttributeList::AT_pure:        HandlePureAttr      (D, Attr, S); break;
1252  default:
1253#if 0
1254    // TODO: when we have the full set of attributes, warn about unknown ones.
1255    S.Diag(Attr->getLoc(), diag::warn_attribute_ignored) << Attr->getName();
1256#endif
1257    break;
1258  }
1259}
1260
1261/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
1262/// attribute list to the specified decl, ignoring any type attributes.
1263void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
1264  while (AttrList) {
1265    ProcessDeclAttribute(D, *AttrList, *this);
1266    AttrList = AttrList->getNext();
1267  }
1268}
1269
1270
1271/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
1272/// it, apply them to D.  This is a bit tricky because PD can have attributes
1273/// specified in many different places, and we need to find and apply them all.
1274void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
1275  // Apply decl attributes from the DeclSpec if present.
1276  if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
1277    ProcessDeclAttributeList(D, Attrs);
1278
1279  // Walk the declarator structure, applying decl attributes that were in a type
1280  // position to the decl itself.  This handles cases like:
1281  //   int *__attr__(x)** D;
1282  // when X is a decl attribute.
1283  for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
1284    if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
1285      ProcessDeclAttributeList(D, Attrs);
1286
1287  // Finally, apply any attributes on the decl itself.
1288  if (const AttributeList *Attrs = PD.getAttributes())
1289    ProcessDeclAttributeList(D, Attrs);
1290}
1291
1292