SemaDeclAttr.cpp revision 888ad7e286c0e4818895b6c78bb22d63fe79c600
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 (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
291    ID->addAttr(new IBOutletAttr());
292  else
293    S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
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" << "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  d->addAttr(new AlwaysInlineAttr());
400}
401
402static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
403  // check the attribute arguments.
404  if (Attr.getNumArgs() != 0) {
405    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
406    return;
407  }
408
409  if (!isFunctionOrMethod(d)) {
410    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
411      << "noreturn" << "function";
412    return;
413  }
414
415  d->addAttr(new NoReturnAttr());
416}
417
418static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
419  // check the attribute arguments.
420  if (Attr.getNumArgs() != 0) {
421    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
422    return;
423  }
424
425  if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
426    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
427      << "unused" << "variable and function";
428    return;
429  }
430
431  d->addAttr(new UnusedAttr());
432}
433
434static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
435  // check the attribute arguments.
436  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
437    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
438      << "0 or 1";
439    return;
440  }
441
442  int priority = 65535; // FIXME: Do not hardcode such constants.
443  if (Attr.getNumArgs() > 0) {
444    Expr *E = static_cast<Expr *>(Attr.getArg(0));
445    llvm::APSInt Idx(32);
446    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
447      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
448        << "constructor" << 1 << E->getSourceRange();
449      return;
450    }
451    priority = Idx.getZExtValue();
452  }
453
454  FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
455  if (!Fn) {
456    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
457      << "constructor" << "function";
458    return;
459  }
460
461  d->addAttr(new ConstructorAttr(priority));
462}
463
464static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
465  // check the attribute arguments.
466  if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
467    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
468       << "0 or 1";
469    return;
470  }
471
472  int priority = 65535; // FIXME: Do not hardcode such constants.
473  if (Attr.getNumArgs() > 0) {
474    Expr *E = static_cast<Expr *>(Attr.getArg(0));
475    llvm::APSInt Idx(32);
476    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
477      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
478        << "destructor" << 1 << E->getSourceRange();
479      return;
480    }
481    priority = Idx.getZExtValue();
482  }
483
484  if (!isa<FunctionDecl>(d)) {
485    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
486      << "destructor" << "function";
487    return;
488  }
489
490  d->addAttr(new DestructorAttr(priority));
491}
492
493static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
494  // check the attribute arguments.
495  if (Attr.getNumArgs() != 0) {
496    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
497    return;
498  }
499
500  d->addAttr(new DeprecatedAttr());
501}
502
503static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
504  // check the attribute arguments.
505  if (Attr.getNumArgs() != 0) {
506    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
507    return;
508  }
509
510  d->addAttr(new UnavailableAttr());
511}
512
513static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
514  // check the attribute arguments.
515  if (Attr.getNumArgs() != 1) {
516    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
517    return;
518  }
519
520  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
521  Arg = Arg->IgnoreParenCasts();
522  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
523
524  if (Str == 0 || Str->isWide()) {
525    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
526      << "visibility" << 1;
527    return;
528  }
529
530  const char *TypeStr = Str->getStrData();
531  unsigned TypeLen = Str->getByteLength();
532  VisibilityAttr::VisibilityTypes type;
533
534  if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
535    type = VisibilityAttr::DefaultVisibility;
536  else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
537    type = VisibilityAttr::HiddenVisibility;
538  else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
539    type = VisibilityAttr::HiddenVisibility; // FIXME
540  else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
541    type = VisibilityAttr::ProtectedVisibility;
542  else {
543    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
544    return;
545  }
546
547  d->addAttr(new VisibilityAttr(type));
548}
549
550static void HandleObjCGCAttr(Decl *d, const AttributeList &Attr, Sema &S) {
551  if (!Attr.getParameterName()) {
552    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
553      << "objc_gc" << 1;
554    return;
555  }
556
557  if (Attr.getNumArgs() != 0) {
558    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
559    return;
560  }
561
562
563  ObjCGCAttr::GCAttrTypes type;
564  if (Attr.getParameterName()->isStr("weak")) {
565    if (isa<FieldDecl>(d) && !isa<ObjCIvarDecl>(d))
566      S.Diag(Attr.getLoc(), diag::warn_attribute_weak_on_field);
567    type = ObjCGCAttr::Weak;
568  }
569  else if (Attr.getParameterName()->isStr("strong"))
570    type = ObjCGCAttr::Strong;
571  else {
572    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
573      << "objc_gc" << Attr.getParameterName();
574    return;
575  }
576
577  d->addAttr(new ObjCGCAttr(type));
578}
579
580static void HandleObjCNSObject(Decl *d, const AttributeList &Attr, Sema &S) {
581  if (Attr.getNumArgs() != 0) {
582    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
583    return;
584  }
585  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(d)) {
586    QualType T = TD->getUnderlyingType();
587    if (!T->isPointerType() ||
588        !T->getAsPointerType()->getPointeeType()->isRecordType()) {
589      S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
590      return;
591    }
592  }
593  d->addAttr(new ObjCNSObjectAttr);
594}
595
596static void
597HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
598  if (Attr.getNumArgs() != 0) {
599    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
600    return;
601  }
602
603  if (!isa<FunctionDecl>(D)) {
604    S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
605    return;
606  }
607
608  D->addAttr(new OverloadableAttr);
609}
610
611static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
612  if (!Attr.getParameterName()) {
613    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
614      << "blocks" << 1;
615    return;
616  }
617
618  if (Attr.getNumArgs() != 0) {
619    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
620    return;
621  }
622
623  BlocksAttr::BlocksAttrTypes type;
624  if (Attr.getParameterName()->isStr("byref"))
625    type = BlocksAttr::ByRef;
626  else {
627    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
628      << "blocks" << Attr.getParameterName();
629    return;
630  }
631
632  d->addAttr(new BlocksAttr(type));
633}
634
635static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
636  // check the attribute arguments.
637  if (Attr.getNumArgs() > 2) {
638    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
639      << "0, 1 or 2";
640    return;
641  }
642
643  int sentinel = 0;
644  if (Attr.getNumArgs() > 0) {
645    Expr *E = static_cast<Expr *>(Attr.getArg(0));
646    llvm::APSInt Idx(32);
647    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
648      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
649       << "sentinel" << 1 << E->getSourceRange();
650      return;
651    }
652    sentinel = Idx.getZExtValue();
653
654    if (sentinel < 0) {
655      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
656        << E->getSourceRange();
657      return;
658    }
659  }
660
661  int nullPos = 0;
662  if (Attr.getNumArgs() > 1) {
663    Expr *E = static_cast<Expr *>(Attr.getArg(1));
664    llvm::APSInt Idx(32);
665    if (!E->isIntegerConstantExpr(Idx, S.Context)) {
666      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
667        << "sentinel" << 2 << E->getSourceRange();
668      return;
669    }
670    nullPos = Idx.getZExtValue();
671
672    if (nullPos > 1 || nullPos < 0) {
673      // FIXME: This error message could be improved, it would be nice
674      // to say what the bounds actually are.
675      S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
676        << E->getSourceRange();
677      return;
678    }
679  }
680
681  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
682    QualType FT = FD->getType();
683    if (!FT->getAsFunctionTypeProto()->isVariadic()) {
684      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
685      return;
686    }
687  } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
688    if (!MD->isVariadic()) {
689      S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic);
690      return;
691    }
692  } else {
693    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
694      << "sentinel" << "function or method";
695    return;
696  }
697
698  // FIXME: Actually create the attribute.
699}
700
701static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
702  // check the attribute arguments.
703  if (Attr.getNumArgs() != 0) {
704    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
705    return;
706  }
707
708  d->addAttr(new WeakAttr());
709}
710
711static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
712  // check the attribute arguments.
713  if (Attr.getNumArgs() != 0) {
714    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
715    return;
716  }
717
718  // Attribute can be applied only to functions or variables.
719  if (isa<VarDecl>(d)) {
720    d->addAttr(new DLLImportAttr());
721    return;
722  }
723
724  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
725  if (!FD) {
726    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
727      << "dllimport" << "function or variable";
728    return;
729  }
730
731  // Currently, the dllimport attribute is ignored for inlined functions.
732  // Warning is emitted.
733  if (FD->isInline()) {
734    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
735    return;
736  }
737
738  // The attribute is also overridden by a subsequent declaration as dllexport.
739  // Warning is emitted.
740  for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
741       nextAttr = nextAttr->getNext()) {
742    if (nextAttr->getKind() == AttributeList::AT_dllexport) {
743      S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
744      return;
745    }
746  }
747
748  if (d->getAttr<DLLExportAttr>()) {
749    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
750    return;
751  }
752
753  d->addAttr(new DLLImportAttr());
754}
755
756static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
757  // check the attribute arguments.
758  if (Attr.getNumArgs() != 0) {
759    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
760    return;
761  }
762
763  // Attribute can be applied only to functions or variables.
764  if (isa<VarDecl>(d)) {
765    d->addAttr(new DLLExportAttr());
766    return;
767  }
768
769  FunctionDecl *FD = dyn_cast<FunctionDecl>(d);
770  if (!FD) {
771    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
772      << "dllexport" << "function or variable";
773    return;
774  }
775
776  // Currently, the dllexport attribute is ignored for inlined functions,
777  // unless the -fkeep-inline-functions flag has been used. Warning is emitted;
778  if (FD->isInline()) {
779    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
780    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
781    return;
782  }
783
784  d->addAttr(new DLLExportAttr());
785}
786
787static void HandleSectionAttr(Decl *d, const AttributeList &Attr, Sema &S) {
788  // Attribute has no arguments.
789  if (Attr.getNumArgs() != 1) {
790    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
791    return;
792  }
793
794  // Make sure that there is a string literal as the sections's single
795  // argument.
796  StringLiteral *SE =
797    dyn_cast<StringLiteral>(static_cast<Expr *>(Attr.getArg(0)));
798  if (!SE) {
799    // FIXME
800    S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
801    return;
802  }
803  d->addAttr(new SectionAttr(std::string(SE->getStrData(),
804                                         SE->getByteLength())));
805}
806
807static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
808  // Attribute has no arguments.
809  if (Attr.getNumArgs() != 0) {
810    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
811    return;
812  }
813
814  // Attribute can be applied only to functions.
815  if (!isa<FunctionDecl>(d)) {
816    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
817      << "stdcall" << "function";
818    return;
819  }
820
821  // stdcall and fastcall attributes are mutually incompatible.
822  if (d->getAttr<FastCallAttr>()) {
823    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
824      << "stdcall" << "fastcall";
825    return;
826  }
827
828  d->addAttr(new StdCallAttr());
829}
830
831static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
832  // Attribute has no arguments.
833  if (Attr.getNumArgs() != 0) {
834    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
835    return;
836  }
837
838  if (!isa<FunctionDecl>(d)) {
839    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
840      << "fastcall" << "function";
841    return;
842  }
843
844  // stdcall and fastcall attributes are mutually incompatible.
845  if (d->getAttr<StdCallAttr>()) {
846    S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
847      << "fastcall" << "stdcall";
848    return;
849  }
850
851  d->addAttr(new FastCallAttr());
852}
853
854static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
855  // check the attribute arguments.
856  if (Attr.getNumArgs() != 0) {
857    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
858    return;
859  }
860
861  d->addAttr(new NoThrowAttr());
862}
863
864static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
865  // check the attribute arguments.
866  if (Attr.getNumArgs() != 0) {
867    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
868    return;
869  }
870
871  d->addAttr(new ConstAttr());
872}
873
874static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
875  // check the attribute arguments.
876  if (Attr.getNumArgs() != 0) {
877    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
878    return;
879  }
880
881  d->addAttr(new PureAttr());
882}
883
884static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
885  // Match gcc which ignores cleanup attrs when compiling C++.
886  if (S.getLangOptions().CPlusPlus)
887    return;
888
889  if (!Attr.getParameterName()) {
890    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
891    return;
892  }
893
894  if (Attr.getNumArgs() != 0) {
895    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
896    return;
897  }
898
899  VarDecl *VD = dyn_cast<VarDecl>(d);
900
901  if (!VD || !VD->hasLocalStorage()) {
902    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
903    return;
904  }
905
906  // Look up the function
907  NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(),
908                                        Sema::LookupOrdinaryName);
909  if (!CleanupDecl) {
910    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) <<
911      Attr.getParameterName();
912    return;
913  }
914
915  FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
916  if (!FD) {
917    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) <<
918      Attr.getParameterName();
919    return;
920  }
921
922  if (FD->getNumParams() != 1) {
923    S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) <<
924      Attr.getParameterName();
925    return;
926  }
927
928  // We're currently more strict than GCC about what function types we accept.
929  // If this ever proves to be a problem it should be easy to fix.
930  QualType Ty = S.Context.getPointerType(VD->getType());
931  QualType ParamTy = FD->getParamDecl(0)->getType();
932  if (Ty != ParamTy) {
933    S.Diag(Attr.getLoc(),
934           diag::err_attribute_cleanup_func_arg_incompatible_type) <<
935      Attr.getParameterName() << ParamTy << Ty;
936    return;
937  }
938
939  d->addAttr(new CleanupAttr(FD));
940}
941
942/// Handle __attribute__((format(type,idx,firstarg))) attributes
943/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
944static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
945
946  if (!Attr.getParameterName()) {
947    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
948      << "format" << 1;
949    return;
950  }
951
952  if (Attr.getNumArgs() != 2) {
953    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
954    return;
955  }
956
957  if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
958    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
959      << "format" << "function";
960    return;
961  }
962
963  // FIXME: in C++ the implicit 'this' function parameter also counts.
964  // this is needed in order to be compatible with GCC
965  // the index must start in 1 and the limit is numargs+1
966  unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
967  unsigned FirstIdx = 1;
968
969  const char *Format = Attr.getParameterName()->getName();
970  unsigned FormatLen = Attr.getParameterName()->getLength();
971
972  // Normalize the argument, __foo__ becomes foo.
973  if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
974      Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
975    Format += 2;
976    FormatLen -= 4;
977  }
978
979  bool Supported = false;
980  bool is_NSString = false;
981  bool is_strftime = false;
982  bool is_CFString = false;
983
984  switch (FormatLen) {
985  default: break;
986  case 5: Supported = !memcmp(Format, "scanf", 5); break;
987  case 6: Supported = !memcmp(Format, "printf", 6); break;
988  case 7: Supported = !memcmp(Format, "strfmon", 7); break;
989  case 8:
990    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
991                (is_NSString = !memcmp(Format, "NSString", 8)) ||
992                (is_CFString = !memcmp(Format, "CFString", 8));
993    break;
994  }
995
996  if (!Supported) {
997    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
998      << "format" << Attr.getParameterName()->getName();
999    return;
1000  }
1001
1002  // checks for the 2nd argument
1003  Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
1004  llvm::APSInt Idx(32);
1005  if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
1006    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
1007      << "format" << 2 << IdxExpr->getSourceRange();
1008    return;
1009  }
1010
1011  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
1012    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
1013      << "format" << 2 << IdxExpr->getSourceRange();
1014    return;
1015  }
1016
1017  // FIXME: Do we need to bounds check?
1018  unsigned ArgIdx = Idx.getZExtValue() - 1;
1019
1020  // make sure the format string is really a string
1021  QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
1022
1023  if (is_CFString) {
1024    if (!isCFStringType(Ty, S.Context)) {
1025      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1026        << "a CFString" << IdxExpr->getSourceRange();
1027      return;
1028    }
1029  } else if (is_NSString) {
1030    // FIXME: do we need to check if the type is NSString*?  What are
1031    //  the semantics?
1032    if (!isNSStringType(Ty, S.Context)) {
1033      // FIXME: Should highlight the actual expression that has the
1034      // wrong type.
1035      S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1036        << "an NSString" << IdxExpr->getSourceRange();
1037      return;
1038    }
1039  } else if (!Ty->isPointerType() ||
1040             !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
1041    // FIXME: Should highlight the actual expression that has the
1042    // wrong type.
1043    S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
1044      << "a string type" << IdxExpr->getSourceRange();
1045    return;
1046  }
1047
1048  // check the 3rd argument
1049  Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
1050  llvm::APSInt FirstArg(32);
1051  if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
1052    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
1053      << "format" << 3 << FirstArgExpr->getSourceRange();
1054    return;
1055  }
1056
1057  // check if the function is variadic if the 3rd argument non-zero
1058  if (FirstArg != 0) {
1059    if (isFunctionOrMethodVariadic(d)) {
1060      ++NumArgs; // +1 for ...
1061    } else {
1062      S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
1063      return;
1064    }
1065  }
1066
1067  // strftime requires FirstArg to be 0 because it doesn't read from any
1068  // variable the input is just the current time + the format string.
1069  if (is_strftime) {
1070    if (FirstArg != 0) {
1071      S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
1072        << FirstArgExpr->getSourceRange();
1073      return;
1074    }
1075  // if 0 it disables parameter checking (to use with e.g. va_list)
1076  } else if (FirstArg != 0 && FirstArg != NumArgs) {
1077    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
1078      << "format" << 3 << FirstArgExpr->getSourceRange();
1079    return;
1080  }
1081
1082  d->addAttr(new FormatAttr(std::string(Format, FormatLen),
1083                            Idx.getZExtValue(), FirstArg.getZExtValue()));
1084}
1085
1086static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
1087                                       Sema &S) {
1088  // check the attribute arguments.
1089  if (Attr.getNumArgs() != 0) {
1090    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1091    return;
1092  }
1093
1094  // FIXME: This shouldn't be restricted to typedefs
1095  TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
1096  if (!TD || !TD->getUnderlyingType()->isUnionType()) {
1097    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1098      << "transparent_union" << "union";
1099    return;
1100  }
1101
1102  RecordDecl* RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
1103
1104  // FIXME: Should we do a check for RD->isDefinition()?
1105
1106  // FIXME: This isn't supposed to be restricted to pointers, but otherwise
1107  // we might silently generate incorrect code; see following code
1108  for (RecordDecl::field_iterator Field = RD->field_begin(),
1109                               FieldEnd = RD->field_end();
1110       Field != FieldEnd; ++Field) {
1111    if (!Field->getType()->isPointerType()) {
1112      S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer);
1113      return;
1114    }
1115  }
1116
1117  // FIXME: This is a complete hack; we should be properly propagating
1118  // transparent_union through Sema.  That said, this is close enough to
1119  // correctly compile all the common cases of transparent_union without
1120  // errors or warnings
1121  QualType NewTy = S.Context.VoidPtrTy;
1122  NewTy.addConst();
1123  TD->setUnderlyingType(NewTy);
1124}
1125
1126static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1127  // check the attribute arguments.
1128  if (Attr.getNumArgs() != 1) {
1129    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1130    return;
1131  }
1132  Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
1133  StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
1134
1135  // Make sure that there is a string literal as the annotation's single
1136  // argument.
1137  if (!SE) {
1138    S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
1139    return;
1140  }
1141  d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
1142                                          SE->getByteLength())));
1143}
1144
1145static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1146  // check the attribute arguments.
1147  if (Attr.getNumArgs() > 1) {
1148    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
1149    return;
1150  }
1151
1152  unsigned Align = 0;
1153  if (Attr.getNumArgs() == 0) {
1154    // FIXME: This should be the target specific maximum alignment.
1155    // (For now we just use 128 bits which is the maximum on X86.
1156    Align = 128;
1157    return;
1158  }
1159
1160  Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
1161  llvm::APSInt Alignment(32);
1162  if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
1163    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
1164      << "aligned" << alignmentExpr->getSourceRange();
1165    return;
1166  }
1167  d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
1168}
1169
1170/// HandleModeAttr - This attribute modifies the width of a decl with
1171/// primitive type.
1172///
1173/// Despite what would be logical, the mode attribute is a decl attribute,
1174/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
1175/// 'G' be HImode, not an intermediate pointer.
1176///
1177static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
1178  // This attribute isn't documented, but glibc uses it.  It changes
1179  // the width of an int or unsigned int to the specified size.
1180
1181  // Check that there aren't any arguments
1182  if (Attr.getNumArgs() != 0) {
1183    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1184    return;
1185  }
1186
1187  IdentifierInfo *Name = Attr.getParameterName();
1188  if (!Name) {
1189    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
1190    return;
1191  }
1192  const char *Str = Name->getName();
1193  unsigned Len = Name->getLength();
1194
1195  // Normalize the attribute name, __foo__ becomes foo.
1196  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
1197      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
1198    Str += 2;
1199    Len -= 4;
1200  }
1201
1202  unsigned DestWidth = 0;
1203  bool IntegerMode = true;
1204  switch (Len) {
1205  case 2:
1206    if (!memcmp(Str, "QI", 2)) { DestWidth =  8; break; }
1207    if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
1208    if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
1209    if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
1210    if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
1211    if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
1212    if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
1213    if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
1214    if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
1215    break;
1216  case 4:
1217    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
1218    // pointer on PIC16 and other embedded platforms.
1219    if (!memcmp(Str, "word", 4))
1220      DestWidth = S.Context.Target.getPointerWidth(0);
1221    if (!memcmp(Str, "byte", 4))
1222      DestWidth = S.Context.Target.getCharWidth();
1223    break;
1224  case 7:
1225    if (!memcmp(Str, "pointer", 7))
1226      DestWidth = S.Context.Target.getPointerWidth(0);
1227    break;
1228  }
1229
1230  QualType OldTy;
1231  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
1232    OldTy = TD->getUnderlyingType();
1233  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
1234    OldTy = VD->getType();
1235  else {
1236    S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
1237      << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
1238    return;
1239  }
1240
1241  // FIXME: Sync this with InitializePredefinedMacros; we need to match
1242  // int8_t and friends, at least with glibc.
1243  // FIXME: Make sure 32/64-bit integers don't get defined to types of
1244  // the wrong width on unusual platforms.
1245  // FIXME: Make sure floating-point mappings are accurate
1246  // FIXME: Support XF and TF types
1247  QualType NewTy;
1248  switch (DestWidth) {
1249  case 0:
1250    S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
1251    return;
1252  default:
1253    S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1254    return;
1255  case 8:
1256    assert(IntegerMode);
1257    if (OldTy->isSignedIntegerType())
1258      NewTy = S.Context.SignedCharTy;
1259    else
1260      NewTy = S.Context.UnsignedCharTy;
1261    break;
1262  case 16:
1263    assert(IntegerMode);
1264    if (OldTy->isSignedIntegerType())
1265      NewTy = S.Context.ShortTy;
1266    else
1267      NewTy = S.Context.UnsignedShortTy;
1268    break;
1269  case 32:
1270    if (!IntegerMode)
1271      NewTy = S.Context.FloatTy;
1272    else if (OldTy->isSignedIntegerType())
1273      NewTy = S.Context.IntTy;
1274    else
1275      NewTy = S.Context.UnsignedIntTy;
1276    break;
1277  case 64:
1278    if (!IntegerMode)
1279      NewTy = S.Context.DoubleTy;
1280    else if (OldTy->isSignedIntegerType())
1281      NewTy = S.Context.LongLongTy;
1282    else
1283      NewTy = S.Context.UnsignedLongLongTy;
1284    break;
1285  case 128:
1286    if (!IntegerMode) {
1287      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
1288      return;
1289    }
1290    NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType());
1291  }
1292
1293  if (!OldTy->getAsBuiltinType())
1294    S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
1295  else if (!(IntegerMode && OldTy->isIntegerType()) &&
1296           !(!IntegerMode && OldTy->isFloatingType())) {
1297    S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
1298  }
1299
1300  // Install the new type.
1301  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
1302    TD->setUnderlyingType(NewTy);
1303  else
1304    cast<ValueDecl>(D)->setType(NewTy);
1305}
1306
1307static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
1308  // check the attribute arguments.
1309  if (Attr.getNumArgs() > 0) {
1310    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
1311    return;
1312  }
1313
1314  if (!isa<FunctionDecl>(d)) {
1315    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
1316      << "nodebug" << "function";
1317    return;
1318  }
1319
1320  d->addAttr(new NodebugAttr());
1321}
1322
1323//===----------------------------------------------------------------------===//
1324// Top Level Sema Entry Points
1325//===----------------------------------------------------------------------===//
1326
1327/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
1328/// the attribute applies to decls.  If the attribute is a type attribute, just
1329/// silently ignore it.
1330static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
1331  switch (Attr.getKind()) {
1332  case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
1333  case AttributeList::AT_address_space:
1334    // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
1335    break;
1336  case AttributeList::AT_alias:       HandleAliasAttr     (D, Attr, S); break;
1337  case AttributeList::AT_aligned:     HandleAlignedAttr   (D, Attr, S); break;
1338  case AttributeList::AT_always_inline:
1339    HandleAlwaysInlineAttr  (D, Attr, S); break;
1340  case AttributeList::AT_annotate:    HandleAnnotateAttr  (D, Attr, S); break;
1341  case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break;
1342  case AttributeList::AT_deprecated:  HandleDeprecatedAttr(D, Attr, S); break;
1343  case AttributeList::AT_destructor:  HandleDestructorAttr(D, Attr, S); break;
1344  case AttributeList::AT_dllexport:   HandleDLLExportAttr (D, Attr, S); break;
1345  case AttributeList::AT_dllimport:   HandleDLLImportAttr (D, Attr, S); break;
1346  case AttributeList::AT_ext_vector_type:
1347    HandleExtVectorTypeAttr(D, Attr, S);
1348    break;
1349  case AttributeList::AT_fastcall:    HandleFastCallAttr  (D, Attr, S); break;
1350  case AttributeList::AT_format:      HandleFormatAttr    (D, Attr, S); break;
1351  case AttributeList::AT_mode:        HandleModeAttr      (D, Attr, S); break;
1352  case AttributeList::AT_nonnull:     HandleNonNullAttr   (D, Attr, S); break;
1353  case AttributeList::AT_noreturn:    HandleNoReturnAttr  (D, Attr, S); break;
1354  case AttributeList::AT_nothrow:     HandleNothrowAttr   (D, Attr, S); break;
1355  case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
1356  case AttributeList::AT_section:     HandleSectionAttr   (D, Attr, S); break;
1357  case AttributeList::AT_stdcall:     HandleStdCallAttr   (D, Attr, S); break;
1358  case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break;
1359  case AttributeList::AT_unused:      HandleUnusedAttr    (D, Attr, S); break;
1360  case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
1361  case AttributeList::AT_visibility:  HandleVisibilityAttr(D, Attr, S); break;
1362  case AttributeList::AT_weak:        HandleWeakAttr      (D, Attr, S); break;
1363  case AttributeList::AT_transparent_union:
1364    HandleTransparentUnionAttr(D, Attr, S);
1365    break;
1366  case AttributeList::AT_objc_gc:     HandleObjCGCAttr    (D, Attr, S); break;
1367  case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
1368  case AttributeList::AT_nsobject:    HandleObjCNSObject  (D, Attr, S); break;
1369  case AttributeList::AT_blocks:      HandleBlocksAttr    (D, Attr, S); break;
1370  case AttributeList::AT_sentinel:    HandleSentinelAttr  (D, Attr, S); break;
1371  case AttributeList::AT_const:       HandleConstAttr     (D, Attr, S); break;
1372  case AttributeList::AT_pure:        HandlePureAttr      (D, Attr, S); break;
1373  case AttributeList::AT_cleanup:     HandleCleanupAttr   (D, Attr, S); break;
1374  case AttributeList::AT_nodebug:     HandleNodebugAttr   (D, Attr, S); break;
1375  case AttributeList::IgnoredAttribute:
1376    // Just ignore
1377    break;
1378  default:
1379    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
1380    break;
1381  }
1382}
1383
1384/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
1385/// attribute list to the specified decl, ignoring any type attributes.
1386void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
1387  while (AttrList) {
1388    ProcessDeclAttribute(D, *AttrList, *this);
1389    AttrList = AttrList->getNext();
1390  }
1391}
1392
1393
1394/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
1395/// it, apply them to D.  This is a bit tricky because PD can have attributes
1396/// specified in many different places, and we need to find and apply them all.
1397void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
1398  // Apply decl attributes from the DeclSpec if present.
1399  if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
1400    ProcessDeclAttributeList(D, Attrs);
1401
1402  // Walk the declarator structure, applying decl attributes that were in a type
1403  // position to the decl itself.  This handles cases like:
1404  //   int *__attr__(x)** D;
1405  // when X is a decl attribute.
1406  for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
1407    if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
1408      ProcessDeclAttributeList(D, Attrs);
1409
1410  // Finally, apply any attributes on the decl itself.
1411  if (const AttributeList *Attrs = PD.getAttributes())
1412    ProcessDeclAttributeList(D, Attrs);
1413}
1414
1415