SemaDeclAttr.cpp revision 72564e73277e29f6db3305d1f27ba408abb7ed88
1//===--- 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" 16#include "clang/AST/DeclObjC.h" 17#include "clang/AST/Expr.h" 18#include "clang/Basic/TargetInfo.h" 19#include "clang/Parse/DeclSpec.h" 20#include <llvm/ADT/StringExtras.h> 21using namespace clang; 22 23//===----------------------------------------------------------------------===// 24// Helper functions 25//===----------------------------------------------------------------------===// 26 27static const FunctionType *getFunctionType(Decl *d) { 28 QualType Ty; 29 if (ValueDecl *decl = dyn_cast<ValueDecl>(d)) 30 Ty = decl->getType(); 31 else if (FieldDecl *decl = dyn_cast<FieldDecl>(d)) 32 Ty = decl->getType(); 33 else if (TypedefDecl* decl = dyn_cast<TypedefDecl>(d)) 34 Ty = decl->getUnderlyingType(); 35 else 36 return 0; 37 38 if (Ty->isFunctionPointerType()) 39 Ty = Ty->getAsPointerType()->getPointeeType(); 40 41 return Ty->getAsFunctionType(); 42} 43 44// FIXME: We should provide an abstraction around a method or function 45// to provide the following bits of information. 46 47/// isFunctionOrMethod - Return true if the given decl has function 48/// type (function or function-typed variable) or an Objective-C 49/// method. 50static bool isFunctionOrMethod(Decl *d) { 51 return getFunctionType(d) || isa<ObjCMethodDecl>(d); 52} 53 54/// hasFunctionProto - Return true if the given decl has a argument 55/// information. This decl should have already passed 56/// isFunctionOrMethod. 57static bool hasFunctionProto(Decl *d) { 58 if (const FunctionType *FnTy = getFunctionType(d)) { 59 return isa<FunctionProtoType>(FnTy); 60 } else { 61 assert(isa<ObjCMethodDecl>(d)); 62 return true; 63 } 64} 65 66/// getFunctionOrMethodNumArgs - Return number of function or method 67/// arguments. It is an error to call this on a K&R function (use 68/// hasFunctionProto first). 69static unsigned getFunctionOrMethodNumArgs(Decl *d) { 70 if (const FunctionType *FnTy = getFunctionType(d)) 71 return cast<FunctionProtoType>(FnTy)->getNumArgs(); 72 return cast<ObjCMethodDecl>(d)->param_size(); 73} 74 75static QualType getFunctionOrMethodArgType(Decl *d, unsigned Idx) { 76 if (const FunctionType *FnTy = getFunctionType(d)) 77 return cast<FunctionProtoType>(FnTy)->getArgType(Idx); 78 79 return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType(); 80} 81 82static bool isFunctionOrMethodVariadic(Decl *d) { 83 if (const FunctionType *FnTy = getFunctionType(d)) { 84 const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); 85 return proto->isVariadic(); 86 } else { 87 return cast<ObjCMethodDecl>(d)->isVariadic(); 88 } 89} 90 91static inline bool isNSStringType(QualType T, ASTContext &Ctx) { 92 const PointerType *PT = T->getAsPointerType(); 93 if (!PT) 94 return false; 95 96 const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAsObjCInterfaceType(); 97 if (!ClsT) 98 return false; 99 100 IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier(); 101 102 // FIXME: Should we walk the chain of classes? 103 return ClsName == &Ctx.Idents.get("NSString") || 104 ClsName == &Ctx.Idents.get("NSMutableString"); 105} 106 107static inline bool isCFStringType(QualType T, ASTContext &Ctx) { 108 const PointerType *PT = T->getAsPointerType(); 109 if (!PT) 110 return false; 111 112 const RecordType *RT = PT->getPointeeType()->getAsRecordType(); 113 if (!RT) 114 return false; 115 116 const RecordDecl *RD = RT->getDecl(); 117 if (RD->getTagKind() != TagDecl::TK_struct) 118 return false; 119 120 return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); 121} 122 123//===----------------------------------------------------------------------===// 124// Attribute Implementations 125//===----------------------------------------------------------------------===// 126 127// FIXME: All this manual attribute parsing code is gross. At the 128// least add some helper functions to check most argument patterns (# 129// and types of args). 130 131static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, 132 Sema &S) { 133 TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); 134 if (tDecl == 0) { 135 S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); 136 return; 137 } 138 139 QualType curType = tDecl->getUnderlyingType(); 140 // check the attribute arguments. 141 if (Attr.getNumArgs() != 1) { 142 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 143 return; 144 } 145 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 146 llvm::APSInt vecSize(32); 147 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { 148 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 149 << "ext_vector_type" << sizeExpr->getSourceRange(); 150 return; 151 } 152 // unlike gcc's vector_size attribute, we do not allow vectors to be defined 153 // in conjunction with complex types (pointers, arrays, functions, etc.). 154 if (!curType->isIntegerType() && !curType->isRealFloatingType()) { 155 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType; 156 return; 157 } 158 // unlike gcc's vector_size attribute, the size is specified as the 159 // number of elements, not the number of bytes. 160 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); 161 162 if (vectorSize == 0) { 163 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) 164 << sizeExpr->getSourceRange(); 165 return; 166 } 167 // Instantiate/Install the vector type, the number of elements is > 0. 168 tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize)); 169 // Remember this typedef decl, we will need it later for diagnostics. 170 S.ExtVectorDecls.push_back(tDecl); 171} 172 173 174/// HandleVectorSizeAttribute - this attribute is only applicable to 175/// integral and float scalars, although arrays, pointers, and function 176/// return values are allowed in conjunction with this construct. Aggregates 177/// with this attribute are invalid, even if they are of the same size as a 178/// corresponding scalar. 179/// The raw attribute should contain precisely 1 argument, the vector size 180/// for the variable, measured in bytes. If curType and rawAttr are well 181/// formed, this routine will return a new vector type. 182static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 183 QualType CurType; 184 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 185 CurType = VD->getType(); 186 else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 187 CurType = TD->getUnderlyingType(); 188 else { 189 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 190 << "vector_size" << SourceRange(Attr.getLoc(), Attr.getLoc()); 191 return; 192 } 193 194 // Check the attribute arugments. 195 if (Attr.getNumArgs() != 1) { 196 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 197 return; 198 } 199 Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); 200 llvm::APSInt vecSize(32); 201 if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { 202 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 203 << "vector_size" << sizeExpr->getSourceRange(); 204 return; 205 } 206 // navigate to the base type - we need to provide for vector pointers, 207 // vector arrays, and functions returning vectors. 208 if (CurType->isPointerType() || CurType->isArrayType() || 209 CurType->isFunctionType()) { 210 assert(0 && "HandleVector(): Complex type construction unimplemented"); 211 /* FIXME: rebuild the type from the inside out, vectorizing the inner type. 212 do { 213 if (PointerType *PT = dyn_cast<PointerType>(canonType)) 214 canonType = PT->getPointeeType().getTypePtr(); 215 else if (ArrayType *AT = dyn_cast<ArrayType>(canonType)) 216 canonType = AT->getElementType().getTypePtr(); 217 else if (FunctionType *FT = dyn_cast<FunctionType>(canonType)) 218 canonType = FT->getResultType().getTypePtr(); 219 } while (canonType->isPointerType() || canonType->isArrayType() || 220 canonType->isFunctionType()); 221 */ 222 } 223 // the base type must be integer or float. 224 if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) { 225 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; 226 return; 227 } 228 unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); 229 // vecSize is specified in bytes - convert to bits. 230 unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); 231 232 // the vector size needs to be an integral multiple of the type size. 233 if (vectorSize % typeSize) { 234 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) 235 << sizeExpr->getSourceRange(); 236 return; 237 } 238 if (vectorSize == 0) { 239 S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) 240 << sizeExpr->getSourceRange(); 241 return; 242 } 243 244 // Success! Instantiate the vector type, the number of elements is > 0, and 245 // not required to be a power of 2, unlike GCC. 246 CurType = S.Context.getVectorType(CurType, vectorSize/typeSize); 247 248 if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 249 VD->setType(CurType); 250 else 251 cast<TypedefDecl>(D)->setUnderlyingType(CurType); 252} 253 254static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 255 // check the attribute arguments. 256 if (Attr.getNumArgs() > 0) { 257 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 258 return; 259 } 260 261 if (TagDecl *TD = dyn_cast<TagDecl>(d)) 262 TD->addAttr(new PackedAttr(1)); 263 else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { 264 // If the alignment is less than or equal to 8 bits, the packed attribute 265 // has no effect. 266 if (!FD->getType()->isIncompleteType() && 267 S.Context.getTypeAlign(FD->getType()) <= 8) 268 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 269 << Attr.getName() << FD->getType(); 270 else 271 FD->addAttr(new PackedAttr(1)); 272 } else 273 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 274} 275 276static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) { 277 // check the attribute arguments. 278 if (Attr.getNumArgs() > 0) { 279 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 280 return; 281 } 282 283 // The IBOutlet attribute only applies to instance variables of Objective-C 284 // classes. 285 if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) 286 d->addAttr(new IBOutletAttr()); 287 else 288 S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet); 289} 290 291static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { 292 // GCC ignores the nonnull attribute on K&R style function 293 // prototypes, so we ignore it as well 294 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 295 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 296 << "nonnull" << 0 /*function*/; 297 return; 298 } 299 300 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 301 302 // The nonnull attribute only applies to pointers. 303 llvm::SmallVector<unsigned, 10> NonNullArgs; 304 305 for (AttributeList::arg_iterator I=Attr.arg_begin(), 306 E=Attr.arg_end(); I!=E; ++I) { 307 308 309 // The argument must be an integer constant expression. 310 Expr *Ex = static_cast<Expr *>(*I); 311 llvm::APSInt ArgNum(32); 312 if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) { 313 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 314 << "nonnull" << Ex->getSourceRange(); 315 return; 316 } 317 318 unsigned x = (unsigned) ArgNum.getZExtValue(); 319 320 if (x < 1 || x > NumArgs) { 321 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 322 << "nonnull" << I.getArgNum() << Ex->getSourceRange(); 323 return; 324 } 325 326 --x; 327 328 // Is the function argument a pointer type? 329 QualType T = getFunctionOrMethodArgType(d, x); 330 if (!T->isPointerType() && !T->isBlockPointerType()) { 331 // FIXME: Should also highlight argument in decl. 332 S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only) 333 << "nonnull" << Ex->getSourceRange(); 334 continue; 335 } 336 337 NonNullArgs.push_back(x); 338 } 339 340 // If no arguments were specified to __attribute__((nonnull)) then all 341 // pointer arguments have a nonnull attribute. 342 if (NonNullArgs.empty()) { 343 for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) { 344 QualType T = getFunctionOrMethodArgType(d, I); 345 if (T->isPointerType() || T->isBlockPointerType()) 346 NonNullArgs.push_back(I); 347 } 348 349 if (NonNullArgs.empty()) { 350 S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); 351 return; 352 } 353 } 354 355 unsigned* start = &NonNullArgs[0]; 356 unsigned size = NonNullArgs.size(); 357 std::sort(start, start + size); 358 d->addAttr(new NonNullAttr(start, size)); 359} 360 361static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { 362 // check the attribute arguments. 363 if (Attr.getNumArgs() != 1) { 364 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 365 return; 366 } 367 368 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 369 Arg = Arg->IgnoreParenCasts(); 370 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 371 372 if (Str == 0 || Str->isWide()) { 373 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 374 << "alias" << 1; 375 return; 376 } 377 378 const char *Alias = Str->getStrData(); 379 unsigned AliasLen = Str->getByteLength(); 380 381 // FIXME: check if target symbol exists in current file 382 383 d->addAttr(new AliasAttr(std::string(Alias, AliasLen))); 384} 385 386static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, 387 Sema &S) { 388 // check the attribute arguments. 389 if (Attr.getNumArgs() != 0) { 390 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 391 return; 392 } 393 394 if (!isFunctionOrMethod(d)) { 395 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 396 << "always_inline" << 0 /*function*/; 397 return; 398 } 399 400 d->addAttr(new AlwaysInlineAttr()); 401} 402 403static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { 404 // check the attribute arguments. 405 if (Attr.getNumArgs() != 0) { 406 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 407 return; 408 } 409 410 if (!isFunctionOrMethod(d)) { 411 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 412 << "noreturn" << 0 /*function*/; 413 return; 414 } 415 416 d->addAttr(new NoReturnAttr()); 417} 418 419static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 420 // check the attribute arguments. 421 if (Attr.getNumArgs() != 0) { 422 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 423 return; 424 } 425 426 if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) { 427 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 428 << "unused" << 2 /*variable and function*/; 429 return; 430 } 431 432 d->addAttr(new UnusedAttr()); 433} 434 435static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 436 // check the attribute arguments. 437 if (Attr.getNumArgs() != 0) { 438 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 439 return; 440 } 441 442 if (const VarDecl *VD = dyn_cast<VarDecl>(d)) { 443 if (VD->hasLocalStorage() || VD->hasExternalStorage()) { 444 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; 445 return; 446 } 447 } else if (!isFunctionOrMethod(d)) { 448 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 449 << "used" << 2 /*variable and function*/; 450 return; 451 } 452 453 d->addAttr(new UsedAttr()); 454} 455 456static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 457 // check the attribute arguments. 458 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 459 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 460 << "0 or 1"; 461 return; 462 } 463 464 int priority = 65535; // FIXME: Do not hardcode such constants. 465 if (Attr.getNumArgs() > 0) { 466 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 467 llvm::APSInt Idx(32); 468 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 469 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 470 << "constructor" << 1 << E->getSourceRange(); 471 return; 472 } 473 priority = Idx.getZExtValue(); 474 } 475 476 FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); 477 if (!Fn) { 478 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 479 << "constructor" << 0 /*function*/; 480 return; 481 } 482 483 d->addAttr(new ConstructorAttr(priority)); 484} 485 486static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { 487 // check the attribute arguments. 488 if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) { 489 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 490 << "0 or 1"; 491 return; 492 } 493 494 int priority = 65535; // FIXME: Do not hardcode such constants. 495 if (Attr.getNumArgs() > 0) { 496 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 497 llvm::APSInt Idx(32); 498 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 499 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 500 << "destructor" << 1 << E->getSourceRange(); 501 return; 502 } 503 priority = Idx.getZExtValue(); 504 } 505 506 if (!isa<FunctionDecl>(d)) { 507 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 508 << "destructor" << 0 /*function*/; 509 return; 510 } 511 512 d->addAttr(new DestructorAttr(priority)); 513} 514 515static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 516 // check the attribute arguments. 517 if (Attr.getNumArgs() != 0) { 518 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 519 return; 520 } 521 522 d->addAttr(new DeprecatedAttr()); 523} 524 525static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { 526 // check the attribute arguments. 527 if (Attr.getNumArgs() != 0) { 528 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 529 return; 530 } 531 532 d->addAttr(new UnavailableAttr()); 533} 534 535static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { 536 // check the attribute arguments. 537 if (Attr.getNumArgs() != 1) { 538 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 539 return; 540 } 541 542 Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); 543 Arg = Arg->IgnoreParenCasts(); 544 StringLiteral *Str = dyn_cast<StringLiteral>(Arg); 545 546 if (Str == 0 || Str->isWide()) { 547 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 548 << "visibility" << 1; 549 return; 550 } 551 552 const char *TypeStr = Str->getStrData(); 553 unsigned TypeLen = Str->getByteLength(); 554 VisibilityAttr::VisibilityTypes type; 555 556 if (TypeLen == 7 && !memcmp(TypeStr, "default", 7)) 557 type = VisibilityAttr::DefaultVisibility; 558 else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6)) 559 type = VisibilityAttr::HiddenVisibility; 560 else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8)) 561 type = VisibilityAttr::HiddenVisibility; // FIXME 562 else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9)) 563 type = VisibilityAttr::ProtectedVisibility; 564 else { 565 S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; 566 return; 567 } 568 569 d->addAttr(new VisibilityAttr(type)); 570} 571 572static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, 573 Sema &S) { 574 if (Attr.getNumArgs() != 0) { 575 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 576 return; 577 } 578 579 ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); 580 if (OCI == 0) { 581 S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); 582 return; 583 } 584 585 D->addAttr(new ObjCExceptionAttr()); 586} 587 588static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { 589 if (Attr.getNumArgs() != 0) { 590 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 591 return; 592 } 593 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { 594 QualType T = TD->getUnderlyingType(); 595 if (!T->isPointerType() || 596 !T->getAsPointerType()->getPointeeType()->isRecordType()) { 597 S.Diag(TD->getLocation(), diag::err_nsobject_attribute); 598 return; 599 } 600 } 601 D->addAttr(new ObjCNSObjectAttr); 602} 603 604static void 605HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { 606 if (Attr.getNumArgs() != 0) { 607 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 608 return; 609 } 610 611 if (!isa<FunctionDecl>(D)) { 612 S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); 613 return; 614 } 615 616 D->addAttr(new OverloadableAttr); 617} 618 619static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { 620 if (!Attr.getParameterName()) { 621 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 622 << "blocks" << 1; 623 return; 624 } 625 626 if (Attr.getNumArgs() != 0) { 627 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 628 return; 629 } 630 631 BlocksAttr::BlocksAttrTypes type; 632 if (Attr.getParameterName()->isStr("byref")) 633 type = BlocksAttr::ByRef; 634 else { 635 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 636 << "blocks" << Attr.getParameterName(); 637 return; 638 } 639 640 d->addAttr(new BlocksAttr(type)); 641} 642 643static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { 644 // check the attribute arguments. 645 if (Attr.getNumArgs() > 2) { 646 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 647 << "0, 1 or 2"; 648 return; 649 } 650 651 int sentinel = 0; 652 if (Attr.getNumArgs() > 0) { 653 Expr *E = static_cast<Expr *>(Attr.getArg(0)); 654 llvm::APSInt Idx(32); 655 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 656 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 657 << "sentinel" << 1 << E->getSourceRange(); 658 return; 659 } 660 sentinel = Idx.getZExtValue(); 661 662 if (sentinel < 0) { 663 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) 664 << E->getSourceRange(); 665 return; 666 } 667 } 668 669 int nullPos = 0; 670 if (Attr.getNumArgs() > 1) { 671 Expr *E = static_cast<Expr *>(Attr.getArg(1)); 672 llvm::APSInt Idx(32); 673 if (!E->isIntegerConstantExpr(Idx, S.Context)) { 674 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 675 << "sentinel" << 2 << E->getSourceRange(); 676 return; 677 } 678 nullPos = Idx.getZExtValue(); 679 680 if (nullPos > 1 || nullPos < 0) { 681 // FIXME: This error message could be improved, it would be nice 682 // to say what the bounds actually are. 683 S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 684 << E->getSourceRange(); 685 return; 686 } 687 } 688 689 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { 690 QualType FT = FD->getType(); 691 if (!FT->getAsFunctionProtoType()->isVariadic()) { 692 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); 693 return; 694 } 695 } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) { 696 if (!MD->isVariadic()) { 697 S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic); 698 return; 699 } 700 } else { 701 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 702 << "sentinel" << 3 /*function or method*/; 703 return; 704 } 705 706 // FIXME: Actually create the attribute. 707} 708 709static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { 710 // check the attribute arguments. 711 if (Attr.getNumArgs() != 0) { 712 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 713 return; 714 } 715 716 // TODO: could also be applied to methods? 717 FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); 718 if (!Fn) { 719 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 720 << "warn_unused_result" << 0 /*function*/; 721 return; 722 } 723 724 Fn->addAttr(new WarnUnusedResultAttr()); 725} 726 727static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { 728 // check the attribute arguments. 729 if (Attr.getNumArgs() != 0) { 730 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 731 return; 732 } 733 734 D->addAttr(new WeakAttr()); 735} 736 737static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 738 // check the attribute arguments. 739 if (Attr.getNumArgs() != 0) { 740 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 741 return; 742 } 743 744 // Attribute can be applied only to functions or variables. 745 if (isa<VarDecl>(D)) { 746 D->addAttr(new DLLImportAttr()); 747 return; 748 } 749 750 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 751 if (!FD) { 752 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 753 << "dllimport" << 2 /*variable and function*/; 754 return; 755 } 756 757 // Currently, the dllimport attribute is ignored for inlined functions. 758 // Warning is emitted. 759 if (FD->isInline()) { 760 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 761 return; 762 } 763 764 // The attribute is also overridden by a subsequent declaration as dllexport. 765 // Warning is emitted. 766 for (AttributeList *nextAttr = Attr.getNext(); nextAttr; 767 nextAttr = nextAttr->getNext()) { 768 if (nextAttr->getKind() == AttributeList::AT_dllexport) { 769 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 770 return; 771 } 772 } 773 774 if (D->getAttr<DLLExportAttr>()) { 775 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; 776 return; 777 } 778 779 D->addAttr(new DLLImportAttr()); 780} 781 782static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 783 // check the attribute arguments. 784 if (Attr.getNumArgs() != 0) { 785 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 786 return; 787 } 788 789 // Attribute can be applied only to functions or variables. 790 if (isa<VarDecl>(D)) { 791 D->addAttr(new DLLExportAttr()); 792 return; 793 } 794 795 FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 796 if (!FD) { 797 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 798 << "dllexport" << 2 /*variable and function*/; 799 return; 800 } 801 802 // Currently, the dllexport attribute is ignored for inlined functions, 803 // unless the -fkeep-inline-functions flag has been used. Warning is emitted; 804 if (FD->isInline()) { 805 // FIXME: ... unless the -fkeep-inline-functions flag has been used. 806 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; 807 return; 808 } 809 810 D->addAttr(new DLLExportAttr()); 811} 812 813static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { 814 // Attribute has no arguments. 815 if (Attr.getNumArgs() != 1) { 816 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 817 return; 818 } 819 820 // Make sure that there is a string literal as the sections's single 821 // argument. 822 StringLiteral *SE = 823 dyn_cast<StringLiteral>(static_cast<Expr *>(Attr.getArg(0))); 824 if (!SE) { 825 // FIXME 826 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 827 return; 828 } 829 D->addAttr(new SectionAttr(std::string(SE->getStrData(), 830 SE->getByteLength()))); 831} 832 833static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 834 // Attribute has no arguments. 835 if (Attr.getNumArgs() != 0) { 836 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 837 return; 838 } 839 840 // Attribute can be applied only to functions. 841 if (!isa<FunctionDecl>(d)) { 842 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 843 << "stdcall" << 0 /*function*/; 844 return; 845 } 846 847 // stdcall and fastcall attributes are mutually incompatible. 848 if (d->getAttr<FastCallAttr>()) { 849 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 850 << "stdcall" << "fastcall"; 851 return; 852 } 853 854 d->addAttr(new StdCallAttr()); 855} 856 857static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { 858 // Attribute has no arguments. 859 if (Attr.getNumArgs() != 0) { 860 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 861 return; 862 } 863 864 if (!isa<FunctionDecl>(d)) { 865 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 866 << "fastcall" << 0 /*function*/; 867 return; 868 } 869 870 // stdcall and fastcall attributes are mutually incompatible. 871 if (d->getAttr<StdCallAttr>()) { 872 S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 873 << "fastcall" << "stdcall"; 874 return; 875 } 876 877 d->addAttr(new FastCallAttr()); 878} 879 880static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { 881 // check the attribute arguments. 882 if (Attr.getNumArgs() != 0) { 883 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 884 return; 885 } 886 887 d->addAttr(new NoThrowAttr()); 888} 889 890static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { 891 // check the attribute arguments. 892 if (Attr.getNumArgs() != 0) { 893 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 894 return; 895 } 896 897 d->addAttr(new ConstAttr()); 898} 899 900static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { 901 // check the attribute arguments. 902 if (Attr.getNumArgs() != 0) { 903 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 904 return; 905 } 906 907 d->addAttr(new PureAttr()); 908} 909 910static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { 911 // Match gcc which ignores cleanup attrs when compiling C++. 912 if (S.getLangOptions().CPlusPlus) 913 return; 914 915 if (!Attr.getParameterName()) { 916 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 917 return; 918 } 919 920 if (Attr.getNumArgs() != 0) { 921 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 922 return; 923 } 924 925 VarDecl *VD = dyn_cast<VarDecl>(d); 926 927 if (!VD || !VD->hasLocalStorage()) { 928 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; 929 return; 930 } 931 932 // Look up the function 933 NamedDecl *CleanupDecl = S.LookupName(S.TUScope, Attr.getParameterName(), 934 Sema::LookupOrdinaryName); 935 if (!CleanupDecl) { 936 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) << 937 Attr.getParameterName(); 938 return; 939 } 940 941 FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); 942 if (!FD) { 943 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) << 944 Attr.getParameterName(); 945 return; 946 } 947 948 if (FD->getNumParams() != 1) { 949 S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) << 950 Attr.getParameterName(); 951 return; 952 } 953 954 // We're currently more strict than GCC about what function types we accept. 955 // If this ever proves to be a problem it should be easy to fix. 956 QualType Ty = S.Context.getPointerType(VD->getType()); 957 QualType ParamTy = FD->getParamDecl(0)->getType(); 958 if (S.CheckAssignmentConstraints(Ty, ParamTy) != Sema::Compatible) { 959 S.Diag(Attr.getLoc(), 960 diag::err_attribute_cleanup_func_arg_incompatible_type) << 961 Attr.getParameterName() << ParamTy << Ty; 962 return; 963 } 964 965 d->addAttr(new CleanupAttr(FD)); 966} 967 968/// Handle __attribute__((format(type,idx,firstarg))) attributes 969/// based on http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 970static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { 971 972 if (!Attr.getParameterName()) { 973 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) 974 << "format" << 1; 975 return; 976 } 977 978 if (Attr.getNumArgs() != 2) { 979 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; 980 return; 981 } 982 983 if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { 984 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 985 << "format" << 0 /*function*/; 986 return; 987 } 988 989 // FIXME: in C++ the implicit 'this' function parameter also counts. 990 // this is needed in order to be compatible with GCC 991 // the index must start in 1 and the limit is numargs+1 992 unsigned NumArgs = getFunctionOrMethodNumArgs(d); 993 unsigned FirstIdx = 1; 994 995 const char *Format = Attr.getParameterName()->getName(); 996 unsigned FormatLen = Attr.getParameterName()->getLength(); 997 998 // Normalize the argument, __foo__ becomes foo. 999 if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && 1000 Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { 1001 Format += 2; 1002 FormatLen -= 4; 1003 } 1004 1005 bool Supported = false; 1006 bool is_NSString = false; 1007 bool is_strftime = false; 1008 bool is_CFString = false; 1009 1010 switch (FormatLen) { 1011 default: break; 1012 case 5: Supported = !memcmp(Format, "scanf", 5); break; 1013 case 6: Supported = !memcmp(Format, "printf", 6); break; 1014 case 7: Supported = !memcmp(Format, "strfmon", 7); break; 1015 case 8: 1016 Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || 1017 (is_NSString = !memcmp(Format, "NSString", 8)) || 1018 (is_CFString = !memcmp(Format, "CFString", 8)); 1019 break; 1020 } 1021 1022 if (!Supported) { 1023 S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 1024 << "format" << Attr.getParameterName()->getName(); 1025 return; 1026 } 1027 1028 // checks for the 2nd argument 1029 Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0)); 1030 llvm::APSInt Idx(32); 1031 if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 1032 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1033 << "format" << 2 << IdxExpr->getSourceRange(); 1034 return; 1035 } 1036 1037 if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 1038 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1039 << "format" << 2 << IdxExpr->getSourceRange(); 1040 return; 1041 } 1042 1043 // FIXME: Do we need to bounds check? 1044 unsigned ArgIdx = Idx.getZExtValue() - 1; 1045 1046 // make sure the format string is really a string 1047 QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); 1048 1049 if (is_CFString) { 1050 if (!isCFStringType(Ty, S.Context)) { 1051 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1052 << "a CFString" << IdxExpr->getSourceRange(); 1053 return; 1054 } 1055 } else if (is_NSString) { 1056 // FIXME: do we need to check if the type is NSString*? What are 1057 // the semantics? 1058 if (!isNSStringType(Ty, S.Context)) { 1059 // FIXME: Should highlight the actual expression that has the 1060 // wrong type. 1061 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1062 << "an NSString" << IdxExpr->getSourceRange(); 1063 return; 1064 } 1065 } else if (!Ty->isPointerType() || 1066 !Ty->getAsPointerType()->getPointeeType()->isCharType()) { 1067 // FIXME: Should highlight the actual expression that has the 1068 // wrong type. 1069 S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 1070 << "a string type" << IdxExpr->getSourceRange(); 1071 return; 1072 } 1073 1074 // check the 3rd argument 1075 Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1)); 1076 llvm::APSInt FirstArg(32); 1077 if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 1078 S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) 1079 << "format" << 3 << FirstArgExpr->getSourceRange(); 1080 return; 1081 } 1082 1083 // check if the function is variadic if the 3rd argument non-zero 1084 if (FirstArg != 0) { 1085 if (isFunctionOrMethodVariadic(d)) { 1086 ++NumArgs; // +1 for ... 1087 } else { 1088 S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); 1089 return; 1090 } 1091 } 1092 1093 // strftime requires FirstArg to be 0 because it doesn't read from any 1094 // variable the input is just the current time + the format string. 1095 if (is_strftime) { 1096 if (FirstArg != 0) { 1097 S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 1098 << FirstArgExpr->getSourceRange(); 1099 return; 1100 } 1101 // if 0 it disables parameter checking (to use with e.g. va_list) 1102 } else if (FirstArg != 0 && FirstArg != NumArgs) { 1103 S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 1104 << "format" << 3 << FirstArgExpr->getSourceRange(); 1105 return; 1106 } 1107 1108 d->addAttr(new FormatAttr(std::string(Format, FormatLen), 1109 Idx.getZExtValue(), FirstArg.getZExtValue())); 1110} 1111 1112static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, 1113 Sema &S) { 1114 // check the attribute arguments. 1115 if (Attr.getNumArgs() != 0) { 1116 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1117 return; 1118 } 1119 1120 // FIXME: This shouldn't be restricted to typedefs 1121 TypedefDecl *TD = dyn_cast<TypedefDecl>(d); 1122 if (!TD || !TD->getUnderlyingType()->isUnionType()) { 1123 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1124 << "transparent_union" << 1 /*union*/; 1125 return; 1126 } 1127 1128 RecordDecl* RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 1129 1130 // FIXME: Should we do a check for RD->isDefinition()? 1131 1132 // FIXME: This isn't supposed to be restricted to pointers, but otherwise 1133 // we might silently generate incorrect code; see following code 1134 for (RecordDecl::field_iterator Field = RD->field_begin(), 1135 FieldEnd = RD->field_end(); 1136 Field != FieldEnd; ++Field) { 1137 if (!Field->getType()->isPointerType()) { 1138 S.Diag(Attr.getLoc(), diag::warn_transparent_union_nonpointer); 1139 return; 1140 } 1141 } 1142 1143 // FIXME: This is a complete hack; we should be properly propagating 1144 // transparent_union through Sema. That said, this is close enough to 1145 // correctly compile all the common cases of transparent_union without 1146 // errors or warnings 1147 QualType NewTy = S.Context.VoidPtrTy; 1148 NewTy.addConst(); 1149 TD->setUnderlyingType(NewTy); 1150} 1151 1152static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1153 // check the attribute arguments. 1154 if (Attr.getNumArgs() != 1) { 1155 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1156 return; 1157 } 1158 Expr *argExpr = static_cast<Expr *>(Attr.getArg(0)); 1159 StringLiteral *SE = dyn_cast<StringLiteral>(argExpr); 1160 1161 // Make sure that there is a string literal as the annotation's single 1162 // argument. 1163 if (!SE) { 1164 S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); 1165 return; 1166 } 1167 d->addAttr(new AnnotateAttr(std::string(SE->getStrData(), 1168 SE->getByteLength()))); 1169} 1170 1171static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1172 // check the attribute arguments. 1173 if (Attr.getNumArgs() > 1) { 1174 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; 1175 return; 1176 } 1177 1178 unsigned Align = 0; 1179 if (Attr.getNumArgs() == 0) { 1180 // FIXME: This should be the target specific maximum alignment. 1181 // (For now we just use 128 bits which is the maximum on X86). 1182 Align = 128; 1183 d->addAttr(new AlignedAttr(Align)); 1184 return; 1185 } 1186 1187 Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0)); 1188 llvm::APSInt Alignment(32); 1189 if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) { 1190 S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) 1191 << "aligned" << alignmentExpr->getSourceRange(); 1192 return; 1193 } 1194 if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { 1195 S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two) 1196 << alignmentExpr->getSourceRange(); 1197 return; 1198 } 1199 1200 d->addAttr(new AlignedAttr(Alignment.getZExtValue() * 8)); 1201} 1202 1203/// HandleModeAttr - This attribute modifies the width of a decl with 1204/// primitive type. 1205/// 1206/// Despite what would be logical, the mode attribute is a decl attribute, 1207/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 1208/// 'G' be HImode, not an intermediate pointer. 1209/// 1210static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { 1211 // This attribute isn't documented, but glibc uses it. It changes 1212 // the width of an int or unsigned int to the specified size. 1213 1214 // Check that there aren't any arguments 1215 if (Attr.getNumArgs() != 0) { 1216 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1217 return; 1218 } 1219 1220 IdentifierInfo *Name = Attr.getParameterName(); 1221 if (!Name) { 1222 S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); 1223 return; 1224 } 1225 const char *Str = Name->getName(); 1226 unsigned Len = Name->getLength(); 1227 1228 // Normalize the attribute name, __foo__ becomes foo. 1229 if (Len > 4 && Str[0] == '_' && Str[1] == '_' && 1230 Str[Len - 2] == '_' && Str[Len - 1] == '_') { 1231 Str += 2; 1232 Len -= 4; 1233 } 1234 1235 unsigned DestWidth = 0; 1236 bool IntegerMode = true; 1237 switch (Len) { 1238 case 2: 1239 if (!memcmp(Str, "QI", 2)) { DestWidth = 8; break; } 1240 if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; } 1241 if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; } 1242 if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; } 1243 if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; } 1244 if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; } 1245 if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; } 1246 if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; } 1247 if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; } 1248 break; 1249 case 4: 1250 // FIXME: glibc uses 'word' to define register_t; this is narrower than a 1251 // pointer on PIC16 and other embedded platforms. 1252 if (!memcmp(Str, "word", 4)) 1253 DestWidth = S.Context.Target.getPointerWidth(0); 1254 if (!memcmp(Str, "byte", 4)) 1255 DestWidth = S.Context.Target.getCharWidth(); 1256 break; 1257 case 7: 1258 if (!memcmp(Str, "pointer", 7)) 1259 DestWidth = S.Context.Target.getPointerWidth(0); 1260 break; 1261 } 1262 1263 QualType OldTy; 1264 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1265 OldTy = TD->getUnderlyingType(); 1266 else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 1267 OldTy = VD->getType(); 1268 else { 1269 S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 1270 << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); 1271 return; 1272 } 1273 1274 // FIXME: Sync this with InitializePredefinedMacros; we need to match 1275 // int8_t and friends, at least with glibc. 1276 // FIXME: Make sure 32/64-bit integers don't get defined to types of 1277 // the wrong width on unusual platforms. 1278 // FIXME: Make sure floating-point mappings are accurate 1279 // FIXME: Support XF and TF types 1280 QualType NewTy; 1281 switch (DestWidth) { 1282 case 0: 1283 S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; 1284 return; 1285 default: 1286 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1287 return; 1288 case 8: 1289 assert(IntegerMode); 1290 if (OldTy->isSignedIntegerType()) 1291 NewTy = S.Context.SignedCharTy; 1292 else 1293 NewTy = S.Context.UnsignedCharTy; 1294 break; 1295 case 16: 1296 assert(IntegerMode); 1297 if (OldTy->isSignedIntegerType()) 1298 NewTy = S.Context.ShortTy; 1299 else 1300 NewTy = S.Context.UnsignedShortTy; 1301 break; 1302 case 32: 1303 if (!IntegerMode) 1304 NewTy = S.Context.FloatTy; 1305 else if (OldTy->isSignedIntegerType()) 1306 NewTy = S.Context.IntTy; 1307 else 1308 NewTy = S.Context.UnsignedIntTy; 1309 break; 1310 case 64: 1311 if (!IntegerMode) 1312 NewTy = S.Context.DoubleTy; 1313 else if (OldTy->isSignedIntegerType()) 1314 NewTy = S.Context.LongLongTy; 1315 else 1316 NewTy = S.Context.UnsignedLongLongTy; 1317 break; 1318 case 128: 1319 if (!IntegerMode) { 1320 S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 1321 return; 1322 } 1323 NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType()); 1324 } 1325 1326 if (!OldTy->getAsBuiltinType()) 1327 S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 1328 else if (!(IntegerMode && OldTy->isIntegerType()) && 1329 !(!IntegerMode && OldTy->isFloatingType())) { 1330 S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 1331 } 1332 1333 // Install the new type. 1334 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) 1335 TD->setUnderlyingType(NewTy); 1336 else 1337 cast<ValueDecl>(D)->setType(NewTy); 1338} 1339 1340static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1341 // check the attribute arguments. 1342 if (Attr.getNumArgs() > 0) { 1343 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1344 return; 1345 } 1346 1347 if (!isFunctionOrMethod(d)) { 1348 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1349 << "nodebug" << 0 /*function*/; 1350 return; 1351 } 1352 1353 d->addAttr(new NodebugAttr()); 1354} 1355 1356static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { 1357 // check the attribute arguments. 1358 if (Attr.getNumArgs() != 0) { 1359 S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; 1360 return; 1361 } 1362 1363 if (!isFunctionOrMethod(d)) { 1364 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1365 << "noinline" << 0 /*function*/; 1366 return; 1367 } 1368 1369 d->addAttr(new NoinlineAttr()); 1370} 1371 1372//===----------------------------------------------------------------------===// 1373// Top Level Sema Entry Points 1374//===----------------------------------------------------------------------===// 1375 1376/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 1377/// the attribute applies to decls. If the attribute is a type attribute, just 1378/// silently ignore it. 1379static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { 1380 switch (Attr.getKind()) { 1381 case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break; 1382 case AttributeList::AT_address_space: 1383 case AttributeList::AT_objc_gc: 1384 // Ignore these, these are type attributes, handled by ProcessTypeAttributes. 1385 break; 1386 case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; 1387 case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; 1388 case AttributeList::AT_always_inline: 1389 HandleAlwaysInlineAttr (D, Attr, S); break; 1390 case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; 1391 case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; 1392 case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; 1393 case AttributeList::AT_destructor: HandleDestructorAttr(D, Attr, S); break; 1394 case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; 1395 case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; 1396 case AttributeList::AT_ext_vector_type: 1397 HandleExtVectorTypeAttr(D, Attr, S); 1398 break; 1399 case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; 1400 case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; 1401 case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; 1402 case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; 1403 case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; 1404 case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; 1405 case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; 1406 case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; 1407 case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; 1408 case AttributeList::AT_unavailable: HandleUnavailableAttr(D, Attr, S); break; 1409 case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; 1410 case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; 1411 case AttributeList::AT_vector_size: HandleVectorSizeAttr(D, Attr, S); break; 1412 case AttributeList::AT_visibility: HandleVisibilityAttr(D, Attr, S); break; 1413 case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); 1414 break; 1415 case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; 1416 case AttributeList::AT_transparent_union: 1417 HandleTransparentUnionAttr(D, Attr, S); 1418 break; 1419 case AttributeList::AT_objc_exception: 1420 HandleObjCExceptionAttr(D, Attr, S); 1421 break; 1422 case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; 1423 case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; 1424 case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; 1425 case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; 1426 case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; 1427 case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; 1428 case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; 1429 case AttributeList::AT_nodebug: HandleNodebugAttr (D, Attr, S); break; 1430 case AttributeList::AT_noinline: HandleNoinlineAttr (D, Attr, S); break; 1431 case AttributeList::IgnoredAttribute: 1432 // Just ignore 1433 break; 1434 default: 1435 S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1436 break; 1437 } 1438} 1439 1440/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 1441/// attribute list to the specified decl, ignoring any type attributes. 1442void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { 1443 while (AttrList) { 1444 ProcessDeclAttribute(D, *AttrList, *this); 1445 AttrList = AttrList->getNext(); 1446 } 1447} 1448 1449 1450/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 1451/// it, apply them to D. This is a bit tricky because PD can have attributes 1452/// specified in many different places, and we need to find and apply them all. 1453void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { 1454 // Apply decl attributes from the DeclSpec if present. 1455 if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) 1456 ProcessDeclAttributeList(D, Attrs); 1457 1458 // Walk the declarator structure, applying decl attributes that were in a type 1459 // position to the decl itself. This handles cases like: 1460 // int *__attr__(x)** D; 1461 // when X is a decl attribute. 1462 for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 1463 if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 1464 ProcessDeclAttributeList(D, Attrs); 1465 1466 // Finally, apply any attributes on the decl itself. 1467 if (const AttributeList *Attrs = PD.getAttributes()) 1468 ProcessDeclAttributeList(D, Attrs); 1469} 1470 1471