blob: 3fda03145cd297831e5a149abd976123e2e488a8 [file] [log] [blame]
Chris Lattner6953a072008-06-26 18:38:35 +00001//===--- 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"
Chris Lattnerdc789562008-06-27 22:18:37 +000016#include "clang/Basic/TargetInfo.h"
Chris Lattner6953a072008-06-26 18:38:35 +000017using namespace clang;
18
19static const FunctionTypeProto *getFunctionProto(Decl *d) {
20 QualType Ty;
21
22 if (ValueDecl *decl = dyn_cast<ValueDecl>(d))
23 Ty = decl->getType();
24 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d))
25 Ty = decl->getType();
26 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
27 Ty = decl->getUnderlyingType();
28 else
29 return 0;
30
31 if (Ty->isFunctionPointerType())
32 Ty = Ty->getAsPointerType()->getPointeeType();
33
34 if (const FunctionType *FnTy = Ty->getAsFunctionType())
35 return dyn_cast<FunctionTypeProto>(FnTy->getAsFunctionType());
36
37 return 0;
38}
39
40static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
41 if (!T->isPointerType())
42 return false;
43
44 T = T->getAsPointerType()->getPointeeType().getCanonicalType();
45 ObjCInterfaceType* ClsT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
46
47 if (!ClsT)
48 return false;
49
50 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
51
52 // FIXME: Should we walk the chain of classes?
53 return ClsName == &Ctx.Idents.get("NSString") ||
54 ClsName == &Ctx.Idents.get("NSMutableString");
55}
56
Chris Lattner1c151132008-06-28 23:36:30 +000057void Sema::HandleDeclAttributes(Decl *New, const AttributeList *DeclSpecAttrs,
58 const AttributeList *DeclaratorAttrs) {
59 if (DeclSpecAttrs == 0 && DeclaratorAttrs == 0) return;
Chris Lattner6953a072008-06-26 18:38:35 +000060
Chris Lattner1c151132008-06-28 23:36:30 +000061 while (DeclSpecAttrs) {
62 HandleDeclAttribute(New, *DeclSpecAttrs);
63 DeclSpecAttrs = DeclSpecAttrs->getNext();
64 }
65
66 // If there are any type attributes that were in the declarator, apply them to
67 // its top level type.
68 if (ValueDecl *VD = dyn_cast<ValueDecl>(New)) {
69 QualType DT = VD->getType();
70 ProcessTypeAttributes(DT, DeclaratorAttrs);
71 VD->setType(DT);
72 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(New)) {
73 QualType DT = TD->getUnderlyingType();
74 ProcessTypeAttributes(DT, DeclaratorAttrs);
75 TD->setUnderlyingType(DT);
76 }
77
78 while (DeclaratorAttrs) {
79 HandleDeclAttribute(New, *DeclaratorAttrs);
80 DeclaratorAttrs = DeclaratorAttrs->getNext();
81 }
82}
83
84/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
85/// the attribute applies to decls. If the attribute is a type attribute, just
86/// silently ignore it.
87void Sema::HandleDeclAttribute(Decl *New, const AttributeList &Attr) {
88 switch (Attr.getKind()) {
89 case AttributeList::AT_address_space:
90 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
91 break;
Chris Lattner8ed14aa2008-06-28 23:48:25 +000092 case AttributeList::AT_vector_size:HandleVectorSizeAttribute(New, Attr);break;
Chris Lattner6953a072008-06-26 18:38:35 +000093 case AttributeList::AT_ext_vector_type:
Chris Lattner1c151132008-06-28 23:36:30 +000094 HandleExtVectorTypeAttribute(New, Attr);
Chris Lattner6953a072008-06-26 18:38:35 +000095 break;
Chris Lattner1c151132008-06-28 23:36:30 +000096 case AttributeList::AT_mode: HandleModeAttribute(New, Attr); break;
Chris Lattner6953a072008-06-26 18:38:35 +000097 case AttributeList::AT_alias: HandleAliasAttribute(New, Attr); break;
98 case AttributeList::AT_deprecated: HandleDeprecatedAttribute(New, Attr);break;
99 case AttributeList::AT_visibility: HandleVisibilityAttribute(New, Attr);break;
100 case AttributeList::AT_weak: HandleWeakAttribute(New, Attr); break;
101 case AttributeList::AT_dllimport: HandleDLLImportAttribute(New, Attr); break;
102 case AttributeList::AT_dllexport: HandleDLLExportAttribute(New, Attr); break;
103 case AttributeList::AT_nothrow: HandleNothrowAttribute(New, Attr); break;
104 case AttributeList::AT_stdcall: HandleStdCallAttribute(New, Attr); break;
105 case AttributeList::AT_fastcall: HandleFastCallAttribute(New, Attr); break;
106 case AttributeList::AT_aligned: HandleAlignedAttribute(New, Attr); break;
107 case AttributeList::AT_packed: HandlePackedAttribute(New, Attr); break;
108 case AttributeList::AT_annotate: HandleAnnotateAttribute(New, Attr); break;
109 case AttributeList::AT_noreturn: HandleNoReturnAttribute(New, Attr); break;
110 case AttributeList::AT_format: HandleFormatAttribute(New, Attr); break;
111 case AttributeList::AT_transparent_union:
112 HandleTransparentUnionAttribute(New, Attr);
113 break;
114 default:
115#if 0
116 // TODO: when we have the full set of attributes, warn about unknown ones.
117 Diag(Attr->getLoc(), diag::warn_attribute_ignored,
118 Attr->getName()->getName());
119#endif
120 break;
121 }
122}
123
Chris Lattner1c151132008-06-28 23:36:30 +0000124void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) {
125 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
126 if (tDecl == 0) {
127 Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
128 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000129 }
130
Chris Lattner6953a072008-06-26 18:38:35 +0000131 QualType curType = tDecl->getUnderlyingType();
132 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000133 if (Attr.getNumArgs() != 1) {
134 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000135 std::string("1"));
136 return;
137 }
Chris Lattner1c151132008-06-28 23:36:30 +0000138 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000139 llvm::APSInt vecSize(32);
140 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000141 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000142 "ext_vector_type", sizeExpr->getSourceRange());
143 return;
144 }
145 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
146 // in conjunction with complex types (pointers, arrays, functions, etc.).
147 Type *canonType = curType.getCanonicalType().getTypePtr();
148 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +0000149 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000150 curType.getCanonicalType().getAsString());
151 return;
152 }
153 // unlike gcc's vector_size attribute, the size is specified as the
154 // number of elements, not the number of bytes.
155 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
156
157 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000158 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000159 sizeExpr->getSourceRange());
160 return;
161 }
162 // Instantiate/Install the vector type, the number of elements is > 0.
163 tDecl->setUnderlyingType(Context.getExtVectorType(curType, vectorSize));
164 // Remember this typedef decl, we will need it later for diagnostics.
165 ExtVectorDecls.push_back(tDecl);
166}
167
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000168
169/// HandleVectorSizeAttribute - this attribute is only applicable to
170/// integral and float scalars, although arrays, pointers, and function
171/// return values are allowed in conjunction with this construct. Aggregates
172/// with this attribute are invalid, even if they are of the same size as a
173/// corresponding scalar.
174/// The raw attribute should contain precisely 1 argument, the vector size
175/// for the variable, measured in bytes. If curType and rawAttr are well
176/// formed, this routine will return a new vector type.
177void Sema::HandleVectorSizeAttribute(Decl *D, const AttributeList &Attr) {
178 QualType CurType;
179 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
180 CurType = VD->getType();
181 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
182 CurType = TD->getUnderlyingType();
183 else {
184 Diag(D->getLocation(), diag::err_attr_wrong_decl,std::string("vector_size"),
185 SourceRange(Attr.getLoc(), Attr.getLoc()));
186 return;
187 }
188
189 // Check the attribute arugments.
Chris Lattner1c151132008-06-28 23:36:30 +0000190 if (Attr.getNumArgs() != 1) {
191 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000192 std::string("1"));
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000193 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000194 }
Chris Lattner1c151132008-06-28 23:36:30 +0000195 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000196 llvm::APSInt vecSize(32);
197 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000198 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000199 "vector_size", sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000200 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000201 }
202 // navigate to the base type - we need to provide for vector pointers,
203 // vector arrays, and functions returning vectors.
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000204 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6953a072008-06-26 18:38:35 +0000205
206 if (canonType->isPointerType() || canonType->isArrayType() ||
207 canonType->isFunctionType()) {
208 assert(0 && "HandleVector(): Complex type construction unimplemented");
209 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
210 do {
211 if (PointerType *PT = dyn_cast<PointerType>(canonType))
212 canonType = PT->getPointeeType().getTypePtr();
213 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
214 canonType = AT->getElementType().getTypePtr();
215 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
216 canonType = FT->getResultType().getTypePtr();
217 } while (canonType->isPointerType() || canonType->isArrayType() ||
218 canonType->isFunctionType());
219 */
220 }
221 // the base type must be integer or float.
222 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +0000223 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000224 CurType.getCanonicalType().getAsString());
225 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000226 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000227 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
Chris Lattner6953a072008-06-26 18:38:35 +0000228 // vecSize is specified in bytes - convert to bits.
229 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
230
231 // the vector size needs to be an integral multiple of the type size.
232 if (vectorSize % typeSize) {
Chris Lattner1c151132008-06-28 23:36:30 +0000233 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000234 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000235 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000236 }
237 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000238 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000239 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000240 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000241 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000242
243 // Success! Instantiate the vector type, the number of elements is > 0, and
244 // not required to be a power of 2, unlike GCC.
245 CurType = Context.getVectorType(CurType, vectorSize/typeSize);
246
247 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
248 VD->setType(CurType);
249 else
250 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6953a072008-06-26 18:38:35 +0000251}
252
Chris Lattner1c151132008-06-28 23:36:30 +0000253void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000254 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000255 if (Attr.getNumArgs() > 0) {
256 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000257 std::string("0"));
258 return;
259 }
260
261 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000262 TD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000263 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
264 // If the alignment is less than or equal to 8 bits, the packed attribute
265 // has no effect.
266 if (!FD->getType()->isIncompleteType() &&
267 Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattner1c151132008-06-28 23:36:30 +0000268 Diag(Attr.getLoc(),
Chris Lattner6953a072008-06-26 18:38:35 +0000269 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner1c151132008-06-28 23:36:30 +0000270 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6953a072008-06-26 18:38:35 +0000271 else
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000272 FD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000273 } else
Chris Lattner1c151132008-06-28 23:36:30 +0000274 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
275 Attr.getName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000276}
277
Chris Lattner1c151132008-06-28 23:36:30 +0000278void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000279 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000280 if (Attr.getNumArgs() != 1) {
281 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000282 std::string("1"));
283 return;
284 }
285
Chris Lattner1c151132008-06-28 23:36:30 +0000286 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000287 Arg = Arg->IgnoreParenCasts();
288 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
289
290 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000291 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000292 "alias", std::string("1"));
293 return;
294 }
295
296 const char *Alias = Str->getStrData();
297 unsigned AliasLen = Str->getByteLength();
298
299 // FIXME: check if target symbol exists in current file
300
301 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
302}
303
Chris Lattner1c151132008-06-28 23:36:30 +0000304void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000305 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000306 if (Attr.getNumArgs() != 0) {
307 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000308 std::string("0"));
309 return;
310 }
311
312 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6953a072008-06-26 18:38:35 +0000313 if (!Fn) {
Chris Lattner1c151132008-06-28 23:36:30 +0000314 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000315 "noreturn", "function");
316 return;
317 }
318
319 d->addAttr(new NoReturnAttr());
320}
321
Chris Lattner1c151132008-06-28 23:36:30 +0000322void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000323 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000324 if (Attr.getNumArgs() != 0) {
325 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000326 std::string("0"));
327 return;
328 }
329
330 d->addAttr(new DeprecatedAttr());
331}
332
Chris Lattner1c151132008-06-28 23:36:30 +0000333void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000334 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000335 if (Attr.getNumArgs() != 1) {
336 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000337 std::string("1"));
338 return;
339 }
340
Chris Lattner1c151132008-06-28 23:36:30 +0000341 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000342 Arg = Arg->IgnoreParenCasts();
343 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
344
345 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000346 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000347 "visibility", std::string("1"));
348 return;
349 }
350
351 const char *TypeStr = Str->getStrData();
352 unsigned TypeLen = Str->getByteLength();
353 VisibilityAttr::VisibilityTypes type;
354
355 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
356 type = VisibilityAttr::DefaultVisibility;
357 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
358 type = VisibilityAttr::HiddenVisibility;
359 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
360 type = VisibilityAttr::HiddenVisibility; // FIXME
361 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
362 type = VisibilityAttr::ProtectedVisibility;
363 else {
Chris Lattner1c151132008-06-28 23:36:30 +0000364 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6953a072008-06-26 18:38:35 +0000365 "visibility", TypeStr);
366 return;
367 }
368
369 d->addAttr(new VisibilityAttr(type));
370}
371
Chris Lattner1c151132008-06-28 23:36:30 +0000372void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000373 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000374 if (Attr.getNumArgs() != 0) {
375 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000376 std::string("0"));
377 return;
378 }
379
380 d->addAttr(new WeakAttr());
381}
382
Chris Lattner1c151132008-06-28 23:36:30 +0000383void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000384 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000385 if (Attr.getNumArgs() != 0) {
386 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000387 std::string("0"));
388 return;
389 }
390
391 d->addAttr(new DLLImportAttr());
392}
393
Chris Lattner1c151132008-06-28 23:36:30 +0000394void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000395 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000396 if (Attr.getNumArgs() != 0) {
397 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000398 std::string("0"));
399 return;
400 }
401
402 d->addAttr(new DLLExportAttr());
403}
404
Chris Lattner1c151132008-06-28 23:36:30 +0000405void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000406 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000407 if (Attr.getNumArgs() != 0) {
408 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000409 std::string("0"));
410 return;
411 }
412
413 d->addAttr(new StdCallAttr());
414}
415
Chris Lattner1c151132008-06-28 23:36:30 +0000416void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000417 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000418 if (Attr.getNumArgs() != 0) {
419 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000420 std::string("0"));
421 return;
422 }
423
424 d->addAttr(new FastCallAttr());
425}
426
Chris Lattner1c151132008-06-28 23:36:30 +0000427void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000428 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000429 if (Attr.getNumArgs() != 0) {
430 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000431 std::string("0"));
432 return;
433 }
434
435 d->addAttr(new NoThrowAttr());
436}
437
438/// Handle __attribute__((format(type,idx,firstarg))) attributes
439/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner1c151132008-06-28 23:36:30 +0000440void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000441
Chris Lattner1c151132008-06-28 23:36:30 +0000442 if (!Attr.getParameterName()) {
443 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000444 "format", std::string("1"));
445 return;
446 }
447
Chris Lattner1c151132008-06-28 23:36:30 +0000448 if (Attr.getNumArgs() != 2) {
449 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000450 std::string("3"));
451 return;
452 }
453
454 // GCC ignores the format attribute on K&R style function
455 // prototypes, so we ignore it as well
456 const FunctionTypeProto *proto = getFunctionProto(d);
457
458 if (!proto) {
Chris Lattner1c151132008-06-28 23:36:30 +0000459 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000460 "format", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000461 return;
462 }
463
464 // FIXME: in C++ the implicit 'this' function parameter also counts.
465 // this is needed in order to be compatible with GCC
466 // the index must start in 1 and the limit is numargs+1
467 unsigned NumArgs = proto->getNumArgs();
468 unsigned FirstIdx = 1;
469
Chris Lattner1c151132008-06-28 23:36:30 +0000470 const char *Format = Attr.getParameterName()->getName();
471 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6953a072008-06-26 18:38:35 +0000472
473 // Normalize the argument, __foo__ becomes foo.
474 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
475 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
476 Format += 2;
477 FormatLen -= 4;
478 }
479
480 bool Supported = false;
481 bool is_NSString = false;
482 bool is_strftime = false;
483
484 switch (FormatLen) {
485 default: break;
486 case 5:
487 Supported = !memcmp(Format, "scanf", 5);
488 break;
489 case 6:
490 Supported = !memcmp(Format, "printf", 6);
491 break;
492 case 7:
493 Supported = !memcmp(Format, "strfmon", 7);
494 break;
495 case 8:
496 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
497 (is_NSString = !memcmp(Format, "NSString", 8));
498 break;
499 }
500
501 if (!Supported) {
Chris Lattner1c151132008-06-28 23:36:30 +0000502 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
503 "format", Attr.getParameterName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000504 return;
505 }
506
507 // checks for the 2nd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000508 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000509 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
510 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000511 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000512 "format", std::string("2"), IdxExpr->getSourceRange());
513 return;
514 }
515
516 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000517 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000518 "format", std::string("2"), IdxExpr->getSourceRange());
519 return;
520 }
521
522 // FIXME: Do we need to bounds check?
523 unsigned ArgIdx = Idx.getZExtValue() - 1;
524
525 // make sure the format string is really a string
526 QualType Ty = proto->getArgType(ArgIdx);
527
528 if (is_NSString) {
529 // FIXME: do we need to check if the type is NSString*? What are
530 // the semantics?
531 if (!isNSStringType(Ty, Context)) {
532 // FIXME: Should highlight the actual expression that has the
533 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000534 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6953a072008-06-26 18:38:35 +0000535 IdxExpr->getSourceRange());
536 return;
537 }
538 } else if (!Ty->isPointerType() ||
539 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
540 // FIXME: Should highlight the actual expression that has the
541 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000542 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000543 IdxExpr->getSourceRange());
544 return;
545 }
546
547 // check the 3rd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000548 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6953a072008-06-26 18:38:35 +0000549 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
550 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000551 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000552 "format", std::string("3"), FirstArgExpr->getSourceRange());
553 return;
554 }
555
556 // check if the function is variadic if the 3rd argument non-zero
557 if (FirstArg != 0) {
558 if (proto->isVariadic()) {
559 ++NumArgs; // +1 for ...
560 } else {
561 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
562 return;
563 }
564 }
565
566 // strftime requires FirstArg to be 0 because it doesn't read from any variable
567 // the input is just the current time + the format string
568 if (is_strftime) {
569 if (FirstArg != 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000570 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6953a072008-06-26 18:38:35 +0000571 FirstArgExpr->getSourceRange());
572 return;
573 }
574 // if 0 it disables parameter checking (to use with e.g. va_list)
575 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000576 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000577 "format", std::string("3"), FirstArgExpr->getSourceRange());
578 return;
579 }
580
581 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
582 Idx.getZExtValue(), FirstArg.getZExtValue()));
583}
584
585void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner1c151132008-06-28 23:36:30 +0000586 const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000587 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000588 if (Attr.getNumArgs() != 0) {
589 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000590 std::string("0"));
591 return;
592 }
593
594 TypeDecl *decl = dyn_cast<TypeDecl>(d);
595
596 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000597 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000598 "transparent_union", "union");
599 return;
600 }
601
602 //QualType QTy = Context.getTypeDeclType(decl);
603 //const RecordType *Ty = QTy->getAsUnionType();
604
605// FIXME
606// Ty->addAttr(new TransparentUnionAttr());
607}
608
Chris Lattner1c151132008-06-28 23:36:30 +0000609void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000610 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000611 if (Attr.getNumArgs() != 1) {
612 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000613 std::string("1"));
614 return;
615 }
Chris Lattner1c151132008-06-28 23:36:30 +0000616 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000617 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
618
619 // Make sure that there is a string literal as the annotation's single
620 // argument.
621 if (!SE) {
Chris Lattner1c151132008-06-28 23:36:30 +0000622 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6953a072008-06-26 18:38:35 +0000623 return;
624 }
625 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
626 SE->getByteLength())));
627}
628
Chris Lattner1c151132008-06-28 23:36:30 +0000629void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000630 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000631 if (Attr.getNumArgs() > 1) {
632 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000633 std::string("1"));
634 return;
635 }
636
637 unsigned Align = 0;
Chris Lattner1c151132008-06-28 23:36:30 +0000638 if (Attr.getNumArgs() == 0) {
Chris Lattner6953a072008-06-26 18:38:35 +0000639 // FIXME: This should be the target specific maximum alignment.
640 // (For now we just use 128 bits which is the maximum on X86.
641 Align = 128;
642 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000643 }
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000644
645 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
646 llvm::APSInt Alignment(32);
647 if (!alignmentExpr->isIntegerConstantExpr(Alignment, Context)) {
648 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
649 "aligned", alignmentExpr->getSourceRange());
650 return;
651 }
652 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6953a072008-06-26 18:38:35 +0000653}
Chris Lattnerdc789562008-06-27 22:18:37 +0000654
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000655/// HandleModeAttribute - This attribute modifies the width of a decl with
656/// primitive type.
Chris Lattnerdc789562008-06-27 22:18:37 +0000657///
658/// Despite what would be logical, the mode attribute is a decl attribute,
659/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
660/// 'G' be HImode, not an intermediate pointer.
661///
662void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
663 // This attribute isn't documented, but glibc uses it. It changes
664 // the width of an int or unsigned int to the specified size.
665
666 // Check that there aren't any arguments
667 if (Attr.getNumArgs() != 0) {
668 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
669 std::string("0"));
670 return;
671 }
672
673 IdentifierInfo *Name = Attr.getParameterName();
674 if (!Name) {
675 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
676 return;
677 }
678 const char *Str = Name->getName();
679 unsigned Len = Name->getLength();
680
681 // Normalize the attribute name, __foo__ becomes foo.
682 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
683 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
684 Str += 2;
685 Len -= 4;
686 }
687
688 unsigned DestWidth = 0;
689 bool IntegerMode = true;
690 switch (Len) {
691 case 2:
692 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
693 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
694 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
695 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
696 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
697 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
698 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
699 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
700 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
701 break;
702 case 4:
703 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
704 // pointer on PIC16 and other embedded platforms.
705 if (!memcmp(Str, "word", 4))
706 DestWidth = Context.Target.getPointerWidth(0);
707 if (!memcmp(Str, "byte", 4))
708 DestWidth = Context.Target.getCharWidth();
709 break;
710 case 7:
711 if (!memcmp(Str, "pointer", 7))
712 DestWidth = Context.Target.getPointerWidth(0);
713 break;
714 }
715
716 QualType OldTy;
717 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
718 OldTy = TD->getUnderlyingType();
719 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
720 OldTy = VD->getType();
721 else {
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000722 Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
Chris Lattnerdc789562008-06-27 22:18:37 +0000723 SourceRange(Attr.getLoc(), Attr.getLoc()));
724 return;
725 }
726
727 // FIXME: Need proper fixed-width types
728 QualType NewTy;
729 switch (DestWidth) {
730 case 0:
731 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
732 return;
733 default:
734 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
735 return;
736 case 8:
737 assert(IntegerMode);
738 if (OldTy->isSignedIntegerType())
739 NewTy = Context.SignedCharTy;
740 else
741 NewTy = Context.UnsignedCharTy;
742 break;
743 case 16:
744 assert(IntegerMode);
745 if (OldTy->isSignedIntegerType())
746 NewTy = Context.ShortTy;
747 else
748 NewTy = Context.UnsignedShortTy;
749 break;
750 case 32:
751 if (!IntegerMode)
752 NewTy = Context.FloatTy;
753 else if (OldTy->isSignedIntegerType())
754 NewTy = Context.IntTy;
755 else
756 NewTy = Context.UnsignedIntTy;
757 break;
758 case 64:
759 if (!IntegerMode)
760 NewTy = Context.DoubleTy;
761 else if (OldTy->isSignedIntegerType())
762 NewTy = Context.LongLongTy;
763 else
764 NewTy = Context.UnsignedLongLongTy;
765 break;
766 }
767
768 if (!OldTy->getAsBuiltinType())
769 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
770 else if (!(IntegerMode && OldTy->isIntegerType()) &&
771 !(!IntegerMode && OldTy->isFloatingType())) {
772 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
773 }
774
775 // Install the new type.
776 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
777 TD->setUnderlyingType(NewTy);
778 else
779 cast<ValueDecl>(D)->setType(NewTy);
780}