blob: 9f63c936e905ea36c8444c7ba55569981ffe2b5c [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
Chris Lattner2024f0a2008-06-29 00:16:31 +000019//===----------------------------------------------------------------------===//
20// Helper functions
21//===----------------------------------------------------------------------===//
22
Chris Lattner6953a072008-06-26 18:38:35 +000023static const FunctionTypeProto *getFunctionProto(Decl *d) {
24 QualType Ty;
Chris Lattner6953a072008-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 Lattner2024f0a2008-06-29 00:16:31 +000060//===----------------------------------------------------------------------===//
61// Top Level Sema Entry Points
62//===----------------------------------------------------------------------===//
Chris Lattnerd7e83d82008-06-28 23:58:55 +000063
Chris Lattner2024f0a2008-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 Lattner1c151132008-06-28 23:36:30 +000079
Chris Lattner2024f0a2008-06-29 00:16:31 +000080 // Finally, apply any attributes on the decl itself.
Chris Lattnerf9e90cc2008-06-29 00:19:33 +000081 if (const AttributeList *Attrs = PD.getAttributes())
Chris Lattner2024f0a2008-06-29 00:16:31 +000082 ProcessDeclAttributeList(D, Attrs);
Chris Lattnerd7e83d82008-06-28 23:58:55 +000083}
84
85/// ProcessDeclAttributeList - Apply all the decl attributes in the specified
86/// attribute list to the specified decl, ignoring any type attributes.
87void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) {
88 while (AttrList) {
89 ProcessDeclAttribute(D, *AttrList);
90 AttrList = AttrList->getNext();
Chris Lattner1c151132008-06-28 23:36:30 +000091 }
92}
93
94/// HandleDeclAttribute - Apply the specific attribute to the specified decl if
95/// the attribute applies to decls. If the attribute is a type attribute, just
96/// silently ignore it.
Chris Lattnerd7e83d82008-06-28 23:58:55 +000097void Sema::ProcessDeclAttribute(Decl *D, const AttributeList &Attr) {
Chris Lattner1c151132008-06-28 23:36:30 +000098 switch (Attr.getKind()) {
99 case AttributeList::AT_address_space:
100 // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
101 break;
Chris Lattnerd7e83d82008-06-28 23:58:55 +0000102 case AttributeList::AT_vector_size: HandleVectorSizeAttribute(D, Attr); break;
103 case AttributeList::AT_ext_vector_type:
104 HandleExtVectorTypeAttribute(D, Attr);
Chris Lattner6953a072008-06-26 18:38:35 +0000105 break;
Chris Lattnerd7e83d82008-06-28 23:58:55 +0000106 case AttributeList::AT_mode: HandleModeAttribute(D, Attr); break;
107 case AttributeList::AT_alias: HandleAliasAttribute(D, Attr); break;
108 case AttributeList::AT_deprecated: HandleDeprecatedAttribute(D, Attr);break;
109 case AttributeList::AT_visibility: HandleVisibilityAttribute(D, Attr);break;
110 case AttributeList::AT_weak: HandleWeakAttribute(D, Attr); break;
111 case AttributeList::AT_dllimport: HandleDLLImportAttribute(D, Attr); break;
112 case AttributeList::AT_dllexport: HandleDLLExportAttribute(D, Attr); break;
113 case AttributeList::AT_nothrow: HandleNothrowAttribute(D, Attr); break;
114 case AttributeList::AT_stdcall: HandleStdCallAttribute(D, Attr); break;
115 case AttributeList::AT_fastcall: HandleFastCallAttribute(D, Attr); break;
116 case AttributeList::AT_aligned: HandleAlignedAttribute(D, Attr); break;
117 case AttributeList::AT_packed: HandlePackedAttribute(D, Attr); break;
118 case AttributeList::AT_annotate: HandleAnnotateAttribute(D, Attr); break;
119 case AttributeList::AT_noreturn: HandleNoReturnAttribute(D, Attr); break;
120 case AttributeList::AT_format: HandleFormatAttribute(D, Attr); break;
Chris Lattner6953a072008-06-26 18:38:35 +0000121 case AttributeList::AT_transparent_union:
Chris Lattnerd7e83d82008-06-28 23:58:55 +0000122 HandleTransparentUnionAttribute(D, Attr);
Chris Lattner6953a072008-06-26 18:38:35 +0000123 break;
124 default:
125#if 0
126 // TODO: when we have the full set of attributes, warn about unknown ones.
127 Diag(Attr->getLoc(), diag::warn_attribute_ignored,
128 Attr->getName()->getName());
129#endif
130 break;
131 }
132}
133
Chris Lattner2024f0a2008-06-29 00:16:31 +0000134//===----------------------------------------------------------------------===//
135// Attribute Implementations
136//===----------------------------------------------------------------------===//
137
Chris Lattner1c151132008-06-28 23:36:30 +0000138void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) {
139 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
140 if (tDecl == 0) {
141 Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
142 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000143 }
144
Chris Lattner6953a072008-06-26 18:38:35 +0000145 QualType curType = tDecl->getUnderlyingType();
146 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000147 if (Attr.getNumArgs() != 1) {
148 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000149 std::string("1"));
150 return;
151 }
Chris Lattner1c151132008-06-28 23:36:30 +0000152 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000153 llvm::APSInt vecSize(32);
154 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000155 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000156 "ext_vector_type", sizeExpr->getSourceRange());
157 return;
158 }
159 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
160 // in conjunction with complex types (pointers, arrays, functions, etc.).
161 Type *canonType = curType.getCanonicalType().getTypePtr();
162 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +0000163 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000164 curType.getCanonicalType().getAsString());
165 return;
166 }
167 // unlike gcc's vector_size attribute, the size is specified as the
168 // number of elements, not the number of bytes.
169 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
170
171 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000172 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000173 sizeExpr->getSourceRange());
174 return;
175 }
176 // Instantiate/Install the vector type, the number of elements is > 0.
177 tDecl->setUnderlyingType(Context.getExtVectorType(curType, vectorSize));
178 // Remember this typedef decl, we will need it later for diagnostics.
179 ExtVectorDecls.push_back(tDecl);
180}
181
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000182
183/// HandleVectorSizeAttribute - this attribute is only applicable to
184/// integral and float scalars, although arrays, pointers, and function
185/// return values are allowed in conjunction with this construct. Aggregates
186/// with this attribute are invalid, even if they are of the same size as a
187/// corresponding scalar.
188/// The raw attribute should contain precisely 1 argument, the vector size
189/// for the variable, measured in bytes. If curType and rawAttr are well
190/// formed, this routine will return a new vector type.
191void Sema::HandleVectorSizeAttribute(Decl *D, const AttributeList &Attr) {
192 QualType CurType;
193 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
194 CurType = VD->getType();
195 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
196 CurType = TD->getUnderlyingType();
197 else {
198 Diag(D->getLocation(), diag::err_attr_wrong_decl,std::string("vector_size"),
199 SourceRange(Attr.getLoc(), Attr.getLoc()));
200 return;
201 }
202
203 // Check the attribute arugments.
Chris Lattner1c151132008-06-28 23:36:30 +0000204 if (Attr.getNumArgs() != 1) {
205 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000206 std::string("1"));
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000207 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000208 }
Chris Lattner1c151132008-06-28 23:36:30 +0000209 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000210 llvm::APSInt vecSize(32);
211 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000212 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000213 "vector_size", sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000214 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000215 }
216 // navigate to the base type - we need to provide for vector pointers,
217 // vector arrays, and functions returning vectors.
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000218 Type *canonType = CurType.getCanonicalType().getTypePtr();
Chris Lattner6953a072008-06-26 18:38:35 +0000219
220 if (canonType->isPointerType() || canonType->isArrayType() ||
221 canonType->isFunctionType()) {
222 assert(0 && "HandleVector(): Complex type construction unimplemented");
223 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
224 do {
225 if (PointerType *PT = dyn_cast<PointerType>(canonType))
226 canonType = PT->getPointeeType().getTypePtr();
227 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
228 canonType = AT->getElementType().getTypePtr();
229 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
230 canonType = FT->getResultType().getTypePtr();
231 } while (canonType->isPointerType() || canonType->isArrayType() ||
232 canonType->isFunctionType());
233 */
234 }
235 // the base type must be integer or float.
236 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner1c151132008-06-28 23:36:30 +0000237 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000238 CurType.getCanonicalType().getAsString());
239 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000240 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000241 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
Chris Lattner6953a072008-06-26 18:38:35 +0000242 // vecSize is specified in bytes - convert to bits.
243 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
244
245 // the vector size needs to be an integral multiple of the type size.
246 if (vectorSize % typeSize) {
Chris Lattner1c151132008-06-28 23:36:30 +0000247 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000248 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000249 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000250 }
251 if (vectorSize == 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000252 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6953a072008-06-26 18:38:35 +0000253 sizeExpr->getSourceRange());
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000254 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000255 }
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000256
257 // Success! Instantiate the vector type, the number of elements is > 0, and
258 // not required to be a power of 2, unlike GCC.
259 CurType = Context.getVectorType(CurType, vectorSize/typeSize);
260
261 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
262 VD->setType(CurType);
263 else
264 cast<TypedefDecl>(D)->setUnderlyingType(CurType);
Chris Lattner6953a072008-06-26 18:38:35 +0000265}
266
Chris Lattner1c151132008-06-28 23:36:30 +0000267void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000268 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000269 if (Attr.getNumArgs() > 0) {
270 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000271 std::string("0"));
272 return;
273 }
274
275 if (TagDecl *TD = dyn_cast<TagDecl>(d))
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000276 TD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000277 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
278 // If the alignment is less than or equal to 8 bits, the packed attribute
279 // has no effect.
280 if (!FD->getType()->isIncompleteType() &&
281 Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattner1c151132008-06-28 23:36:30 +0000282 Diag(Attr.getLoc(),
Chris Lattner6953a072008-06-26 18:38:35 +0000283 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner1c151132008-06-28 23:36:30 +0000284 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6953a072008-06-26 18:38:35 +0000285 else
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000286 FD->addAttr(new PackedAttr());
Chris Lattner6953a072008-06-26 18:38:35 +0000287 } else
Chris Lattner1c151132008-06-28 23:36:30 +0000288 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
289 Attr.getName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000290}
291
Chris Lattner1c151132008-06-28 23:36:30 +0000292void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000293 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000294 if (Attr.getNumArgs() != 1) {
295 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000296 std::string("1"));
297 return;
298 }
299
Chris Lattner1c151132008-06-28 23:36:30 +0000300 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000301 Arg = Arg->IgnoreParenCasts();
302 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
303
304 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000305 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000306 "alias", std::string("1"));
307 return;
308 }
309
310 const char *Alias = Str->getStrData();
311 unsigned AliasLen = Str->getByteLength();
312
313 // FIXME: check if target symbol exists in current file
314
315 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
316}
317
Chris Lattner1c151132008-06-28 23:36:30 +0000318void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000319 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000320 if (Attr.getNumArgs() != 0) {
321 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000322 std::string("0"));
323 return;
324 }
325
326 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
Chris Lattner6953a072008-06-26 18:38:35 +0000327 if (!Fn) {
Chris Lattner1c151132008-06-28 23:36:30 +0000328 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000329 "noreturn", "function");
330 return;
331 }
332
333 d->addAttr(new NoReturnAttr());
334}
335
Chris Lattner1c151132008-06-28 23:36:30 +0000336void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000337 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000338 if (Attr.getNumArgs() != 0) {
339 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000340 std::string("0"));
341 return;
342 }
343
344 d->addAttr(new DeprecatedAttr());
345}
346
Chris Lattner1c151132008-06-28 23:36:30 +0000347void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000348 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000349 if (Attr.getNumArgs() != 1) {
350 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000351 std::string("1"));
352 return;
353 }
354
Chris Lattner1c151132008-06-28 23:36:30 +0000355 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000356 Arg = Arg->IgnoreParenCasts();
357 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
358
359 if (Str == 0 || Str->isWide()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000360 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000361 "visibility", std::string("1"));
362 return;
363 }
364
365 const char *TypeStr = Str->getStrData();
366 unsigned TypeLen = Str->getByteLength();
367 VisibilityAttr::VisibilityTypes type;
368
369 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
370 type = VisibilityAttr::DefaultVisibility;
371 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
372 type = VisibilityAttr::HiddenVisibility;
373 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
374 type = VisibilityAttr::HiddenVisibility; // FIXME
375 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
376 type = VisibilityAttr::ProtectedVisibility;
377 else {
Chris Lattner1c151132008-06-28 23:36:30 +0000378 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6953a072008-06-26 18:38:35 +0000379 "visibility", TypeStr);
380 return;
381 }
382
383 d->addAttr(new VisibilityAttr(type));
384}
385
Chris Lattner1c151132008-06-28 23:36:30 +0000386void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000387 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000388 if (Attr.getNumArgs() != 0) {
389 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000390 std::string("0"));
391 return;
392 }
393
394 d->addAttr(new WeakAttr());
395}
396
Chris Lattner1c151132008-06-28 23:36:30 +0000397void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000398 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000399 if (Attr.getNumArgs() != 0) {
400 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000401 std::string("0"));
402 return;
403 }
404
405 d->addAttr(new DLLImportAttr());
406}
407
Chris Lattner1c151132008-06-28 23:36:30 +0000408void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000409 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000410 if (Attr.getNumArgs() != 0) {
411 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000412 std::string("0"));
413 return;
414 }
415
416 d->addAttr(new DLLExportAttr());
417}
418
Chris Lattner1c151132008-06-28 23:36:30 +0000419void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000420 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000421 if (Attr.getNumArgs() != 0) {
422 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000423 std::string("0"));
424 return;
425 }
426
427 d->addAttr(new StdCallAttr());
428}
429
Chris Lattner1c151132008-06-28 23:36:30 +0000430void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000431 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000432 if (Attr.getNumArgs() != 0) {
433 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000434 std::string("0"));
435 return;
436 }
437
438 d->addAttr(new FastCallAttr());
439}
440
Chris Lattner1c151132008-06-28 23:36:30 +0000441void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000442 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000443 if (Attr.getNumArgs() != 0) {
444 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000445 std::string("0"));
446 return;
447 }
448
449 d->addAttr(new NoThrowAttr());
450}
451
452/// Handle __attribute__((format(type,idx,firstarg))) attributes
453/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner1c151132008-06-28 23:36:30 +0000454void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000455
Chris Lattner1c151132008-06-28 23:36:30 +0000456 if (!Attr.getParameterName()) {
457 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000458 "format", std::string("1"));
459 return;
460 }
461
Chris Lattner1c151132008-06-28 23:36:30 +0000462 if (Attr.getNumArgs() != 2) {
463 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000464 std::string("3"));
465 return;
466 }
467
468 // GCC ignores the format attribute on K&R style function
469 // prototypes, so we ignore it as well
470 const FunctionTypeProto *proto = getFunctionProto(d);
471
472 if (!proto) {
Chris Lattner1c151132008-06-28 23:36:30 +0000473 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000474 "format", "function");
Chris Lattner6953a072008-06-26 18:38:35 +0000475 return;
476 }
477
478 // FIXME: in C++ the implicit 'this' function parameter also counts.
479 // this is needed in order to be compatible with GCC
480 // the index must start in 1 and the limit is numargs+1
481 unsigned NumArgs = proto->getNumArgs();
482 unsigned FirstIdx = 1;
483
Chris Lattner1c151132008-06-28 23:36:30 +0000484 const char *Format = Attr.getParameterName()->getName();
485 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6953a072008-06-26 18:38:35 +0000486
487 // Normalize the argument, __foo__ becomes foo.
488 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
489 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
490 Format += 2;
491 FormatLen -= 4;
492 }
493
494 bool Supported = false;
495 bool is_NSString = false;
496 bool is_strftime = false;
497
498 switch (FormatLen) {
499 default: break;
500 case 5:
501 Supported = !memcmp(Format, "scanf", 5);
502 break;
503 case 6:
504 Supported = !memcmp(Format, "printf", 6);
505 break;
506 case 7:
507 Supported = !memcmp(Format, "strfmon", 7);
508 break;
509 case 8:
510 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
511 (is_NSString = !memcmp(Format, "NSString", 8));
512 break;
513 }
514
515 if (!Supported) {
Chris Lattner1c151132008-06-28 23:36:30 +0000516 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
517 "format", Attr.getParameterName()->getName());
Chris Lattner6953a072008-06-26 18:38:35 +0000518 return;
519 }
520
521 // checks for the 2nd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000522 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000523 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
524 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000525 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000526 "format", std::string("2"), IdxExpr->getSourceRange());
527 return;
528 }
529
530 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000531 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000532 "format", std::string("2"), IdxExpr->getSourceRange());
533 return;
534 }
535
536 // FIXME: Do we need to bounds check?
537 unsigned ArgIdx = Idx.getZExtValue() - 1;
538
539 // make sure the format string is really a string
540 QualType Ty = proto->getArgType(ArgIdx);
541
542 if (is_NSString) {
543 // FIXME: do we need to check if the type is NSString*? What are
544 // the semantics?
545 if (!isNSStringType(Ty, Context)) {
546 // FIXME: Should highlight the actual expression that has the
547 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000548 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6953a072008-06-26 18:38:35 +0000549 IdxExpr->getSourceRange());
550 return;
551 }
552 } else if (!Ty->isPointerType() ||
553 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
554 // FIXME: Should highlight the actual expression that has the
555 // wrong type.
Chris Lattner1c151132008-06-28 23:36:30 +0000556 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6953a072008-06-26 18:38:35 +0000557 IdxExpr->getSourceRange());
558 return;
559 }
560
561 // check the 3rd argument
Chris Lattner1c151132008-06-28 23:36:30 +0000562 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6953a072008-06-26 18:38:35 +0000563 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
564 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner1c151132008-06-28 23:36:30 +0000565 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6953a072008-06-26 18:38:35 +0000566 "format", std::string("3"), FirstArgExpr->getSourceRange());
567 return;
568 }
569
570 // check if the function is variadic if the 3rd argument non-zero
571 if (FirstArg != 0) {
572 if (proto->isVariadic()) {
573 ++NumArgs; // +1 for ...
574 } else {
575 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
576 return;
577 }
578 }
579
580 // strftime requires FirstArg to be 0 because it doesn't read from any variable
581 // the input is just the current time + the format string
582 if (is_strftime) {
583 if (FirstArg != 0) {
Chris Lattner1c151132008-06-28 23:36:30 +0000584 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6953a072008-06-26 18:38:35 +0000585 FirstArgExpr->getSourceRange());
586 return;
587 }
588 // if 0 it disables parameter checking (to use with e.g. va_list)
589 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner1c151132008-06-28 23:36:30 +0000590 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6953a072008-06-26 18:38:35 +0000591 "format", std::string("3"), FirstArgExpr->getSourceRange());
592 return;
593 }
594
595 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
596 Idx.getZExtValue(), FirstArg.getZExtValue()));
597}
598
599void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner1c151132008-06-28 23:36:30 +0000600 const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000601 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000602 if (Attr.getNumArgs() != 0) {
603 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000604 std::string("0"));
605 return;
606 }
607
608 TypeDecl *decl = dyn_cast<TypeDecl>(d);
609
610 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner1c151132008-06-28 23:36:30 +0000611 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6953a072008-06-26 18:38:35 +0000612 "transparent_union", "union");
613 return;
614 }
615
616 //QualType QTy = Context.getTypeDeclType(decl);
617 //const RecordType *Ty = QTy->getAsUnionType();
618
619// FIXME
620// Ty->addAttr(new TransparentUnionAttr());
621}
622
Chris Lattner1c151132008-06-28 23:36:30 +0000623void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000624 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000625 if (Attr.getNumArgs() != 1) {
626 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000627 std::string("1"));
628 return;
629 }
Chris Lattner1c151132008-06-28 23:36:30 +0000630 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6953a072008-06-26 18:38:35 +0000631 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
632
633 // Make sure that there is a string literal as the annotation's single
634 // argument.
635 if (!SE) {
Chris Lattner1c151132008-06-28 23:36:30 +0000636 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6953a072008-06-26 18:38:35 +0000637 return;
638 }
639 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
640 SE->getByteLength())));
641}
642
Chris Lattner1c151132008-06-28 23:36:30 +0000643void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6953a072008-06-26 18:38:35 +0000644 // check the attribute arguments.
Chris Lattner1c151132008-06-28 23:36:30 +0000645 if (Attr.getNumArgs() > 1) {
646 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6953a072008-06-26 18:38:35 +0000647 std::string("1"));
648 return;
649 }
650
651 unsigned Align = 0;
Chris Lattner1c151132008-06-28 23:36:30 +0000652 if (Attr.getNumArgs() == 0) {
Chris Lattner6953a072008-06-26 18:38:35 +0000653 // FIXME: This should be the target specific maximum alignment.
654 // (For now we just use 128 bits which is the maximum on X86.
655 Align = 128;
656 return;
Chris Lattner6953a072008-06-26 18:38:35 +0000657 }
Chris Lattnerb0011ca2008-06-28 23:50:44 +0000658
659 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
660 llvm::APSInt Alignment(32);
661 if (!alignmentExpr->isIntegerConstantExpr(Alignment, Context)) {
662 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
663 "aligned", alignmentExpr->getSourceRange());
664 return;
665 }
666 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8));
Chris Lattner6953a072008-06-26 18:38:35 +0000667}
Chris Lattnerdc789562008-06-27 22:18:37 +0000668
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000669/// HandleModeAttribute - This attribute modifies the width of a decl with
670/// primitive type.
Chris Lattnerdc789562008-06-27 22:18:37 +0000671///
672/// Despite what would be logical, the mode attribute is a decl attribute,
673/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
674/// 'G' be HImode, not an intermediate pointer.
675///
676void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
677 // This attribute isn't documented, but glibc uses it. It changes
678 // the width of an int or unsigned int to the specified size.
679
680 // Check that there aren't any arguments
681 if (Attr.getNumArgs() != 0) {
682 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
683 std::string("0"));
684 return;
685 }
686
687 IdentifierInfo *Name = Attr.getParameterName();
688 if (!Name) {
689 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
690 return;
691 }
692 const char *Str = Name->getName();
693 unsigned Len = Name->getLength();
694
695 // Normalize the attribute name, __foo__ becomes foo.
696 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
697 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
698 Str += 2;
699 Len -= 4;
700 }
701
702 unsigned DestWidth = 0;
703 bool IntegerMode = true;
704 switch (Len) {
705 case 2:
706 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
707 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
708 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
709 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
710 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
711 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
712 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
713 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
714 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
715 break;
716 case 4:
717 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
718 // pointer on PIC16 and other embedded platforms.
719 if (!memcmp(Str, "word", 4))
720 DestWidth = Context.Target.getPointerWidth(0);
721 if (!memcmp(Str, "byte", 4))
722 DestWidth = Context.Target.getCharWidth();
723 break;
724 case 7:
725 if (!memcmp(Str, "pointer", 7))
726 DestWidth = Context.Target.getPointerWidth(0);
727 break;
728 }
729
730 QualType OldTy;
731 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
732 OldTy = TD->getUnderlyingType();
733 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
734 OldTy = VD->getType();
735 else {
Chris Lattner8ed14aa2008-06-28 23:48:25 +0000736 Diag(D->getLocation(), diag::err_attr_wrong_decl, "mode",
Chris Lattnerdc789562008-06-27 22:18:37 +0000737 SourceRange(Attr.getLoc(), Attr.getLoc()));
738 return;
739 }
740
741 // FIXME: Need proper fixed-width types
742 QualType NewTy;
743 switch (DestWidth) {
744 case 0:
745 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
746 return;
747 default:
748 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
749 return;
750 case 8:
751 assert(IntegerMode);
752 if (OldTy->isSignedIntegerType())
753 NewTy = Context.SignedCharTy;
754 else
755 NewTy = Context.UnsignedCharTy;
756 break;
757 case 16:
758 assert(IntegerMode);
759 if (OldTy->isSignedIntegerType())
760 NewTy = Context.ShortTy;
761 else
762 NewTy = Context.UnsignedShortTy;
763 break;
764 case 32:
765 if (!IntegerMode)
766 NewTy = Context.FloatTy;
767 else if (OldTy->isSignedIntegerType())
768 NewTy = Context.IntTy;
769 else
770 NewTy = Context.UnsignedIntTy;
771 break;
772 case 64:
773 if (!IntegerMode)
774 NewTy = Context.DoubleTy;
775 else if (OldTy->isSignedIntegerType())
776 NewTy = Context.LongLongTy;
777 else
778 NewTy = Context.UnsignedLongLongTy;
779 break;
780 }
781
782 if (!OldTy->getAsBuiltinType())
783 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
784 else if (!(IntegerMode && OldTy->isIntegerType()) &&
785 !(!IntegerMode && OldTy->isFloatingType())) {
786 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
787 }
788
789 // Install the new type.
790 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
791 TD->setUnderlyingType(NewTy);
792 else
793 cast<ValueDecl>(D)->setType(NewTy);
794}