SemaDeclAttr.cpp revision 4e5bb1221fef5534ef364e2defff959dd2c2fab0
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/Basic/TargetInfo.h"
17using namespace clang;
18
19//===----------------------------------------------------------------------===//
20//  Helper functions
21//===----------------------------------------------------------------------===//
22
23static const FunctionTypeProto *getFunctionProto(Decl *d) {
24  QualType Ty;
25  if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
26    Ty = decl->getType();
27  else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
28    Ty = decl->getType();
29  else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
30    Ty = decl->getUnderlyingType();
31  else
32    return 0;
33
34  if (Ty->isFunctionPointerType())
35    Ty = Ty->getAsPointerType()->getPointeeType();
36
37  if (const FunctionType *FnTy = Ty->getAsFunctionType())
38    return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
39
40  return 0;
41}
42
43static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
44  if (!T->isPointerType())
45    return false;
46
47  T = T->getAsPointerType()->getPointeeType().getCanonicalType();
48  ObjCInterfaceType* ClsT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
49
50  if (!ClsT)
51    return false;
52
53  IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
54
55  // FIXME: Should we walk the chain of classes?
56  return ClsName == &Ctx.Idents.get("NSString") ||
57         ClsName == &Ctx.Idents.get("NSMutableString");
58}
59
60//===----------------------------------------------------------------------===//
61// Attribute Implementations
62//===----------------------------------------------------------------------===//
63
64static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr,
65                                    Sema &S) {
66  TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
67  if (tDecl == 0) {
68    S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
69    return;
70  }
71
72  QualType curType = tDecl->getUnderlyingType();
73  // check the attribute arguments.
74  if (Attr.getNumArgs() != 1) {
75    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
76           std::string("1"));
77    return;
78  }
79  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
80  llvm::APSInt vecSize(32);
81  if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
82    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
83           "ext_vector_type", sizeExpr->getSourceRange());
84    return;
85  }
86  // unlike gcc's vector_size attribute, we do not allow vectors to be defined
87  // in conjunction with complex types (pointers, arrays, functions, etc.).
88  Type *canonType = curType.getCanonicalType().getTypePtr();
89  if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
90    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
91           curType.getCanonicalType().getAsString());
92    return;
93  }
94  // unlike gcc's vector_size attribute, the size is specified as the
95  // number of elements, not the number of bytes.
96  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
97
98  if (vectorSize == 0) {
99    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
100           sizeExpr->getSourceRange());
101    return;
102  }
103  // Instantiate/Install the vector type, the number of elements is > 0.
104  tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize));
105  // Remember this typedef decl, we will need it later for diagnostics.
106  S.ExtVectorDecls.push_back(tDecl);
107}
108
109
110/// HandleVectorSizeAttribute - this attribute is only applicable to
111/// integral and float scalars, although arrays, pointers, and function
112/// return values are allowed in conjunction with this construct. Aggregates
113/// with this attribute are invalid, even if they are of the same size as a
114/// corresponding scalar.
115/// The raw attribute should contain precisely 1 argument, the vector size
116/// for the variable, measured in bytes. If curType and rawAttr are well
117/// formed, this routine will return a new vector type.
118static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
119  QualType CurType;
120  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
121    CurType = VD->getType();
122  else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
123    CurType = TD->getUnderlyingType();
124  else {
125    S.Diag(D->getLocation(), diag::err_attr_wrong_decl,
126           std::string("vector_size"),
127           SourceRange(Attr.getLoc(), Attr.getLoc()));
128    return;
129  }
130
131  // Check the attribute arugments.
132  if (Attr.getNumArgs() != 1) {
133    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
134           std::string("1"));
135    return;
136  }
137  Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
138  llvm::APSInt vecSize(32);
139  if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
140    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
141           "vector_size", sizeExpr->getSourceRange());
142    return;
143  }
144  // navigate to the base type - we need to provide for vector pointers,
145  // vector arrays, and functions returning vectors.
146  Type *canonType = CurType.getCanonicalType().getTypePtr();
147
148  if (canonType->isPointerType() || canonType->isArrayType() ||
149      canonType->isFunctionType()) {
150    assert(0 && "HandleVector(): Complex type construction unimplemented");
151    /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
152     do {
153     if (PointerType *PT = dyn_cast<PointerType>(canonType))
154     canonType = PT->getPointeeType().getTypePtr();
155     else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
156     canonType = AT->getElementType().getTypePtr();
157     else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
158     canonType = FT->getResultType().getTypePtr();
159     } while (canonType->isPointerType() || canonType->isArrayType() ||
160     canonType->isFunctionType());
161     */
162  }
163  // the base type must be integer or float.
164  if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
165    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
166           CurType.getCanonicalType().getAsString());
167    return;
168  }
169  unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
170  // vecSize is specified in bytes - convert to bits.
171  unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
172
173  // the vector size needs to be an integral multiple of the type size.
174  if (vectorSize % typeSize) {
175    S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
176           sizeExpr->getSourceRange());
177    return;
178  }
179  if (vectorSize == 0) {
180    S.Diag(Attr.getLoc(), diag::err_attribute_zero_size,
181           sizeExpr->getSourceRange());
182    return;
183  }
184
185  // Success! Instantiate the vector type, the number of elements is > 0, and
186  // not required to be a power of 2, unlike GCC.
187  CurType = S.Context.getVectorType(CurType, vectorSize/typeSize);
188
189  if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
190    VD->setType(CurType);
191  else
192    cast<TypedefDecl>(D)->setUnderlyingType(CurType);
193}
194
195static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
196  // check the attribute arguments.
197  if (Attr.getNumArgs() > 0) {
198    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
199           std::string("0"));
200    return;
201  }
202
203  if (TagDecl *TD = dyn_cast<TagDecl>(d))
204    TD->addAttr(new PackedAttr());
205  else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
206    // If the alignment is less than or equal to 8 bits, the packed attribute
207    // has no effect.
208    if (!FD->getType()->isIncompleteType() &&
209        S.Context.getTypeAlign(FD->getType()) <= 8)
210      S.Diag(Attr.getLoc(),
211             diag::warn_attribute_ignored_for_field_of_type,
212             Attr.getName()->getName(), FD->getType().getAsString());
213    else
214      FD->addAttr(new PackedAttr());
215  } else
216    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored,
217           Attr.getName()->getName());
218}
219
220static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
221  // check the attribute arguments.
222  if (Attr.getNumArgs() > 0) {
223    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
224           std::string("0"));
225    return;
226  }
227
228  // The IBOutlet attribute only applies to instance variables of Objective-C
229  // classes.
230  if (ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(d))
231    ID->addAttr(new IBOutletAttr());
232  else
233    S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet_non_ivar);
234}
235
236static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
237  // check the attribute arguments.
238  if (Attr.getNumArgs() != 1) {
239    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
240           std::string("1"));
241    return;
242  }
243
244  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
245  Arg = Arg->IgnoreParenCasts();
246  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
247
248  if (Str == 0 || Str->isWide()) {
249    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
250           "alias", std::string("1"));
251    return;
252  }
253
254  const char *Alias = Str->getStrData();
255  unsigned AliasLen = Str->getByteLength();
256
257  // FIXME: check if target symbol exists in current file
258
259  d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
260}
261
262static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
263  // check the attribute arguments.
264  if (Attr.getNumArgs() != 0) {
265    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
266           std::string("0"));
267    return;
268  }
269
270  FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
271  if (!Fn) {
272    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
273           "noreturn", "function");
274    return;
275  }
276
277  d->addAttr(new NoReturnAttr());
278}
279
280static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
281  // check the attribute arguments.
282  if (Attr.getNumArgs() != 0) {
283    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
284           std::string("0"));
285    return;
286  }
287
288  d->addAttr(new DeprecatedAttr());
289}
290
291static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
292  // check the attribute arguments.
293  if (Attr.getNumArgs() != 1) {
294    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
295           std::string("1"));
296    return;
297  }
298
299  Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
300  Arg = Arg->IgnoreParenCasts();
301  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
302
303  if (Str == 0 || Str->isWide()) {
304    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
305           "visibility", std::string("1"));
306    return;
307  }
308
309  const char *TypeStr = Str->getStrData();
310  unsigned TypeLen = Str->getByteLength();
311  VisibilityAttr::VisibilityTypes type;
312
313  if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
314    type = VisibilityAttr::DefaultVisibility;
315  else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
316    type = VisibilityAttr::HiddenVisibility;
317  else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
318    type = VisibilityAttr::HiddenVisibility; // FIXME
319  else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
320    type = VisibilityAttr::ProtectedVisibility;
321  else {
322    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
323           "visibility", TypeStr);
324    return;
325  }
326
327  d->addAttr(new VisibilityAttr(type));
328}
329
330static void HandleWeakAttr(Decl *d, const AttributeList &Attr, Sema &S) {
331  // check the attribute arguments.
332  if (Attr.getNumArgs() != 0) {
333    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
334           std::string("0"));
335    return;
336  }
337
338  d->addAttr(new WeakAttr());
339}
340
341static void HandleDLLImportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
342  // check the attribute arguments.
343  if (Attr.getNumArgs() != 0) {
344    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
345           std::string("0"));
346    return;
347  }
348
349  d->addAttr(new DLLImportAttr());
350}
351
352static void HandleDLLExportAttr(Decl *d, const AttributeList &Attr, Sema &S) {
353  // check the attribute arguments.
354  if (Attr.getNumArgs() != 0) {
355    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
356           std::string("0"));
357    return;
358  }
359
360  d->addAttr(new DLLExportAttr());
361}
362
363static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
364  // check the attribute arguments.
365  if (Attr.getNumArgs() != 0) {
366    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
367           std::string("0"));
368    return;
369  }
370
371  d->addAttr(new StdCallAttr());
372}
373
374static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) {
375  // check the attribute arguments.
376  if (Attr.getNumArgs() != 0) {
377    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
378           std::string("0"));
379    return;
380  }
381
382  d->addAttr(new FastCallAttr());
383}
384
385static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
386  // check the attribute arguments.
387  if (Attr.getNumArgs() != 0) {
388    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
389           std::string("0"));
390    return;
391  }
392
393  d->addAttr(new NoThrowAttr());
394}
395
396/// Handle __attribute__((format(type,idx,firstarg))) attributes
397/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
398static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
399
400  if (!Attr.getParameterName()) {
401    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
402           "format", std::string("1"));
403    return;
404  }
405
406  if (Attr.getNumArgs() != 2) {
407    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
408           std::string("3"));
409    return;
410  }
411
412  // GCC ignores the format attribute on K&R style function
413  // prototypes, so we ignore it as well
414  const FunctionTypeProto *proto = getFunctionProto(d);
415
416  if (!proto) {
417    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
418           "format", "function");
419    return;
420  }
421
422  // FIXME: in C++ the implicit 'this' function parameter also counts.
423  // this is needed in order to be compatible with GCC
424  // the index must start in 1 and the limit is numargs+1
425  unsigned NumArgs  = proto->getNumArgs();
426  unsigned FirstIdx = 1;
427
428  const char *Format = Attr.getParameterName()->getName();
429  unsigned FormatLen = Attr.getParameterName()->getLength();
430
431  // Normalize the argument, __foo__ becomes foo.
432  if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
433      Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
434    Format += 2;
435    FormatLen -= 4;
436  }
437
438  bool Supported = false;
439  bool is_NSString = false;
440  bool is_strftime = false;
441
442  switch (FormatLen) {
443  default: break;
444  case 5: Supported = !memcmp(Format, "scanf", 5); break;
445  case 6: Supported = !memcmp(Format, "printf", 6); break;
446  case 7: Supported = !memcmp(Format, "strfmon", 7); break;
447  case 8:
448    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
449                (is_NSString = !memcmp(Format, "NSString", 8));
450    break;
451  }
452
453  if (!Supported) {
454    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
455           "format", Attr.getParameterName()->getName());
456    return;
457  }
458
459  // checks for the 2nd argument
460  Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
461  llvm::APSInt Idx(32);
462  if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
463    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
464           "format", std::string("2"), IdxExpr->getSourceRange());
465    return;
466  }
467
468  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
469    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
470           "format", std::string("2"), IdxExpr->getSourceRange());
471    return;
472  }
473
474  // FIXME: Do we need to bounds check?
475  unsigned ArgIdx = Idx.getZExtValue() - 1;
476
477  // make sure the format string is really a string
478  QualType Ty = proto->getArgType(ArgIdx);
479
480  if (is_NSString) {
481    // FIXME: do we need to check if the type is NSString*?  What are
482    //  the semantics?
483    if (!isNSStringType(Ty, S.Context)) {
484      // FIXME: Should highlight the actual expression that has the
485      // wrong type.
486      S.Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
487             IdxExpr->getSourceRange());
488      return;
489    }
490  } else if (!Ty->isPointerType() ||
491             !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
492    // FIXME: Should highlight the actual expression that has the
493    // wrong type.
494    S.Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
495           IdxExpr->getSourceRange());
496    return;
497  }
498
499  // check the 3rd argument
500  Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
501  llvm::APSInt FirstArg(32);
502  if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
503    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
504           "format", std::string("3"), FirstArgExpr->getSourceRange());
505    return;
506  }
507
508  // check if the function is variadic if the 3rd argument non-zero
509  if (FirstArg != 0) {
510    if (proto->isVariadic()) {
511      ++NumArgs; // +1 for ...
512    } else {
513      S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
514      return;
515    }
516  }
517
518  // strftime requires FirstArg to be 0 because it doesn't read from any variable
519  // the input is just the current time + the format string
520  if (is_strftime) {
521    if (FirstArg != 0) {
522      S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
523             FirstArgExpr->getSourceRange());
524      return;
525    }
526  // if 0 it disables parameter checking (to use with e.g. va_list)
527  } else if (FirstArg != 0 && FirstArg != NumArgs) {
528    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
529           "format", std::string("3"), FirstArgExpr->getSourceRange());
530    return;
531  }
532
533  d->addAttr(new FormatAttr(std::string(Format, FormatLen),
534                            Idx.getZExtValue(), FirstArg.getZExtValue()));
535}
536
537static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
538                                       Sema &S) {
539  // check the attribute arguments.
540  if (Attr.getNumArgs() != 0) {
541    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
542         std::string("0"));
543    return;
544  }
545
546  TypeDecl *decl = dyn_cast<TypeDecl>(d);
547
548  if (!decl || !S.Context.getTypeDeclType(decl)->isUnionType()) {
549    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
550         "transparent_union", "union");
551    return;
552  }
553
554  //QualType QTy = Context.getTypeDeclType(decl);
555  //const RecordType *Ty = QTy->getAsUnionType();
556
557// FIXME
558// Ty->addAttr(new TransparentUnionAttr());
559}
560
561static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
562  // check the attribute arguments.
563  if (Attr.getNumArgs() != 1) {
564    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
565           std::string("1"));
566    return;
567  }
568  Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
569  StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
570
571  // Make sure that there is a string literal as the annotation's single
572  // argument.
573  if (!SE) {
574    S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
575    return;
576  }
577  d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
578                                          SE->getByteLength())));
579}
580
581static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
582  // check the attribute arguments.
583  if (Attr.getNumArgs() > 1) {
584    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
585           std::string("1"));
586    return;
587  }
588
589  unsigned Align = 0;
590  if (Attr.getNumArgs() == 0) {
591    // FIXME: This should be the target specific maximum alignment.
592    // (For now we just use 128 bits which is the maximum on X86.
593    Align = 128;
594    return;
595  }
596
597  Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
598  llvm::APSInt Alignment(32);
599  if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
600    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
601           "aligned", alignmentExpr->getSourceRange());
602    return;
603  }
604  d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
605}
606
607/// HandleModeAttr - This attribute modifies the width of a decl with
608/// primitive type.
609///
610/// Despite what would be logical, the mode attribute is a decl attribute,
611/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
612/// 'G' be HImode, not an intermediate pointer.
613///
614static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
615  // This attribute isn't documented, but glibc uses it.  It changes
616  // the width of an int or unsigned int to the specified size.
617
618  // Check that there aren't any arguments
619  if (Attr.getNumArgs() != 0) {
620    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
621           std::string("0"));
622    return;
623  }
624
625  IdentifierInfo *Name = Attr.getParameterName();
626  if (!Name) {
627    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
628    return;
629  }
630  const char *Str = Name->getName();
631  unsigned Len = Name->getLength();
632
633  // Normalize the attribute name, __foo__ becomes foo.
634  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
635      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
636    Str += 2;
637    Len -= 4;
638  }
639
640  unsigned DestWidth = 0;
641  bool IntegerMode = true;
642  switch (Len) {
643  case 2:
644    if (!memcmp(Str, "QI", 2)) { DestWidth =  8; break; }
645    if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
646    if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
647    if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
648    if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
649    if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
650    if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
651    if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
652    if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
653    break;
654  case 4:
655    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
656    // pointer on PIC16 and other embedded platforms.
657    if (!memcmp(Str, "word", 4))
658      DestWidth = S.Context.Target.getPointerWidth(0);
659    if (!memcmp(Str, "byte", 4))
660      DestWidth = S.Context.Target.getCharWidth();
661    break;
662  case 7:
663    if (!memcmp(Str, "pointer", 7))
664      DestWidth = S.Context.Target.getPointerWidth(0);
665    break;
666  }
667
668  QualType OldTy;
669  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
670    OldTy = TD->getUnderlyingType();
671  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
672    OldTy = VD->getType();
673  else {
674    S.Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
675           SourceRange(Attr.getLoc(), Attr.getLoc()));
676    return;
677  }
678
679  // FIXME: Need proper fixed-width types
680  QualType NewTy;
681  switch (DestWidth) {
682  case 0:
683    S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
684    return;
685  default:
686    S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
687    return;
688  case 8:
689    assert(IntegerMode);
690    if (OldTy->isSignedIntegerType())
691      NewTy = S.Context.SignedCharTy;
692    else
693      NewTy = S.Context.UnsignedCharTy;
694    break;
695  case 16:
696    assert(IntegerMode);
697    if (OldTy->isSignedIntegerType())
698      NewTy = S.Context.ShortTy;
699    else
700      NewTy = S.Context.UnsignedShortTy;
701    break;
702  case 32:
703    if (!IntegerMode)
704      NewTy = S.Context.FloatTy;
705    else if (OldTy->isSignedIntegerType())
706      NewTy = S.Context.IntTy;
707    else
708      NewTy = S.Context.UnsignedIntTy;
709    break;
710  case 64:
711    if (!IntegerMode)
712      NewTy = S.Context.DoubleTy;
713    else if (OldTy->isSignedIntegerType())
714      NewTy = S.Context.LongLongTy;
715    else
716      NewTy = S.Context.UnsignedLongLongTy;
717    break;
718  }
719
720  if (!OldTy->getAsBuiltinType())
721    S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
722  else if (!(IntegerMode && OldTy->isIntegerType()) &&
723           !(!IntegerMode && OldTy->isFloatingType())) {
724    S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
725  }
726
727  // Install the new type.
728  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
729    TD->setUnderlyingType(NewTy);
730  else
731    cast<ValueDecl>(D)->setType(NewTy);
732}
733
734//===----------------------------------------------------------------------===//
735// Top Level Sema Entry Points
736//===----------------------------------------------------------------------===//
737
738/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
739/// the attribute applies to decls.  If the attribute is a type attribute, just
740/// silently ignore it.
741static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
742  switch (Attr.getKind()) {
743  case AttributeList::AT_address_space:
744    // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
745    break;
746  case AttributeList::AT_ext_vector_type:
747    HandleExtVectorTypeAttr(D, Attr, S);
748    break;
749  case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break;
750  case AttributeList::AT_mode:        HandleModeAttr      (D, Attr, S); break;
751  case AttributeList::AT_alias:       HandleAliasAttr     (D, Attr, S); break;
752  case AttributeList::AT_deprecated:  HandleDeprecatedAttr(D, Attr, S); break;
753  case AttributeList::AT_visibility:  HandleVisibilityAttr(D, Attr, S); break;
754  case AttributeList::AT_weak:        HandleWeakAttr      (D, Attr, S); break;
755  case AttributeList::AT_dllimport:   HandleDLLImportAttr (D, Attr, S); break;
756  case AttributeList::AT_dllexport:   HandleDLLExportAttr (D, Attr, S); break;
757  case AttributeList::AT_nothrow:     HandleNothrowAttr   (D, Attr, S); break;
758  case AttributeList::AT_stdcall:     HandleStdCallAttr   (D, Attr, S); break;
759  case AttributeList::AT_fastcall:    HandleFastCallAttr  (D, Attr, S); break;
760  case AttributeList::AT_aligned:     HandleAlignedAttr   (D, Attr, S); break;
761  case AttributeList::AT_packed:      HandlePackedAttr    (D, Attr, S); break;
762  case AttributeList::AT_annotate:    HandleAnnotateAttr  (D, Attr, S); break;
763  case AttributeList::AT_noreturn:    HandleNoReturnAttr  (D, Attr, S); break;
764  case AttributeList::AT_format:      HandleFormatAttr    (D, Attr, S); break;
765  case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
766  case AttributeList::AT_transparent_union:
767    HandleTransparentUnionAttr(D, Attr, S);
768    break;
769  default:
770#if 0
771    // TODO: when we have the full set of attributes, warn about unknown ones.
772    S.Diag(Attr->getLoc(), diag::warn_attribute_ignored,
773           Attr->getName()->getName());
774#endif
775    break;
776  }
777}
778
779/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
780/// attribute list to the specified decl, ignoring any type attributes.
781void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
782  while (AttrList) {
783    ProcessDeclAttribute(D, *AttrList, *this);
784    AttrList = AttrList->getNext();
785  }
786}
787
788
789/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
790/// it, apply them to D.  This is a bit tricky because PD can have attributes
791/// specified in many different places, and we need to find and apply them all.
792void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
793  // Apply decl attributes from the DeclSpec if present.
794  if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
795    ProcessDeclAttributeList(D, Attrs);
796
797  // Walk the declarator structure, applying decl attributes that were in a type
798  // position to the decl itself.  This handles cases like:
799  //   int *__attr__(x)** D;
800  // when X is a decl attribute.
801  for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
802    if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
803      ProcessDeclAttributeList(D, Attrs);
804
805  // Finally, apply any attributes on the decl itself.
806  if (const AttributeList *Attrs = PD.getAttributes())
807    ProcessDeclAttributeList(D, Attrs);
808}
809
810