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