blob: c8396ad707fa17f1ba18713b201c152fa520e868 [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 Lattner6b6b5372008-06-26 18:38:35 +000092 case AttributeList::AT_vector_size:
93 if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
94 QualType newType = HandleVectorTypeAttribute(vDecl->getType(), Attr);
95 if (!newType.isNull()) // install the new vector type into the decl
96 vDecl->setType(newType);
97 }
98 if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
99 QualType newType = HandleVectorTypeAttribute(tDecl->getUnderlyingType(),
100 Attr);
101 if (!newType.isNull()) // install the new vector type into the decl
102 tDecl->setUnderlyingType(newType);
103 }
104 break;
105 case AttributeList::AT_ext_vector_type:
Chris Lattner545dd342008-06-28 23:36:30 +0000106 HandleExtVectorTypeAttribute(New, Attr);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000107 break;
Chris Lattner545dd342008-06-28 23:36:30 +0000108 case AttributeList::AT_mode: HandleModeAttribute(New, Attr); break;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000109 case AttributeList::AT_alias: HandleAliasAttribute(New, Attr); break;
110 case AttributeList::AT_deprecated: HandleDeprecatedAttribute(New, Attr);break;
111 case AttributeList::AT_visibility: HandleVisibilityAttribute(New, Attr);break;
112 case AttributeList::AT_weak: HandleWeakAttribute(New, Attr); break;
113 case AttributeList::AT_dllimport: HandleDLLImportAttribute(New, Attr); break;
114 case AttributeList::AT_dllexport: HandleDLLExportAttribute(New, Attr); break;
115 case AttributeList::AT_nothrow: HandleNothrowAttribute(New, Attr); break;
116 case AttributeList::AT_stdcall: HandleStdCallAttribute(New, Attr); break;
117 case AttributeList::AT_fastcall: HandleFastCallAttribute(New, Attr); break;
118 case AttributeList::AT_aligned: HandleAlignedAttribute(New, Attr); break;
119 case AttributeList::AT_packed: HandlePackedAttribute(New, Attr); break;
120 case AttributeList::AT_annotate: HandleAnnotateAttribute(New, Attr); break;
121 case AttributeList::AT_noreturn: HandleNoReturnAttribute(New, Attr); break;
122 case AttributeList::AT_format: HandleFormatAttribute(New, Attr); break;
123 case AttributeList::AT_transparent_union:
124 HandleTransparentUnionAttribute(New, Attr);
125 break;
126 default:
127#if 0
128 // TODO: when we have the full set of attributes, warn about unknown ones.
129 Diag(Attr->getLoc(), diag::warn_attribute_ignored,
130 Attr->getName()->getName());
131#endif
132 break;
133 }
134}
135
Chris Lattner545dd342008-06-28 23:36:30 +0000136void Sema::HandleExtVectorTypeAttribute(Decl *d, const AttributeList &Attr) {
137 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
138 if (tDecl == 0) {
139 Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
140 return;
Chris Lattner6b6b5372008-06-26 18:38:35 +0000141 }
142
Chris Lattner6b6b5372008-06-26 18:38:35 +0000143 QualType curType = tDecl->getUnderlyingType();
144 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000145 if (Attr.getNumArgs() != 1) {
146 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000147 std::string("1"));
148 return;
149 }
Chris Lattner545dd342008-06-28 23:36:30 +0000150 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000151 llvm::APSInt vecSize(32);
152 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000153 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000154 "ext_vector_type", sizeExpr->getSourceRange());
155 return;
156 }
157 // unlike gcc's vector_size attribute, we do not allow vectors to be defined
158 // in conjunction with complex types (pointers, arrays, functions, etc.).
159 Type *canonType = curType.getCanonicalType().getTypePtr();
160 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner545dd342008-06-28 23:36:30 +0000161 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000162 curType.getCanonicalType().getAsString());
163 return;
164 }
165 // unlike gcc's vector_size attribute, the size is specified as the
166 // number of elements, not the number of bytes.
167 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
168
169 if (vectorSize == 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000170 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000171 sizeExpr->getSourceRange());
172 return;
173 }
174 // Instantiate/Install the vector type, the number of elements is > 0.
175 tDecl->setUnderlyingType(Context.getExtVectorType(curType, vectorSize));
176 // Remember this typedef decl, we will need it later for diagnostics.
177 ExtVectorDecls.push_back(tDecl);
178}
179
180QualType Sema::HandleVectorTypeAttribute(QualType curType,
Chris Lattner545dd342008-06-28 23:36:30 +0000181 const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000182 // check the attribute arugments.
Chris Lattner545dd342008-06-28 23:36:30 +0000183 if (Attr.getNumArgs() != 1) {
184 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000185 std::string("1"));
186 return QualType();
187 }
Chris Lattner545dd342008-06-28 23:36:30 +0000188 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000189 llvm::APSInt vecSize(32);
190 if (!sizeExpr->isIntegerConstantExpr(vecSize, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000191 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000192 "vector_size", sizeExpr->getSourceRange());
193 return QualType();
194 }
195 // navigate to the base type - we need to provide for vector pointers,
196 // vector arrays, and functions returning vectors.
197 Type *canonType = curType.getCanonicalType().getTypePtr();
198
199 if (canonType->isPointerType() || canonType->isArrayType() ||
200 canonType->isFunctionType()) {
201 assert(0 && "HandleVector(): Complex type construction unimplemented");
202 /* FIXME: rebuild the type from the inside out, vectorizing the inner type.
203 do {
204 if (PointerType *PT = dyn_cast<PointerType>(canonType))
205 canonType = PT->getPointeeType().getTypePtr();
206 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType))
207 canonType = AT->getElementType().getTypePtr();
208 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType))
209 canonType = FT->getResultType().getTypePtr();
210 } while (canonType->isPointerType() || canonType->isArrayType() ||
211 canonType->isFunctionType());
212 */
213 }
214 // the base type must be integer or float.
215 if (!(canonType->isIntegerType() || canonType->isRealFloatingType())) {
Chris Lattner545dd342008-06-28 23:36:30 +0000216 Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000217 curType.getCanonicalType().getAsString());
218 return QualType();
219 }
220 unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(curType));
221 // vecSize is specified in bytes - convert to bits.
222 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
223
224 // the vector size needs to be an integral multiple of the type size.
225 if (vectorSize % typeSize) {
Chris Lattner545dd342008-06-28 23:36:30 +0000226 Diag(Attr.getLoc(), diag::err_attribute_invalid_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000227 sizeExpr->getSourceRange());
228 return QualType();
229 }
230 if (vectorSize == 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000231 Diag(Attr.getLoc(), diag::err_attribute_zero_size,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000232 sizeExpr->getSourceRange());
233 return QualType();
234 }
235 // Instantiate the vector type, the number of elements is > 0, and not
236 // required to be a power of 2, unlike GCC.
237 return Context.getVectorType(curType, vectorSize/typeSize);
238}
239
Chris Lattner545dd342008-06-28 23:36:30 +0000240void Sema::HandlePackedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000241 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000242 if (Attr.getNumArgs() > 0) {
243 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000244 std::string("0"));
245 return;
246 }
247
248 if (TagDecl *TD = dyn_cast<TagDecl>(d))
249 TD->addAttr(new PackedAttr);
250 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
251 // If the alignment is less than or equal to 8 bits, the packed attribute
252 // has no effect.
253 if (!FD->getType()->isIncompleteType() &&
254 Context.getTypeAlign(FD->getType()) <= 8)
Chris Lattner545dd342008-06-28 23:36:30 +0000255 Diag(Attr.getLoc(),
Chris Lattner6b6b5372008-06-26 18:38:35 +0000256 diag::warn_attribute_ignored_for_field_of_type,
Chris Lattner545dd342008-06-28 23:36:30 +0000257 Attr.getName()->getName(), FD->getType().getAsString());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000258 else
259 FD->addAttr(new PackedAttr);
260 } else
Chris Lattner545dd342008-06-28 23:36:30 +0000261 Diag(Attr.getLoc(), diag::warn_attribute_ignored,
262 Attr.getName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000263}
264
Chris Lattner545dd342008-06-28 23:36:30 +0000265void Sema::HandleAliasAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000266 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000267 if (Attr.getNumArgs() != 1) {
268 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000269 std::string("1"));
270 return;
271 }
272
Chris Lattner545dd342008-06-28 23:36:30 +0000273 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000274 Arg = Arg->IgnoreParenCasts();
275 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
276
277 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000278 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000279 "alias", std::string("1"));
280 return;
281 }
282
283 const char *Alias = Str->getStrData();
284 unsigned AliasLen = Str->getByteLength();
285
286 // FIXME: check if target symbol exists in current file
287
288 d->addAttr(new AliasAttr(std::string(Alias, AliasLen)));
289}
290
Chris Lattner545dd342008-06-28 23:36:30 +0000291void Sema::HandleNoReturnAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000292 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000293 if (Attr.getNumArgs() != 0) {
294 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000295 std::string("0"));
296 return;
297 }
298
299 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
300
301 if (!Fn) {
Chris Lattner545dd342008-06-28 23:36:30 +0000302 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000303 "noreturn", "function");
304 return;
305 }
306
307 d->addAttr(new NoReturnAttr());
308}
309
Chris Lattner545dd342008-06-28 23:36:30 +0000310void Sema::HandleDeprecatedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000311 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000312 if (Attr.getNumArgs() != 0) {
313 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000314 std::string("0"));
315 return;
316 }
317
318 d->addAttr(new DeprecatedAttr());
319}
320
Chris Lattner545dd342008-06-28 23:36:30 +0000321void Sema::HandleVisibilityAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000322 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000323 if (Attr.getNumArgs() != 1) {
324 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000325 std::string("1"));
326 return;
327 }
328
Chris Lattner545dd342008-06-28 23:36:30 +0000329 Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000330 Arg = Arg->IgnoreParenCasts();
331 StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
332
333 if (Str == 0 || Str->isWide()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000334 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000335 "visibility", std::string("1"));
336 return;
337 }
338
339 const char *TypeStr = Str->getStrData();
340 unsigned TypeLen = Str->getByteLength();
341 VisibilityAttr::VisibilityTypes type;
342
343 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7))
344 type = VisibilityAttr::DefaultVisibility;
345 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6))
346 type = VisibilityAttr::HiddenVisibility;
347 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8))
348 type = VisibilityAttr::HiddenVisibility; // FIXME
349 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9))
350 type = VisibilityAttr::ProtectedVisibility;
351 else {
Chris Lattner545dd342008-06-28 23:36:30 +0000352 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000353 "visibility", TypeStr);
354 return;
355 }
356
357 d->addAttr(new VisibilityAttr(type));
358}
359
Chris Lattner545dd342008-06-28 23:36:30 +0000360void Sema::HandleWeakAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000361 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000362 if (Attr.getNumArgs() != 0) {
363 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000364 std::string("0"));
365 return;
366 }
367
368 d->addAttr(new WeakAttr());
369}
370
Chris Lattner545dd342008-06-28 23:36:30 +0000371void Sema::HandleDLLImportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000372 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000373 if (Attr.getNumArgs() != 0) {
374 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000375 std::string("0"));
376 return;
377 }
378
379 d->addAttr(new DLLImportAttr());
380}
381
Chris Lattner545dd342008-06-28 23:36:30 +0000382void Sema::HandleDLLExportAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000383 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000384 if (Attr.getNumArgs() != 0) {
385 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000386 std::string("0"));
387 return;
388 }
389
390 d->addAttr(new DLLExportAttr());
391}
392
Chris Lattner545dd342008-06-28 23:36:30 +0000393void Sema::HandleStdCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000394 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000395 if (Attr.getNumArgs() != 0) {
396 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000397 std::string("0"));
398 return;
399 }
400
401 d->addAttr(new StdCallAttr());
402}
403
Chris Lattner545dd342008-06-28 23:36:30 +0000404void Sema::HandleFastCallAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000405 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000406 if (Attr.getNumArgs() != 0) {
407 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000408 std::string("0"));
409 return;
410 }
411
412 d->addAttr(new FastCallAttr());
413}
414
Chris Lattner545dd342008-06-28 23:36:30 +0000415void Sema::HandleNothrowAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000416 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000417 if (Attr.getNumArgs() != 0) {
418 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000419 std::string("0"));
420 return;
421 }
422
423 d->addAttr(new NoThrowAttr());
424}
425
426/// Handle __attribute__((format(type,idx,firstarg))) attributes
427/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Chris Lattner545dd342008-06-28 23:36:30 +0000428void Sema::HandleFormatAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000429
Chris Lattner545dd342008-06-28 23:36:30 +0000430 if (!Attr.getParameterName()) {
431 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000432 "format", std::string("1"));
433 return;
434 }
435
Chris Lattner545dd342008-06-28 23:36:30 +0000436 if (Attr.getNumArgs() != 2) {
437 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000438 std::string("3"));
439 return;
440 }
441
442 // GCC ignores the format attribute on K&R style function
443 // prototypes, so we ignore it as well
444 const FunctionTypeProto *proto = getFunctionProto(d);
445
446 if (!proto) {
Chris Lattner545dd342008-06-28 23:36:30 +0000447 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000448 "format", "function");
449 return;
450 }
451
452 // FIXME: in C++ the implicit 'this' function parameter also counts.
453 // this is needed in order to be compatible with GCC
454 // the index must start in 1 and the limit is numargs+1
455 unsigned NumArgs = proto->getNumArgs();
456 unsigned FirstIdx = 1;
457
Chris Lattner545dd342008-06-28 23:36:30 +0000458 const char *Format = Attr.getParameterName()->getName();
459 unsigned FormatLen = Attr.getParameterName()->getLength();
Chris Lattner6b6b5372008-06-26 18:38:35 +0000460
461 // Normalize the argument, __foo__ becomes foo.
462 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' &&
463 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') {
464 Format += 2;
465 FormatLen -= 4;
466 }
467
468 bool Supported = false;
469 bool is_NSString = false;
470 bool is_strftime = false;
471
472 switch (FormatLen) {
473 default: break;
474 case 5:
475 Supported = !memcmp(Format, "scanf", 5);
476 break;
477 case 6:
478 Supported = !memcmp(Format, "printf", 6);
479 break;
480 case 7:
481 Supported = !memcmp(Format, "strfmon", 7);
482 break;
483 case 8:
484 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) ||
485 (is_NSString = !memcmp(Format, "NSString", 8));
486 break;
487 }
488
489 if (!Supported) {
Chris Lattner545dd342008-06-28 23:36:30 +0000490 Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported,
491 "format", Attr.getParameterName()->getName());
Chris Lattner6b6b5372008-06-26 18:38:35 +0000492 return;
493 }
494
495 // checks for the 2nd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000496 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000497 llvm::APSInt Idx(Context.getTypeSize(IdxExpr->getType()));
498 if (!IdxExpr->isIntegerConstantExpr(Idx, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000499 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000500 "format", std::string("2"), IdxExpr->getSourceRange());
501 return;
502 }
503
504 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000505 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000506 "format", std::string("2"), IdxExpr->getSourceRange());
507 return;
508 }
509
510 // FIXME: Do we need to bounds check?
511 unsigned ArgIdx = Idx.getZExtValue() - 1;
512
513 // make sure the format string is really a string
514 QualType Ty = proto->getArgType(ArgIdx);
515
516 if (is_NSString) {
517 // FIXME: do we need to check if the type is NSString*? What are
518 // the semantics?
519 if (!isNSStringType(Ty, Context)) {
520 // FIXME: Should highlight the actual expression that has the
521 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000522 Diag(Attr.getLoc(), diag::err_format_attribute_not_NSString,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000523 IdxExpr->getSourceRange());
524 return;
525 }
526 } else if (!Ty->isPointerType() ||
527 !Ty->getAsPointerType()->getPointeeType()->isCharType()) {
528 // FIXME: Should highlight the actual expression that has the
529 // wrong type.
Chris Lattner545dd342008-06-28 23:36:30 +0000530 Diag(Attr.getLoc(), diag::err_format_attribute_not_string,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000531 IdxExpr->getSourceRange());
532 return;
533 }
534
535 // check the 3rd argument
Chris Lattner545dd342008-06-28 23:36:30 +0000536 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000537 llvm::APSInt FirstArg(Context.getTypeSize(FirstArgExpr->getType()));
538 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000539 Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000540 "format", std::string("3"), FirstArgExpr->getSourceRange());
541 return;
542 }
543
544 // check if the function is variadic if the 3rd argument non-zero
545 if (FirstArg != 0) {
546 if (proto->isVariadic()) {
547 ++NumArgs; // +1 for ...
548 } else {
549 Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
550 return;
551 }
552 }
553
554 // strftime requires FirstArg to be 0 because it doesn't read from any variable
555 // the input is just the current time + the format string
556 if (is_strftime) {
557 if (FirstArg != 0) {
Chris Lattner545dd342008-06-28 23:36:30 +0000558 Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000559 FirstArgExpr->getSourceRange());
560 return;
561 }
562 // if 0 it disables parameter checking (to use with e.g. va_list)
563 } else if (FirstArg != 0 && FirstArg != NumArgs) {
Chris Lattner545dd342008-06-28 23:36:30 +0000564 Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000565 "format", std::string("3"), FirstArgExpr->getSourceRange());
566 return;
567 }
568
569 d->addAttr(new FormatAttr(std::string(Format, FormatLen),
570 Idx.getZExtValue(), FirstArg.getZExtValue()));
571}
572
573void Sema::HandleTransparentUnionAttribute(Decl *d,
Chris Lattner545dd342008-06-28 23:36:30 +0000574 const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000575 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000576 if (Attr.getNumArgs() != 0) {
577 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000578 std::string("0"));
579 return;
580 }
581
582 TypeDecl *decl = dyn_cast<TypeDecl>(d);
583
584 if (!decl || !Context.getTypeDeclType(decl)->isUnionType()) {
Chris Lattner545dd342008-06-28 23:36:30 +0000585 Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000586 "transparent_union", "union");
587 return;
588 }
589
590 //QualType QTy = Context.getTypeDeclType(decl);
591 //const RecordType *Ty = QTy->getAsUnionType();
592
593// FIXME
594// Ty->addAttr(new TransparentUnionAttr());
595}
596
Chris Lattner545dd342008-06-28 23:36:30 +0000597void Sema::HandleAnnotateAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000598 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000599 if (Attr.getNumArgs() != 1) {
600 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000601 std::string("1"));
602 return;
603 }
Chris Lattner545dd342008-06-28 23:36:30 +0000604 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000605 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr);
606
607 // Make sure that there is a string literal as the annotation's single
608 // argument.
609 if (!SE) {
Chris Lattner545dd342008-06-28 23:36:30 +0000610 Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string);
Chris Lattner6b6b5372008-06-26 18:38:35 +0000611 return;
612 }
613 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(),
614 SE->getByteLength())));
615}
616
Chris Lattner545dd342008-06-28 23:36:30 +0000617void Sema::HandleAlignedAttribute(Decl *d, const AttributeList &Attr) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000618 // check the attribute arguments.
Chris Lattner545dd342008-06-28 23:36:30 +0000619 if (Attr.getNumArgs() > 1) {
620 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000621 std::string("1"));
622 return;
623 }
624
625 unsigned Align = 0;
626
Chris Lattner545dd342008-06-28 23:36:30 +0000627 if (Attr.getNumArgs() == 0) {
Chris Lattner6b6b5372008-06-26 18:38:35 +0000628 // FIXME: This should be the target specific maximum alignment.
629 // (For now we just use 128 bits which is the maximum on X86.
630 Align = 128;
631 return;
632 } else {
Chris Lattner545dd342008-06-28 23:36:30 +0000633 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
Chris Lattner6b6b5372008-06-26 18:38:35 +0000634 llvm::APSInt alignment(32);
635 if (!alignmentExpr->isIntegerConstantExpr(alignment, Context)) {
Chris Lattner545dd342008-06-28 23:36:30 +0000636 Diag(Attr.getLoc(), diag::err_attribute_argument_not_int,
Chris Lattner6b6b5372008-06-26 18:38:35 +0000637 "aligned", alignmentExpr->getSourceRange());
638 return;
639 }
640
641 Align = alignment.getZExtValue() * 8;
642 }
643
644 d->addAttr(new AlignedAttr(Align));
645}
Chris Lattnerfbf13472008-06-27 22:18:37 +0000646
647/// HandleModeAttribute - Process a mode attribute on the specified decl.
648///
649/// Despite what would be logical, the mode attribute is a decl attribute,
650/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
651/// 'G' be HImode, not an intermediate pointer.
652///
653void Sema::HandleModeAttribute(Decl *D, const AttributeList &Attr) {
654 // This attribute isn't documented, but glibc uses it. It changes
655 // the width of an int or unsigned int to the specified size.
656
657 // Check that there aren't any arguments
658 if (Attr.getNumArgs() != 0) {
659 Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments,
660 std::string("0"));
661 return;
662 }
663
664 IdentifierInfo *Name = Attr.getParameterName();
665 if (!Name) {
666 Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
667 return;
668 }
669 const char *Str = Name->getName();
670 unsigned Len = Name->getLength();
671
672 // Normalize the attribute name, __foo__ becomes foo.
673 if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
674 Str[Len - 2] == '_' && Str[Len - 1] == '_') {
675 Str += 2;
676 Len -= 4;
677 }
678
679 unsigned DestWidth = 0;
680 bool IntegerMode = true;
681 switch (Len) {
682 case 2:
683 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; }
684 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
685 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
686 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
687 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
688 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
689 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
690 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
691 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
692 break;
693 case 4:
694 // FIXME: glibc uses 'word' to define register_t; this is narrower than a
695 // pointer on PIC16 and other embedded platforms.
696 if (!memcmp(Str, "word", 4))
697 DestWidth = Context.Target.getPointerWidth(0);
698 if (!memcmp(Str, "byte", 4))
699 DestWidth = Context.Target.getCharWidth();
700 break;
701 case 7:
702 if (!memcmp(Str, "pointer", 7))
703 DestWidth = Context.Target.getPointerWidth(0);
704 break;
705 }
706
707 QualType OldTy;
708 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
709 OldTy = TD->getUnderlyingType();
710 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
711 OldTy = VD->getType();
712 else {
713 Diag(D->getLocation(), diag::err_mode_wrong_decl,
714 SourceRange(Attr.getLoc(), Attr.getLoc()));
715 return;
716 }
717
718 // FIXME: Need proper fixed-width types
719 QualType NewTy;
720 switch (DestWidth) {
721 case 0:
722 Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
723 return;
724 default:
725 Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
726 return;
727 case 8:
728 assert(IntegerMode);
729 if (OldTy->isSignedIntegerType())
730 NewTy = Context.SignedCharTy;
731 else
732 NewTy = Context.UnsignedCharTy;
733 break;
734 case 16:
735 assert(IntegerMode);
736 if (OldTy->isSignedIntegerType())
737 NewTy = Context.ShortTy;
738 else
739 NewTy = Context.UnsignedShortTy;
740 break;
741 case 32:
742 if (!IntegerMode)
743 NewTy = Context.FloatTy;
744 else if (OldTy->isSignedIntegerType())
745 NewTy = Context.IntTy;
746 else
747 NewTy = Context.UnsignedIntTy;
748 break;
749 case 64:
750 if (!IntegerMode)
751 NewTy = Context.DoubleTy;
752 else if (OldTy->isSignedIntegerType())
753 NewTy = Context.LongLongTy;
754 else
755 NewTy = Context.UnsignedLongLongTy;
756 break;
757 }
758
759 if (!OldTy->getAsBuiltinType())
760 Diag(Attr.getLoc(), diag::err_mode_not_primitive);
761 else if (!(IntegerMode && OldTy->isIntegerType()) &&
762 !(!IntegerMode && OldTy->isFloatingType())) {
763 Diag(Attr.getLoc(), diag::err_mode_wrong_type);
764 }
765
766 // Install the new type.
767 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
768 TD->setUnderlyingType(NewTy);
769 else
770 cast<ValueDecl>(D)->setType(NewTy);
771}