blob: d2e5c9186b9c74e852c3013c198e4e555d11bb54 [file] [log] [blame]
Chris Lattner6b6b5372008-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 Lattnerfbf13472008-06-27 22:18:37 +000016#include "clang/Basic/TargetInfo.h"
Chris Lattner6b6b5372008-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 Lattner545dd342008-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 Lattner6b6b5372008-06-26 18:38:35 +000060
Chris Lattner545dd342008-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 Lattner065c5a82008-06-28 23:48:25 +000092 case AttributeList::AT_vector_size:HandleVectorSizeAttribute(New, Attr);break;
Chris Lattner6b6b5372008-06-26 18:38:35 +000093 case AttributeList::AT_ext_vector_type:
Chris Lattner545dd342008-06-28 23:36:30 +000094 HandleExtVectorTypeAttribute(New, Attr);
Chris Lattner6b6b5372008-06-26 18:38:35 +000095 break;
Chris Lattner545dd342008-06-28 23:36:30 +000096 case AttributeList::AT_mode: HandleModeAttribute(New, Attr); break;
Chris Lattner6b6b5372008-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 Lattner545dd342008-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 Lattner6b6b5372008-06-26 18:38:35 +0000129 }
130
Chris Lattner6b6b5372008-06-26 18:38:35 +0000131 QualType curType = tDecl->getUnderlyingType();
132 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000133 if (Attr.getNumArgs() != 1) {
134 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000135 std::string("1"));
136 return;
137 }
Chris Lattner545dd342008-06-28 23:36:30 +0000138 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000139 llvm::APSInt vecSize(32);
140 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000141 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-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 Lattner545dd342008-06-28 23:36:30 +0000149 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6b6b5372008-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 Lattner545dd342008-06-28 23:36:30 +0000158 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-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 Lattner065c5a82008-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 Lattner545dd342008-06-28 23:36:30 +0000190 if (Attr.getNumArgs() != 1) {
191 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000192 std::string("1"));
Chris Lattner065c5a82008-06-28 23:48:25 +0000193 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000194 }
Chris Lattner545dd342008-06-28 23:36:30 +0000195 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000196 llvm::APSInt vecSize(32);
197 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000198 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000199 "vector_size", sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000200 return;
Chris Lattner6b6b5372008-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 Lattner065c5a82008-06-28 23:48:25 +0000204 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6b6b5372008-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 Lattner545dd342008-06-28 23:36:30 +0000223 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner065c5a82008-06-28 23:48:25 +0000224 CurType.getCanonicalType().getAsString());
225 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000226 }
Chris Lattner065c5a82008-06-28 23:48:25 +0000227 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
Chris Lattner6b6b5372008-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 Lattner545dd342008-06-28 23:36:30 +0000233 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000234 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000235 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000236 }
237 if (vectorSize == 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000238 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000239 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000240 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000241 }
Chris Lattner065c5a82008-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 Lattner6b6b5372008-06-26 18:38:35 +0000251}
252
Chris Lattner545dd342008-06-28 23:36:30 +0000253void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000254 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000255 if (Attr.getNumArgs() > 0) {
256 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000257 std::string("0"));
258 return;
259 }
260
261 if (TagDecl *TD = dyn_cast<TagDecl>(d))
262 TD->addAttr(new PackedAttr);
263 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 Lattner545dd342008-06-28 23:36:30 +0000268 Diag(Attr.getLoc(),
Chris Lattner6b6b5372008-06-26 18:38:35 +0000269 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner545dd342008-06-28 23:36:30 +0000270 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000271 else
272 FD->addAttr(new PackedAttr);
273 } else
Chris Lattner545dd342008-06-28 23:36:30 +0000274 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
275 Attr.getName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000276}
277
Chris Lattner545dd342008-06-28 23:36:30 +0000278void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000279 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000280 if (Attr.getNumArgs() != 1) {
281 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000282 std::string("1"));
283 return;
284 }
285
Chris Lattner545dd342008-06-28 23:36:30 +0000286 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000287 Arg = Arg->IgnoreParenCasts();
288 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
289
290 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000291 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-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 Lattner545dd342008-06-28 23:36:30 +0000304void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000305 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000306 if (Attr.getNumArgs() != 0) {
307 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000308 std::string("0"));
309 return;
310 }
311
312 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
313
314 if (!Fn) {
Chris Lattner545dd342008-06-28 23:36:30 +0000315 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000316 "noreturn", "function");
317 return;
318 }
319
320 d->addAttr(new NoReturnAttr());
321}
322
Chris Lattner545dd342008-06-28 23:36:30 +0000323void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000324 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000325 if (Attr.getNumArgs() != 0) {
326 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000327 std::string("0"));
328 return;
329 }
330
331 d->addAttr(new DeprecatedAttr());
332}
333
Chris Lattner545dd342008-06-28 23:36:30 +0000334void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000335 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000336 if (Attr.getNumArgs() != 1) {
337 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000338 std::string("1"));
339 return;
340 }
341
Chris Lattner545dd342008-06-28 23:36:30 +0000342 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000343 Arg = Arg->IgnoreParenCasts();
344 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
345
346 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000347 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000348 "visibility", std::string("1"));
349 return;
350 }
351
352 const char *TypeStr = Str->getStrData();
353 unsigned TypeLen = Str->getByteLength();
354 VisibilityAttr::VisibilityTypes type;
355
356 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
357 type = VisibilityAttr::DefaultVisibility;
358 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
359 type = VisibilityAttr::HiddenVisibility;
360 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
361 type = VisibilityAttr::HiddenVisibility; // FIXME
362 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
363 type = VisibilityAttr::ProtectedVisibility;
364 else {
Chris Lattner545dd342008-06-28 23:36:30 +0000365 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000366 "visibility", TypeStr);
367 return;
368 }
369
370 d->addAttr(new VisibilityAttr(type));
371}
372
Chris Lattner545dd342008-06-28 23:36:30 +0000373void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000374 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000375 if (Attr.getNumArgs() != 0) {
376 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000377 std::string("0"));
378 return;
379 }
380
381 d->addAttr(new WeakAttr());
382}
383
Chris Lattner545dd342008-06-28 23:36:30 +0000384void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000385 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000386 if (Attr.getNumArgs() != 0) {
387 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000388 std::string("0"));
389 return;
390 }
391
392 d->addAttr(new DLLImportAttr());
393}
394
Chris Lattner545dd342008-06-28 23:36:30 +0000395void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000396 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000397 if (Attr.getNumArgs() != 0) {
398 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000399 std::string("0"));
400 return;
401 }
402
403 d->addAttr(new DLLExportAttr());
404}
405
Chris Lattner545dd342008-06-28 23:36:30 +0000406void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000407 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000408 if (Attr.getNumArgs() != 0) {
409 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000410 std::string("0"));
411 return;
412 }
413
414 d->addAttr(new StdCallAttr());
415}
416
Chris Lattner545dd342008-06-28 23:36:30 +0000417void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000418 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000419 if (Attr.getNumArgs() != 0) {
420 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000421 std::string("0"));
422 return;
423 }
424
425 d->addAttr(new FastCallAttr());
426}
427
Chris Lattner545dd342008-06-28 23:36:30 +0000428void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000429 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000430 if (Attr.getNumArgs() != 0) {
431 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000432 std::string("0"));
433 return;
434 }
435
436 d->addAttr(new NoThrowAttr());
437}
438
439/// Handle __attribute__((format(type,idx,firstarg))) attributes
440/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner545dd342008-06-28 23:36:30 +0000441void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000442
Chris Lattner545dd342008-06-28 23:36:30 +0000443 if (!Attr.getParameterName()) {
444 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000445 "format", std::string("1"));
446 return;
447 }
448
Chris Lattner545dd342008-06-28 23:36:30 +0000449 if (Attr.getNumArgs() != 2) {
450 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000451 std::string("3"));
452 return;
453 }
454
455 // GCC ignores the format attribute on K&R style function
456 // prototypes, so we ignore it as well
457 const FunctionTypeProto *proto = getFunctionProto(d);
458
459 if (!proto) {
Chris Lattner545dd342008-06-28 23:36:30 +0000460 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000461 "format", "function");
462 return;
463 }
464
465 // FIXME: in C++ the implicit 'this' function parameter also counts.
466 // this is needed in order to be compatible with GCC
467 // the index must start in 1 and the limit is numargs+1
468 unsigned NumArgs = proto->getNumArgs();
469 unsigned FirstIdx = 1;
470
Chris Lattner545dd342008-06-28 23:36:30 +0000471 const char *Format = Attr.getParameterName()->getName();
472 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000473
474 // Normalize the argument, __foo__ becomes foo.
475 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
476 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
477 Format += 2;
478 FormatLen -= 4;
479 }
480
481 bool Supported = false;
482 bool is_NSString = false;
483 bool is_strftime = false;
484
485 switch (FormatLen) {
486 default: break;
487 case 5:
488 Supported = !memcmp(Format, "scanf", 5);
489 break;
490 case 6:
491 Supported = !memcmp(Format, "printf", 6);
492 break;
493 case 7:
494 Supported = !memcmp(Format, "strfmon", 7);
495 break;
496 case 8:
497 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
498 (is_NSString = !memcmp(Format, "NSString", 8));
499 break;
500 }
501
502 if (!Supported) {
Chris Lattner545dd342008-06-28 23:36:30 +0000503 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
504 "format", Attr.getParameterName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000505 return;
506 }
507
508 // checks for the 2nd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000509 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000510 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
511 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000512 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000513 "format", std::string("2"), IdxExpr->getSourceRange());
514 return;
515 }
516
517 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000518 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000519 "format", std::string("2"), IdxExpr->getSourceRange());
520 return;
521 }
522
523 // FIXME: Do we need to bounds check?
524 unsigned ArgIdx = Idx.getZExtValue() - 1;
525
526 // make sure the format string is really a string
527 QualType Ty = proto->getArgType(ArgIdx);
528
529 if (is_NSString) {
530 // FIXME: do we need to check if the type is NSString*? What are
531 // the semantics?
532 if (!isNSStringType(Ty, Context)) {
533 // FIXME: Should highlight the actual expression that has the
534 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000535 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000536 IdxExpr->getSourceRange());
537 return;
538 }
539 } else if (!Ty->isPointerType() ||
540 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
541 // FIXME: Should highlight the actual expression that has the
542 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000543 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000544 IdxExpr->getSourceRange());
545 return;
546 }
547
548 // check the 3rd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000549 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000550 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
551 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000552 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000553 "format", std::string("3"), FirstArgExpr->getSourceRange());
554 return;
555 }
556
557 // check if the function is variadic if the 3rd argument non-zero
558 if (FirstArg != 0) {
559 if (proto->isVariadic()) {
560 ++NumArgs; // +1 for ...
561 } else {
562 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
563 return;
564 }
565 }
566
567 // strftime requires FirstArg to be 0 because it doesn't read from any variable
568 // the input is just the current time + the format string
569 if (is_strftime) {
570 if (FirstArg != 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000571 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000572 FirstArgExpr->getSourceRange());
573 return;
574 }
575 // if 0 it disables parameter checking (to use with e.g. va_list)
576 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000577 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000578 "format", std::string("3"), FirstArgExpr->getSourceRange());
579 return;
580 }
581
582 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
583 Idx.getZExtValue(), FirstArg.getZExtValue()));
584}
585
586void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner545dd342008-06-28 23:36:30 +0000587 const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000588 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000589 if (Attr.getNumArgs() != 0) {
590 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000591 std::string("0"));
592 return;
593 }
594
595 TypeDecl *decl = dyn_cast<TypeDecl>(d);
596
597 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000598 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000599 "transparent_union", "union");
600 return;
601 }
602
603 //QualType QTy = Context.getTypeDeclType(decl);
604 //const RecordType *Ty = QTy->getAsUnionType();
605
606// FIXME
607// Ty->addAttr(new TransparentUnionAttr());
608}
609
Chris Lattner545dd342008-06-28 23:36:30 +0000610void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000611 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000612 if (Attr.getNumArgs() != 1) {
613 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000614 std::string("1"));
615 return;
616 }
Chris Lattner545dd342008-06-28 23:36:30 +0000617 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000618 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
619
620 // Make sure that there is a string literal as the annotation's single
621 // argument.
622 if (!SE) {
Chris Lattner545dd342008-06-28 23:36:30 +0000623 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000624 return;
625 }
626 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
627 SE->getByteLength())));
628}
629
Chris Lattner545dd342008-06-28 23:36:30 +0000630void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000631 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000632 if (Attr.getNumArgs() > 1) {
633 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000634 std::string("1"));
635 return;
636 }
637
638 unsigned Align = 0;
639
Chris Lattner545dd342008-06-28 23:36:30 +0000640 if (Attr.getNumArgs() == 0) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000641 // FIXME: This should be the target specific maximum alignment.
642 // (For now we just use 128 bits which is the maximum on X86.
643 Align = 128;
644 return;
645 } else {
Chris Lattner545dd342008-06-28 23:36:30 +0000646 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000647 llvm::APSInt alignment(32);
648 if (!alignmentExpr->isIntegerConstantExpr(alignment, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000649 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000650 "aligned", alignmentExpr->getSourceRange());
651 return;
652 }
653
654 Align = alignment.getZExtValue() * 8;
655 }
656
657 d->addAttr(new AlignedAttr(Align));
658}
Chris Lattnerfbf13472008-06-27 22:18:37 +0000659
Chris Lattner065c5a82008-06-28 23:48:25 +0000660/// HandleModeAttribute - This attribute modifies the width of a decl with
661/// primitive type.
Chris Lattnerfbf13472008-06-27 22:18:37 +0000662///
663/// Despite what would be logical, the mode attribute is a decl attribute,
664/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
665/// 'G' be HImode, not an intermediate pointer.
666///
667void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
668 // This attribute isn't documented, but glibc uses it. It changes
669 // the width of an int or unsigned int to the specified size.
670
671 // Check that there aren't any arguments
672 if (Attr.getNumArgs() != 0) {
673 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
674 std::string("0"));
675 return;
676 }
677
678 IdentifierInfo *Name = Attr.getParameterName();
679 if (!Name) {
680 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
681 return;
682 }
683 const char *Str = Name->getName();
684 unsigned Len = Name->getLength();
685
686 // Normalize the attribute name, __foo__ becomes foo.
687 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
688 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
689 Str += 2;
690 Len -= 4;
691 }
692
693 unsigned DestWidth = 0;
694 bool IntegerMode = true;
695 switch (Len) {
696 case 2:
697 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
698 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
699 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
700 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
701 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
702 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
703 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
704 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
705 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
706 break;
707 case 4:
708 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
709 // pointer on PIC16 and other embedded platforms.
710 if (!memcmp(Str, "word", 4))
711 DestWidth = Context.Target.getPointerWidth(0);
712 if (!memcmp(Str, "byte", 4))
713 DestWidth = Context.Target.getCharWidth();
714 break;
715 case 7:
716 if (!memcmp(Str, "pointer", 7))
717 DestWidth = Context.Target.getPointerWidth(0);
718 break;
719 }
720
721 QualType OldTy;
722 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
723 OldTy = TD->getUnderlyingType();
724 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
725 OldTy = VD->getType();
726 else {
Chris Lattner065c5a82008-06-28 23:48:25 +0000727 Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
Chris Lattnerfbf13472008-06-27 22:18:37 +0000728 SourceRange(Attr.getLoc(), Attr.getLoc()));
729 return;
730 }
731
732 // FIXME: Need proper fixed-width types
733 QualType NewTy;
734 switch (DestWidth) {
735 case 0:
736 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
737 return;
738 default:
739 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
740 return;
741 case 8:
742 assert(IntegerMode);
743 if (OldTy->isSignedIntegerType())
744 NewTy = Context.SignedCharTy;
745 else
746 NewTy = Context.UnsignedCharTy;
747 break;
748 case 16:
749 assert(IntegerMode);
750 if (OldTy->isSignedIntegerType())
751 NewTy = Context.ShortTy;
752 else
753 NewTy = Context.UnsignedShortTy;
754 break;
755 case 32:
756 if (!IntegerMode)
757 NewTy = Context.FloatTy;
758 else if (OldTy->isSignedIntegerType())
759 NewTy = Context.IntTy;
760 else
761 NewTy = Context.UnsignedIntTy;
762 break;
763 case 64:
764 if (!IntegerMode)
765 NewTy = Context.DoubleTy;
766 else if (OldTy->isSignedIntegerType())
767 NewTy = Context.LongLongTy;
768 else
769 NewTy = Context.UnsignedLongLongTy;
770 break;
771 }
772
773 if (!OldTy->getAsBuiltinType())
774 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
775 else if (!(IntegerMode && OldTy->isIntegerType()) &&
776 !(!IntegerMode && OldTy->isFloatingType())) {
777 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
778 }
779
780 // Install the new type.
781 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
782 TD->setUnderlyingType(NewTy);
783 else
784 cast<ValueDecl>(D)->setType(NewTy);
785}