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