blob: 28905314ee8dc7b21e4ffb628a55561ae6b84b1b [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
Chris Lattnere5c5ee12008-06-29 00:16:31 +000019//===----------------------------------------------------------------------===//
20// Helper functions
21//===----------------------------------------------------------------------===//
22
Chris Lattner6b6b5372008-06-26 18:38:35 +000023static const FunctionTypeProto *getFunctionProto(Decl *d) {
24 QualType Ty;
Chris Lattner6b6b5372008-06-26 18:38:35 +000025 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
Chris Lattnere5c5ee12008-06-29 00:16:31 +000060//===----------------------------------------------------------------------===//
61// Top Level Sema Entry Points
62//===----------------------------------------------------------------------===//
Chris Lattnerf2e4bd52008-06-28 23:58:55 +000063
Chris Lattnere5c5ee12008-06-29 00:16:31 +000064/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
65/// it, apply them to D. This is a bit tricky because PD can have attributes
66/// specified in many different places, and we need to find and apply them all.
67void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) {
68 // Apply decl attributes from the DeclSpec if present.
69 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
70 ProcessDeclAttributeList(D, Attrs);
71
72 // Walk the declarator structure, applying decl attributes that were in a type
73 // position to the decl itself. This handles cases like:
74 // int *__attr__(x)** D;
75 // when X is a decl attribute.
76 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
77 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
78 ProcessDeclAttributeList(D, Attrs);
Chris Lattner545dd342008-06-28 23:36:30 +000079
Chris Lattnere5c5ee12008-06-29 00:16:31 +000080 // Finally, apply any attributes on the decl itself.
81 if (const AttributeList *Attrs = PD.getAttributes()) {
82 ProcessDeclAttributeList(D, Attrs);
83
84 // If there are any type attributes that were in the declarator, apply them to
85 // its top-level type.
86 // FIXME: we shouldn't allow type attributes here. :(
87 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
88 QualType DT = VD->getType();
89 ProcessTypeAttributes(DT, Attrs);
90 VD->setType(DT);
91 } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
92 QualType DT = TD->getUnderlyingType();
93 ProcessTypeAttributes(DT, Attrs);
94 TD->setUnderlyingType(DT);
95 }
96 // FIXME: field decl?
Chris Lattner545dd342008-06-28 23:36:30 +000097 }
Chris Lattnerf2e4bd52008-06-28 23:58:55 +000098}
99
100/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
101/// attribute list to the specified decl, ignoring any type attributes.
102void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
103 while (AttrList) {
104 ProcessDeclAttribute(D, *AttrList);
105 AttrList = AttrList->getNext();
Chris Lattner545dd342008-06-28 23:36:30 +0000106 }
107}
108
109/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
110/// the attribute applies to decls. If the attribute is a type attribute, just
111/// silently ignore it.
Chris Lattnerf2e4bd52008-06-28 23:58:55 +0000112void Sema::ProcessDeclAttribute(Decl *D, const AttributeList &Attr) {
Chris Lattner545dd342008-06-28 23:36:30 +0000113 switch (Attr.getKind()) {
114 case AttributeList::AT_address_space:
115 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
116 break;
Chris Lattnerf2e4bd52008-06-28 23:58:55 +0000117 case AttributeList::AT_vector_size: HandleVectorSizeAttribute(D, Attr); break;
118 case AttributeList::AT_ext_vector_type:
119 HandleExtVectorTypeAttribute(D, Attr);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000120 break;
Chris Lattnerf2e4bd52008-06-28 23:58:55 +0000121 case AttributeList::AT_mode: HandleModeAttribute(D, Attr); break;
122 case AttributeList::AT_alias: HandleAliasAttribute(D, Attr); break;
123 case AttributeList::AT_deprecated: HandleDeprecatedAttribute(D, Attr);break;
124 case AttributeList::AT_visibility: HandleVisibilityAttribute(D, Attr);break;
125 case AttributeList::AT_weak: HandleWeakAttribute(D, Attr); break;
126 case AttributeList::AT_dllimport: HandleDLLImportAttribute(D, Attr); break;
127 case AttributeList::AT_dllexport: HandleDLLExportAttribute(D, Attr); break;
128 case AttributeList::AT_nothrow: HandleNothrowAttribute(D, Attr); break;
129 case AttributeList::AT_stdcall: HandleStdCallAttribute(D, Attr); break;
130 case AttributeList::AT_fastcall: HandleFastCallAttribute(D, Attr); break;
131 case AttributeList::AT_aligned: HandleAlignedAttribute(D, Attr); break;
132 case AttributeList::AT_packed: HandlePackedAttribute(D, Attr); break;
133 case AttributeList::AT_annotate: HandleAnnotateAttribute(D, Attr); break;
134 case AttributeList::AT_noreturn: HandleNoReturnAttribute(D, Attr); break;
135 case AttributeList::AT_format: HandleFormatAttribute(D, Attr); break;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000136 case AttributeList::AT_transparent_union:
Chris Lattnerf2e4bd52008-06-28 23:58:55 +0000137 HandleTransparentUnionAttribute(D, Attr);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000138 break;
139 default:
140#if 0
141 // TODO: when we have the full set of attributes, warn about unknown ones.
142 Diag(Attr->getLoc(), diag::warn_attribute_ignored,
143 Attr->getName()->getName());
144#endif
145 break;
146 }
147}
148
Chris Lattnere5c5ee12008-06-29 00:16:31 +0000149//===----------------------------------------------------------------------===//
150// Attribute Implementations
151//===----------------------------------------------------------------------===//
152
Chris Lattner545dd342008-06-28 23:36:30 +0000153void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) {
154 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
155 if (tDecl == 0) {
156 Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
157 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000158 }
159
Chris Lattner6b6b5372008-06-26 18:38:35 +0000160 QualType curType = tDecl->getUnderlyingType();
161 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000162 if (Attr.getNumArgs() != 1) {
163 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000164 std::string("1"));
165 return;
166 }
Chris Lattner545dd342008-06-28 23:36:30 +0000167 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000168 llvm::APSInt vecSize(32);
169 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000170 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000171 "ext_vector_type", sizeExpr->getSourceRange());
172 return;
173 }
174 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
175 // in conjunction with complex types (pointers, arrays, functions, etc.).
176 Type *canonType = curType.getCanonicalType().getTypePtr();
177 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner545dd342008-06-28 23:36:30 +0000178 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000179 curType.getCanonicalType().getAsString());
180 return;
181 }
182 // unlike gcc's vector_size attribute, the size is specified as the
183 // number of elements, not the number of bytes.
184 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
185
186 if (vectorSize == 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000187 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000188 sizeExpr->getSourceRange());
189 return;
190 }
191 // Instantiate/Install the vector type, the number of elements is > 0.
192 tDecl->setUnderlyingType(Context.getExtVectorType(curType, vectorSize));
193 // Remember this typedef decl, we will need it later for diagnostics.
194 ExtVectorDecls.push_back(tDecl);
195}
196
Chris Lattner065c5a82008-06-28 23:48:25 +0000197
198/// HandleVectorSizeAttribute - this attribute is only applicable to
199/// integral and float scalars, although arrays, pointers, and function
200/// return values are allowed in conjunction with this construct. Aggregates
201/// with this attribute are invalid, even if they are of the same size as a
202/// corresponding scalar.
203/// The raw attribute should contain precisely 1 argument, the vector size
204/// for the variable, measured in bytes. If curType and rawAttr are well
205/// formed, this routine will return a new vector type.
206void Sema::HandleVectorSizeAttribute(Decl *D, const AttributeList &Attr) {
207 QualType CurType;
208 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
209 CurType = VD->getType();
210 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
211 CurType = TD->getUnderlyingType();
212 else {
213 Diag(D->getLocation(), diag::err_attr_wrong_decl,std::string("vector_size"),
214 SourceRange(Attr.getLoc(), Attr.getLoc()));
215 return;
216 }
217
218 // Check the attribute arugments.
Chris Lattner545dd342008-06-28 23:36:30 +0000219 if (Attr.getNumArgs() != 1) {
220 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000221 std::string("1"));
Chris Lattner065c5a82008-06-28 23:48:25 +0000222 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000223 }
Chris Lattner545dd342008-06-28 23:36:30 +0000224 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000225 llvm::APSInt vecSize(32);
226 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000227 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000228 "vector_size", sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000229 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000230 }
231 // navigate to the base type - we need to provide for vector pointers,
232 // vector arrays, and functions returning vectors.
Chris Lattner065c5a82008-06-28 23:48:25 +0000233 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000234
235 if (canonType->isPointerType() || canonType->isArrayType() ||
236 canonType->isFunctionType()) {
237 assert(0 && "HandleVector(): Complex type construction unimplemented");
238 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
239 do {
240 if (PointerType *PT = dyn_cast<PointerType>(canonType))
241 canonType = PT->getPointeeType().getTypePtr();
242 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
243 canonType = AT->getElementType().getTypePtr();
244 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
245 canonType = FT->getResultType().getTypePtr();
246 } while (canonType->isPointerType() || canonType->isArrayType() ||
247 canonType->isFunctionType());
248 */
249 }
250 // the base type must be integer or float.
251 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner545dd342008-06-28 23:36:30 +0000252 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner065c5a82008-06-28 23:48:25 +0000253 CurType.getCanonicalType().getAsString());
254 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000255 }
Chris Lattner065c5a82008-06-28 23:48:25 +0000256 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000257 // vecSize is specified in bytes - convert to bits.
258 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
259
260 // the vector size needs to be an integral multiple of the type size.
261 if (vectorSize % typeSize) {
Chris Lattner545dd342008-06-28 23:36:30 +0000262 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000263 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000264 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000265 }
266 if (vectorSize == 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000267 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000268 sizeExpr->getSourceRange());
Chris Lattner065c5a82008-06-28 23:48:25 +0000269 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000270 }
Chris Lattner065c5a82008-06-28 23:48:25 +0000271
272 // Success! Instantiate the vector type, the number of elements is > 0, and
273 // not required to be a power of 2, unlike GCC.
274 CurType = Context.getVectorType(CurType, vectorSize/typeSize);
275
276 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
277 VD->setType(CurType);
278 else
279 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000280}
281
Chris Lattner545dd342008-06-28 23:36:30 +0000282void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000283 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000284 if (Attr.getNumArgs() > 0) {
285 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000286 std::string("0"));
287 return;
288 }
289
290 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattner49e2d342008-06-28 23:50:44 +0000291 TD->addAttr(new PackedAttr());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000292 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
293 // If the alignment is less than or equal to 8 bits, the packed attribute
294 // has no effect.
295 if (!FD->getType()->isIncompleteType() &&
296 Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattner545dd342008-06-28 23:36:30 +0000297 Diag(Attr.getLoc(),
Chris Lattner6b6b5372008-06-26 18:38:35 +0000298 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner545dd342008-06-28 23:36:30 +0000299 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000300 else
Chris Lattner49e2d342008-06-28 23:50:44 +0000301 FD->addAttr(new PackedAttr());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000302 } else
Chris Lattner545dd342008-06-28 23:36:30 +0000303 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
304 Attr.getName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000305}
306
Chris Lattner545dd342008-06-28 23:36:30 +0000307void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000308 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000309 if (Attr.getNumArgs() != 1) {
310 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000311 std::string("1"));
312 return;
313 }
314
Chris Lattner545dd342008-06-28 23:36:30 +0000315 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000316 Arg = Arg->IgnoreParenCasts();
317 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
318
319 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000320 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000321 "alias", std::string("1"));
322 return;
323 }
324
325 const char *Alias = Str->getStrData();
326 unsigned AliasLen = Str->getByteLength();
327
328 // FIXME: check if target symbol exists in current file
329
330 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
331}
332
Chris Lattner545dd342008-06-28 23:36:30 +0000333void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000334 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000335 if (Attr.getNumArgs() != 0) {
336 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000337 std::string("0"));
338 return;
339 }
340
341 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000342 if (!Fn) {
Chris Lattner545dd342008-06-28 23:36:30 +0000343 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000344 "noreturn", "function");
345 return;
346 }
347
348 d->addAttr(new NoReturnAttr());
349}
350
Chris Lattner545dd342008-06-28 23:36:30 +0000351void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000352 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000353 if (Attr.getNumArgs() != 0) {
354 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000355 std::string("0"));
356 return;
357 }
358
359 d->addAttr(new DeprecatedAttr());
360}
361
Chris Lattner545dd342008-06-28 23:36:30 +0000362void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000363 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000364 if (Attr.getNumArgs() != 1) {
365 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000366 std::string("1"));
367 return;
368 }
369
Chris Lattner545dd342008-06-28 23:36:30 +0000370 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000371 Arg = Arg->IgnoreParenCasts();
372 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
373
374 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000375 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000376 "visibility", std::string("1"));
377 return;
378 }
379
380 const char *TypeStr = Str->getStrData();
381 unsigned TypeLen = Str->getByteLength();
382 VisibilityAttr::VisibilityTypes type;
383
384 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
385 type = VisibilityAttr::DefaultVisibility;
386 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
387 type = VisibilityAttr::HiddenVisibility;
388 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
389 type = VisibilityAttr::HiddenVisibility; // FIXME
390 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
391 type = VisibilityAttr::ProtectedVisibility;
392 else {
Chris Lattner545dd342008-06-28 23:36:30 +0000393 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000394 "visibility", TypeStr);
395 return;
396 }
397
398 d->addAttr(new VisibilityAttr(type));
399}
400
Chris Lattner545dd342008-06-28 23:36:30 +0000401void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000402 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000403 if (Attr.getNumArgs() != 0) {
404 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000405 std::string("0"));
406 return;
407 }
408
409 d->addAttr(new WeakAttr());
410}
411
Chris Lattner545dd342008-06-28 23:36:30 +0000412void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000413 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000414 if (Attr.getNumArgs() != 0) {
415 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000416 std::string("0"));
417 return;
418 }
419
420 d->addAttr(new DLLImportAttr());
421}
422
Chris Lattner545dd342008-06-28 23:36:30 +0000423void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000424 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000425 if (Attr.getNumArgs() != 0) {
426 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000427 std::string("0"));
428 return;
429 }
430
431 d->addAttr(new DLLExportAttr());
432}
433
Chris Lattner545dd342008-06-28 23:36:30 +0000434void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000435 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000436 if (Attr.getNumArgs() != 0) {
437 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000438 std::string("0"));
439 return;
440 }
441
442 d->addAttr(new StdCallAttr());
443}
444
Chris Lattner545dd342008-06-28 23:36:30 +0000445void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000446 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000447 if (Attr.getNumArgs() != 0) {
448 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000449 std::string("0"));
450 return;
451 }
452
453 d->addAttr(new FastCallAttr());
454}
455
Chris Lattner545dd342008-06-28 23:36:30 +0000456void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000457 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000458 if (Attr.getNumArgs() != 0) {
459 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000460 std::string("0"));
461 return;
462 }
463
464 d->addAttr(new NoThrowAttr());
465}
466
467/// Handle __attribute__((format(type,idx,firstarg))) attributes
468/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner545dd342008-06-28 23:36:30 +0000469void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000470
Chris Lattner545dd342008-06-28 23:36:30 +0000471 if (!Attr.getParameterName()) {
472 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000473 "format", std::string("1"));
474 return;
475 }
476
Chris Lattner545dd342008-06-28 23:36:30 +0000477 if (Attr.getNumArgs() != 2) {
478 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000479 std::string("3"));
480 return;
481 }
482
483 // GCC ignores the format attribute on K&R style function
484 // prototypes, so we ignore it as well
485 const FunctionTypeProto *proto = getFunctionProto(d);
486
487 if (!proto) {
Chris Lattner545dd342008-06-28 23:36:30 +0000488 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner49e2d342008-06-28 23:50:44 +0000489 "format", "function");
Chris Lattner6b6b5372008-06-26 18:38:35 +0000490 return;
491 }
492
493 // FIXME: in C++ the implicit 'this' function parameter also counts.
494 // this is needed in order to be compatible with GCC
495 // the index must start in 1 and the limit is numargs+1
496 unsigned NumArgs = proto->getNumArgs();
497 unsigned FirstIdx = 1;
498
Chris Lattner545dd342008-06-28 23:36:30 +0000499 const char *Format = Attr.getParameterName()->getName();
500 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000501
502 // Normalize the argument, __foo__ becomes foo.
503 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
504 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
505 Format += 2;
506 FormatLen -= 4;
507 }
508
509 bool Supported = false;
510 bool is_NSString = false;
511 bool is_strftime = false;
512
513 switch (FormatLen) {
514 default: break;
515 case 5:
516 Supported = !memcmp(Format, "scanf", 5);
517 break;
518 case 6:
519 Supported = !memcmp(Format, "printf", 6);
520 break;
521 case 7:
522 Supported = !memcmp(Format, "strfmon", 7);
523 break;
524 case 8:
525 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
526 (is_NSString = !memcmp(Format, "NSString", 8));
527 break;
528 }
529
530 if (!Supported) {
Chris Lattner545dd342008-06-28 23:36:30 +0000531 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
532 "format", Attr.getParameterName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000533 return;
534 }
535
536 // checks for the 2nd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000537 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000538 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
539 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000540 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000541 "format", std::string("2"), IdxExpr->getSourceRange());
542 return;
543 }
544
545 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000546 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000547 "format", std::string("2"), IdxExpr->getSourceRange());
548 return;
549 }
550
551 // FIXME: Do we need to bounds check?
552 unsigned ArgIdx = Idx.getZExtValue() - 1;
553
554 // make sure the format string is really a string
555 QualType Ty = proto->getArgType(ArgIdx);
556
557 if (is_NSString) {
558 // FIXME: do we need to check if the type is NSString*? What are
559 // the semantics?
560 if (!isNSStringType(Ty, Context)) {
561 // FIXME: Should highlight the actual expression that has the
562 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000563 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000564 IdxExpr->getSourceRange());
565 return;
566 }
567 } else if (!Ty->isPointerType() ||
568 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
569 // FIXME: Should highlight the actual expression that has the
570 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000571 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000572 IdxExpr->getSourceRange());
573 return;
574 }
575
576 // check the 3rd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000577 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000578 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
579 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000580 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000581 "format", std::string("3"), FirstArgExpr->getSourceRange());
582 return;
583 }
584
585 // check if the function is variadic if the 3rd argument non-zero
586 if (FirstArg != 0) {
587 if (proto->isVariadic()) {
588 ++NumArgs; // +1 for ...
589 } else {
590 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
591 return;
592 }
593 }
594
595 // strftime requires FirstArg to be 0 because it doesn't read from any variable
596 // the input is just the current time + the format string
597 if (is_strftime) {
598 if (FirstArg != 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000599 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000600 FirstArgExpr->getSourceRange());
601 return;
602 }
603 // if 0 it disables parameter checking (to use with e.g. va_list)
604 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000605 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000606 "format", std::string("3"), FirstArgExpr->getSourceRange());
607 return;
608 }
609
610 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
611 Idx.getZExtValue(), FirstArg.getZExtValue()));
612}
613
614void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner545dd342008-06-28 23:36:30 +0000615 const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000616 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000617 if (Attr.getNumArgs() != 0) {
618 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000619 std::string("0"));
620 return;
621 }
622
623 TypeDecl *decl = dyn_cast<TypeDecl>(d);
624
625 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000626 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000627 "transparent_union", "union");
628 return;
629 }
630
631 //QualType QTy = Context.getTypeDeclType(decl);
632 //const RecordType *Ty = QTy->getAsUnionType();
633
634// FIXME
635// Ty->addAttr(new TransparentUnionAttr());
636}
637
Chris Lattner545dd342008-06-28 23:36:30 +0000638void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000639 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000640 if (Attr.getNumArgs() != 1) {
641 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000642 std::string("1"));
643 return;
644 }
Chris Lattner545dd342008-06-28 23:36:30 +0000645 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000646 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
647
648 // Make sure that there is a string literal as the annotation's single
649 // argument.
650 if (!SE) {
Chris Lattner545dd342008-06-28 23:36:30 +0000651 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000652 return;
653 }
654 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
655 SE->getByteLength())));
656}
657
Chris Lattner545dd342008-06-28 23:36:30 +0000658void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000659 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000660 if (Attr.getNumArgs() > 1) {
661 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000662 std::string("1"));
663 return;
664 }
665
666 unsigned Align = 0;
Chris Lattner545dd342008-06-28 23:36:30 +0000667 if (Attr.getNumArgs() == 0) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000668 // FIXME: This should be the target specific maximum alignment.
669 // (For now we just use 128 bits which is the maximum on X86.
670 Align = 128;
671 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000672 }
Chris Lattner49e2d342008-06-28 23:50:44 +0000673
674 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
675 llvm::APSInt Alignment(32);
676 if (!alignmentExpr->isIntegerConstantExpr(Alignment, Context)) {
677 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
678 "aligned", alignmentExpr->getSourceRange());
679 return;
680 }
681 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000682}
Chris Lattnerfbf13472008-06-27 22:18:37 +0000683
Chris Lattner065c5a82008-06-28 23:48:25 +0000684/// HandleModeAttribute - This attribute modifies the width of a decl with
685/// primitive type.
Chris Lattnerfbf13472008-06-27 22:18:37 +0000686///
687/// Despite what would be logical, the mode attribute is a decl attribute,
688/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
689/// 'G' be HImode, not an intermediate pointer.
690///
691void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
692 // This attribute isn't documented, but glibc uses it. It changes
693 // the width of an int or unsigned int to the specified size.
694
695 // Check that there aren't any arguments
696 if (Attr.getNumArgs() != 0) {
697 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
698 std::string("0"));
699 return;
700 }
701
702 IdentifierInfo *Name = Attr.getParameterName();
703 if (!Name) {
704 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
705 return;
706 }
707 const char *Str = Name->getName();
708 unsigned Len = Name->getLength();
709
710 // Normalize the attribute name, __foo__ becomes foo.
711 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
712 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
713 Str += 2;
714 Len -= 4;
715 }
716
717 unsigned DestWidth = 0;
718 bool IntegerMode = true;
719 switch (Len) {
720 case 2:
721 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
722 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
723 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
724 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
725 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
726 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
727 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
728 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
729 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
730 break;
731 case 4:
732 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
733 // pointer on PIC16 and other embedded platforms.
734 if (!memcmp(Str, "word", 4))
735 DestWidth = Context.Target.getPointerWidth(0);
736 if (!memcmp(Str, "byte", 4))
737 DestWidth = Context.Target.getCharWidth();
738 break;
739 case 7:
740 if (!memcmp(Str, "pointer", 7))
741 DestWidth = Context.Target.getPointerWidth(0);
742 break;
743 }
744
745 QualType OldTy;
746 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
747 OldTy = TD->getUnderlyingType();
748 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
749 OldTy = VD->getType();
750 else {
Chris Lattner065c5a82008-06-28 23:48:25 +0000751 Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
Chris Lattnerfbf13472008-06-27 22:18:37 +0000752 SourceRange(Attr.getLoc(), Attr.getLoc()));
753 return;
754 }
755
756 // FIXME: Need proper fixed-width types
757 QualType NewTy;
758 switch (DestWidth) {
759 case 0:
760 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
761 return;
762 default:
763 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
764 return;
765 case 8:
766 assert(IntegerMode);
767 if (OldTy->isSignedIntegerType())
768 NewTy = Context.SignedCharTy;
769 else
770 NewTy = Context.UnsignedCharTy;
771 break;
772 case 16:
773 assert(IntegerMode);
774 if (OldTy->isSignedIntegerType())
775 NewTy = Context.ShortTy;
776 else
777 NewTy = Context.UnsignedShortTy;
778 break;
779 case 32:
780 if (!IntegerMode)
781 NewTy = Context.FloatTy;
782 else if (OldTy->isSignedIntegerType())
783 NewTy = Context.IntTy;
784 else
785 NewTy = Context.UnsignedIntTy;
786 break;
787 case 64:
788 if (!IntegerMode)
789 NewTy = Context.DoubleTy;
790 else if (OldTy->isSignedIntegerType())
791 NewTy = Context.LongLongTy;
792 else
793 NewTy = Context.UnsignedLongLongTy;
794 break;
795 }
796
797 if (!OldTy->getAsBuiltinType())
798 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
799 else if (!(IntegerMode && OldTy->isIntegerType()) &&
800 !(!IntegerMode && OldTy->isFloatingType())) {
801 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
802 }
803
804 // Install the new type.
805 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
806 TD->setUnderlyingType(NewTy);
807 else
808 cast<ValueDecl>(D)->setType(NewTy);
809}