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