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