1193326Sed//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file implements decl-related attribute processing. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14212904Sdim#include "clang/Sema/SemaInternal.h" 15202379Srdivacky#include "TargetAttributesSema.h" 16193326Sed#include "clang/AST/ASTContext.h" 17239462Sdim#include "clang/AST/CXXInheritance.h" 18212904Sdim#include "clang/AST/DeclCXX.h" 19249423Sdim#include "clang/AST/DeclObjC.h" 20226633Sdim#include "clang/AST/DeclTemplate.h" 21193326Sed#include "clang/AST/Expr.h" 22249423Sdim#include "clang/AST/Mangle.h" 23249423Sdim#include "clang/Basic/CharInfo.h" 24224145Sdim#include "clang/Basic/SourceManager.h" 25193326Sed#include "clang/Basic/TargetInfo.h" 26263508Sdim#include "clang/Lex/Preprocessor.h" 27212904Sdim#include "clang/Sema/DeclSpec.h" 28212904Sdim#include "clang/Sema/DelayedDiagnostic.h" 29226633Sdim#include "clang/Sema/Lookup.h" 30249423Sdim#include "clang/Sema/Scope.h" 31198092Srdivacky#include "llvm/ADT/StringExtras.h" 32193326Sedusing namespace clang; 33212904Sdimusing namespace sema; 34193326Sed 35221345Sdim/// These constants match the enumerated choices of 36221345Sdim/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. 37226633Sdimenum AttributeDeclKind { 38221345Sdim ExpectedFunction, 39221345Sdim ExpectedUnion, 40221345Sdim ExpectedVariableOrFunction, 41221345Sdim ExpectedFunctionOrMethod, 42221345Sdim ExpectedParameter, 43221345Sdim ExpectedFunctionMethodOrBlock, 44249423Sdim ExpectedFunctionMethodOrClass, 45221345Sdim ExpectedFunctionMethodOrParameter, 46221345Sdim ExpectedClass, 47221345Sdim ExpectedVariable, 48221345Sdim ExpectedMethod, 49226633Sdim ExpectedVariableFunctionOrLabel, 50234353Sdim ExpectedFieldOrGlobalVar, 51239462Sdim ExpectedStruct, 52249423Sdim ExpectedVariableFunctionOrTag, 53249423Sdim ExpectedTLSVar, 54249423Sdim ExpectedVariableOrField, 55249423Sdim ExpectedVariableFieldOrTag, 56263508Sdim ExpectedTypeOrNamespace, 57263508Sdim ExpectedObjectiveCInterface, 58263508Sdim ExpectedMethodOrProperty, 59263508Sdim ExpectedStructOrUnion, 60263508Sdim ExpectedStructOrUnionOrClass 61221345Sdim}; 62221345Sdim 63193326Sed//===----------------------------------------------------------------------===// 64193326Sed// Helper functions 65193326Sed//===----------------------------------------------------------------------===// 66193326Sed 67224145Sdimstatic const FunctionType *getFunctionType(const Decl *D, 68198092Srdivacky bool blocksToo = true) { 69193326Sed QualType Ty; 70224145Sdim if (const ValueDecl *decl = dyn_cast<ValueDecl>(D)) 71193326Sed Ty = decl->getType(); 72224145Sdim else if (const FieldDecl *decl = dyn_cast<FieldDecl>(D)) 73193326Sed Ty = decl->getType(); 74224145Sdim else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(D)) 75193326Sed Ty = decl->getUnderlyingType(); 76193326Sed else 77193326Sed return 0; 78198092Srdivacky 79193326Sed if (Ty->isFunctionPointerType()) 80198092Srdivacky Ty = Ty->getAs<PointerType>()->getPointeeType(); 81193326Sed else if (blocksToo && Ty->isBlockPointerType()) 82198092Srdivacky Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); 83193326Sed 84198092Srdivacky return Ty->getAs<FunctionType>(); 85193326Sed} 86193326Sed 87193326Sed// FIXME: We should provide an abstraction around a method or function 88193326Sed// to provide the following bits of information. 89193326Sed 90201361Srdivacky/// isFunction - Return true if the given decl has function 91198092Srdivacky/// type (function or function-typed variable). 92224145Sdimstatic bool isFunction(const Decl *D) { 93224145Sdim return getFunctionType(D, false) != NULL; 94198092Srdivacky} 95198092Srdivacky 96198092Srdivacky/// isFunctionOrMethod - Return true if the given decl has function 97193326Sed/// type (function or function-typed variable) or an Objective-C 98193326Sed/// method. 99224145Sdimstatic bool isFunctionOrMethod(const Decl *D) { 100239462Sdim return isFunction(D) || isa<ObjCMethodDecl>(D); 101193326Sed} 102193326Sed 103193326Sed/// isFunctionOrMethodOrBlock - Return true if the given decl has function 104193326Sed/// type (function or function-typed variable) or an Objective-C 105193326Sed/// method or a block. 106224145Sdimstatic bool isFunctionOrMethodOrBlock(const Decl *D) { 107224145Sdim if (isFunctionOrMethod(D)) 108193326Sed return true; 109193326Sed // check for block is more involved. 110224145Sdim if (const VarDecl *V = dyn_cast<VarDecl>(D)) { 111193326Sed QualType Ty = V->getType(); 112193326Sed return Ty->isBlockPointerType(); 113193326Sed } 114224145Sdim return isa<BlockDecl>(D); 115193326Sed} 116193326Sed 117218893Sdim/// Return true if the given decl has a declarator that should have 118218893Sdim/// been processed by Sema::GetTypeForDeclarator. 119224145Sdimstatic bool hasDeclarator(const Decl *D) { 120224145Sdim // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. 121224145Sdim return isa<DeclaratorDecl>(D) || isa<BlockDecl>(D) || isa<TypedefNameDecl>(D) || 122224145Sdim isa<ObjCPropertyDecl>(D); 123218893Sdim} 124218893Sdim 125193326Sed/// hasFunctionProto - Return true if the given decl has a argument 126193326Sed/// information. This decl should have already passed 127193326Sed/// isFunctionOrMethod or isFunctionOrMethodOrBlock. 128224145Sdimstatic bool hasFunctionProto(const Decl *D) { 129224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 130193326Sed return isa<FunctionProtoType>(FnTy); 131193326Sed else { 132224145Sdim assert(isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D)); 133193326Sed return true; 134193326Sed } 135193326Sed} 136193326Sed 137193326Sed/// getFunctionOrMethodNumArgs - Return number of function or method 138193326Sed/// arguments. It is an error to call this on a K&R function (use 139193326Sed/// hasFunctionProto first). 140224145Sdimstatic unsigned getFunctionOrMethodNumArgs(const Decl *D) { 141224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 142193326Sed return cast<FunctionProtoType>(FnTy)->getNumArgs(); 143224145Sdim if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 144193326Sed return BD->getNumParams(); 145224145Sdim return cast<ObjCMethodDecl>(D)->param_size(); 146193326Sed} 147193326Sed 148224145Sdimstatic QualType getFunctionOrMethodArgType(const Decl *D, unsigned Idx) { 149224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 150193326Sed return cast<FunctionProtoType>(FnTy)->getArgType(Idx); 151224145Sdim if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 152193326Sed return BD->getParamDecl(Idx)->getType(); 153198092Srdivacky 154224145Sdim return cast<ObjCMethodDecl>(D)->param_begin()[Idx]->getType(); 155193326Sed} 156193326Sed 157224145Sdimstatic QualType getFunctionOrMethodResultType(const Decl *D) { 158224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) 159193326Sed return cast<FunctionProtoType>(FnTy)->getResultType(); 160224145Sdim return cast<ObjCMethodDecl>(D)->getResultType(); 161193326Sed} 162193326Sed 163224145Sdimstatic bool isFunctionOrMethodVariadic(const Decl *D) { 164224145Sdim if (const FunctionType *FnTy = getFunctionType(D)) { 165193326Sed const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); 166193326Sed return proto->isVariadic(); 167224145Sdim } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 168207619Srdivacky return BD->isVariadic(); 169193326Sed else { 170224145Sdim return cast<ObjCMethodDecl>(D)->isVariadic(); 171193326Sed } 172193326Sed} 173193326Sed 174224145Sdimstatic bool isInstanceMethod(const Decl *D) { 175224145Sdim if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) 176218893Sdim return MethodDecl->isInstance(); 177218893Sdim return false; 178218893Sdim} 179218893Sdim 180193326Sedstatic inline bool isNSStringType(QualType T, ASTContext &Ctx) { 181198092Srdivacky const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); 182193326Sed if (!PT) 183193326Sed return false; 184198092Srdivacky 185208600Srdivacky ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); 186208600Srdivacky if (!Cls) 187193326Sed return false; 188198092Srdivacky 189208600Srdivacky IdentifierInfo* ClsName = Cls->getIdentifier(); 190198092Srdivacky 191193326Sed // FIXME: Should we walk the chain of classes? 192193326Sed return ClsName == &Ctx.Idents.get("NSString") || 193193326Sed ClsName == &Ctx.Idents.get("NSMutableString"); 194193326Sed} 195193326Sed 196193326Sedstatic inline bool isCFStringType(QualType T, ASTContext &Ctx) { 197198092Srdivacky const PointerType *PT = T->getAs<PointerType>(); 198193326Sed if (!PT) 199193326Sed return false; 200193326Sed 201198092Srdivacky const RecordType *RT = PT->getPointeeType()->getAs<RecordType>(); 202193326Sed if (!RT) 203193326Sed return false; 204198092Srdivacky 205193326Sed const RecordDecl *RD = RT->getDecl(); 206208600Srdivacky if (RD->getTagKind() != TTK_Struct) 207193326Sed return false; 208193326Sed 209193326Sed return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); 210193326Sed} 211193326Sed 212263508Sdimstatic unsigned getNumAttributeArgs(const AttributeList &Attr) { 213263508Sdim // FIXME: Include the type in the argument list. 214263508Sdim return Attr.getNumArgs() + Attr.hasParsedType(); 215263508Sdim} 216263508Sdim 217226633Sdim/// \brief Check if the attribute has exactly as many args as Num. May 218226633Sdim/// output an error. 219224145Sdimstatic bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, 220263508Sdim unsigned Num) { 221263508Sdim if (getNumAttributeArgs(Attr) != Num) { 222263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 223263508Sdim << Attr.getName() << Num; 224224145Sdim return false; 225224145Sdim } 226224145Sdim 227224145Sdim return true; 228224145Sdim} 229224145Sdim 230226633Sdim 231226633Sdim/// \brief Check if the attribute has at least as many args as Num. May 232226633Sdim/// output an error. 233226633Sdimstatic bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, 234263508Sdim unsigned Num) { 235263508Sdim if (getNumAttributeArgs(Attr) < Num) { 236226633Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; 237226633Sdim return false; 238226633Sdim } 239226633Sdim 240226633Sdim return true; 241226633Sdim} 242226633Sdim 243239462Sdim/// \brief Check if IdxExpr is a valid argument index for a function or 244239462Sdim/// instance method D. May output an error. 245226633Sdim/// 246239462Sdim/// \returns true if IdxExpr is a valid index. 247239462Sdimstatic bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D, 248239462Sdim StringRef AttrName, 249239462Sdim SourceLocation AttrLoc, 250239462Sdim unsigned AttrArgNum, 251239462Sdim const Expr *IdxExpr, 252239462Sdim uint64_t &Idx) 253239462Sdim{ 254263508Sdim assert(isFunctionOrMethod(D)); 255239462Sdim 256239462Sdim // In C++ the implicit 'this' function parameter also counts. 257239462Sdim // Parameters are counted from one. 258263508Sdim bool HP = hasFunctionProto(D); 259263508Sdim bool HasImplicitThisParam = isInstanceMethod(D); 260263508Sdim bool IV = HP && isFunctionOrMethodVariadic(D); 261263508Sdim unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) + 262263508Sdim HasImplicitThisParam; 263239462Sdim 264239462Sdim llvm::APSInt IdxInt; 265239462Sdim if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || 266239462Sdim !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { 267263508Sdim std::string Name = std::string("'") + AttrName.str() + std::string("'"); 268263508Sdim S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str() 269263508Sdim << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); 270239462Sdim return false; 271239462Sdim } 272239462Sdim 273239462Sdim Idx = IdxInt.getLimitedValue(); 274263508Sdim if (Idx < 1 || (!IV && Idx > NumArgs)) { 275239462Sdim S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds) 276239462Sdim << AttrName << AttrArgNum << IdxExpr->getSourceRange(); 277239462Sdim return false; 278239462Sdim } 279239462Sdim Idx--; // Convert to zero-based. 280239462Sdim if (HasImplicitThisParam) { 281239462Sdim if (Idx == 0) { 282239462Sdim S.Diag(AttrLoc, 283239462Sdim diag::err_attribute_invalid_implicit_this_argument) 284239462Sdim << AttrName << IdxExpr->getSourceRange(); 285239462Sdim return false; 286239462Sdim } 287239462Sdim --Idx; 288239462Sdim } 289239462Sdim 290239462Sdim return true; 291239462Sdim} 292239462Sdim 293263508Sdim/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal. 294263508Sdim/// If not emit an error and return false. If the argument is an identifier it 295263508Sdim/// will emit an error with a fixit hint and treat it as if it was a string 296263508Sdim/// literal. 297263508Sdimbool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr, 298263508Sdim unsigned ArgNum, StringRef &Str, 299263508Sdim SourceLocation *ArgLocation) { 300263508Sdim // Look for identifiers. If we have one emit a hint to fix it to a literal. 301263508Sdim if (Attr.isArgIdent(ArgNum)) { 302263508Sdim IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum); 303263508Sdim Diag(Loc->Loc, diag::err_attribute_argument_type) 304263508Sdim << Attr.getName() << AANT_ArgumentString 305263508Sdim << FixItHint::CreateInsertion(Loc->Loc, "\"") 306263508Sdim << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\""); 307263508Sdim Str = Loc->Ident->getName(); 308263508Sdim if (ArgLocation) 309263508Sdim *ArgLocation = Loc->Loc; 310263508Sdim return true; 311263508Sdim } 312263508Sdim 313263508Sdim // Now check for an actual string literal. 314263508Sdim Expr *ArgExpr = Attr.getArgAsExpr(ArgNum); 315263508Sdim StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); 316263508Sdim if (ArgLocation) 317263508Sdim *ArgLocation = ArgExpr->getLocStart(); 318263508Sdim 319263508Sdim if (!Literal || !Literal->isAscii()) { 320263508Sdim Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) 321263508Sdim << Attr.getName() << AANT_ArgumentString; 322263508Sdim return false; 323263508Sdim } 324263508Sdim 325263508Sdim Str = Literal->getString(); 326263508Sdim return true; 327263508Sdim} 328263508Sdim 329239462Sdim/// 330226633Sdim/// \brief Check if passed in Decl is a field or potentially shared global var 331226633Sdim/// \return true if the Decl is a field or potentially shared global variable 332226633Sdim/// 333226633Sdimstatic bool mayBeSharedVariable(const Decl *D) { 334226633Sdim if (isa<FieldDecl>(D)) 335226633Sdim return true; 336226633Sdim if (const VarDecl *vd = dyn_cast<VarDecl>(D)) 337251662Sdim return vd->hasGlobalStorage() && !vd->getTLSKind(); 338226633Sdim 339226633Sdim return false; 340226633Sdim} 341226633Sdim 342226633Sdim/// \brief Check if the passed-in expression is of type int or bool. 343226633Sdimstatic bool isIntOrBool(Expr *Exp) { 344226633Sdim QualType QT = Exp->getType(); 345226633Sdim return QT->isBooleanType() || QT->isIntegerType(); 346226633Sdim} 347226633Sdim 348239462Sdim 349239462Sdim// Check to see if the type is a smart pointer of some kind. We assume 350239462Sdim// it's a smart pointer if it defines both operator-> and operator*. 351239462Sdimstatic bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { 352239462Sdim DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( 353239462Sdim S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); 354249423Sdim if (Res1.empty()) 355239462Sdim return false; 356239462Sdim 357239462Sdim DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( 358239462Sdim S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); 359249423Sdim if (Res2.empty()) 360239462Sdim return false; 361239462Sdim 362239462Sdim return true; 363239462Sdim} 364239462Sdim 365226633Sdim/// \brief Check if passed in Decl is a pointer type. 366226633Sdim/// Note that this function may produce an error message. 367226633Sdim/// \return true if the Decl is a pointer type; false otherwise 368239462Sdimstatic bool threadSafetyCheckIsPointer(Sema &S, const Decl *D, 369239462Sdim const AttributeList &Attr) { 370226633Sdim if (const ValueDecl *vd = dyn_cast<ValueDecl>(D)) { 371226633Sdim QualType QT = vd->getType(); 372226633Sdim if (QT->isAnyPointerType()) 373226633Sdim return true; 374239462Sdim 375239462Sdim if (const RecordType *RT = QT->getAs<RecordType>()) { 376239462Sdim // If it's an incomplete type, it could be a smart pointer; skip it. 377239462Sdim // (We don't want to force template instantiation if we can avoid it, 378239462Sdim // since that would alter the order in which templates are instantiated.) 379239462Sdim if (RT->isIncompleteType()) 380239462Sdim return true; 381239462Sdim 382239462Sdim if (threadSafetyCheckIsSmartPointer(S, RT)) 383239462Sdim return true; 384239462Sdim } 385239462Sdim 386239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_pointer) 387226633Sdim << Attr.getName()->getName() << QT; 388226633Sdim } else { 389226633Sdim S.Diag(Attr.getLoc(), diag::err_attribute_can_be_applied_only_to_value_decl) 390226633Sdim << Attr.getName(); 391226633Sdim } 392226633Sdim return false; 393226633Sdim} 394226633Sdim 395226633Sdim/// \brief Checks that the passed in QualType either is of RecordType or points 396226633Sdim/// to RecordType. Returns the relevant RecordType, null if it does not exit. 397226633Sdimstatic const RecordType *getRecordType(QualType QT) { 398226633Sdim if (const RecordType *RT = QT->getAs<RecordType>()) 399226633Sdim return RT; 400226633Sdim 401226633Sdim // Now check if we point to record type. 402226633Sdim if (const PointerType *PT = QT->getAs<PointerType>()) 403226633Sdim return PT->getPointeeType()->getAs<RecordType>(); 404226633Sdim 405226633Sdim return 0; 406226633Sdim} 407226633Sdim 408239462Sdim 409239462Sdimstatic bool checkBaseClassIsLockableCallback(const CXXBaseSpecifier *Specifier, 410239462Sdim CXXBasePath &Path, void *Unused) { 411239462Sdim const RecordType *RT = Specifier->getType()->getAs<RecordType>(); 412239462Sdim if (RT->getDecl()->getAttr<LockableAttr>()) 413239462Sdim return true; 414239462Sdim return false; 415239462Sdim} 416239462Sdim 417239462Sdim 418226633Sdim/// \brief Thread Safety Analysis: Checks that the passed in RecordType 419239462Sdim/// resolves to a lockable object. 420234353Sdimstatic void checkForLockableRecord(Sema &S, Decl *D, const AttributeList &Attr, 421234353Sdim QualType Ty) { 422234353Sdim const RecordType *RT = getRecordType(Ty); 423239462Sdim 424234353Sdim // Warn if could not get record type for this argument. 425226633Sdim if (!RT) { 426239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_class) 427234353Sdim << Attr.getName() << Ty.getAsString(); 428234353Sdim return; 429226633Sdim } 430239462Sdim 431239462Sdim // Don't check for lockable if the class hasn't been defined yet. 432234353Sdim if (RT->isIncompleteType()) 433234353Sdim return; 434239462Sdim 435239462Sdim // Allow smart pointers to be used as lockable objects. 436239462Sdim // FIXME -- Check the type that the smart pointer points to. 437239462Sdim if (threadSafetyCheckIsSmartPointer(S, RT)) 438234353Sdim return; 439239462Sdim 440239462Sdim // Check if the type is lockable. 441239462Sdim RecordDecl *RD = RT->getDecl(); 442239462Sdim if (RD->getAttr<LockableAttr>()) 443239462Sdim return; 444239462Sdim 445239462Sdim // Else check if any base classes are lockable. 446239462Sdim if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { 447239462Sdim CXXBasePaths BPaths(false, false); 448239462Sdim if (CRD->lookupInBases(checkBaseClassIsLockableCallback, 0, BPaths)) 449239462Sdim return; 450226633Sdim } 451239462Sdim 452239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_argument_not_lockable) 453239462Sdim << Attr.getName() << Ty.getAsString(); 454226633Sdim} 455226633Sdim 456226633Sdim/// \brief Thread Safety Analysis: Checks that all attribute arguments, starting 457239462Sdim/// from Sidx, resolve to a lockable object. 458226633Sdim/// \param Sidx The attribute argument index to start checking with. 459226633Sdim/// \param ParamIdxOk Whether an argument can be indexing into a function 460226633Sdim/// parameter list. 461239462Sdimstatic void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, 462226633Sdim const AttributeList &Attr, 463226633Sdim SmallVectorImpl<Expr*> &Args, 464226633Sdim int Sidx = 0, 465226633Sdim bool ParamIdxOk = false) { 466226633Sdim for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { 467263508Sdim Expr *ArgExp = Attr.getArgAsExpr(Idx); 468226633Sdim 469226633Sdim if (ArgExp->isTypeDependent()) { 470239462Sdim // FIXME -- need to check this again on template instantiation 471226633Sdim Args.push_back(ArgExp); 472226633Sdim continue; 473226633Sdim } 474226633Sdim 475239462Sdim if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) { 476243830Sdim if (StrLit->getLength() == 0 || 477263508Sdim (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) { 478243830Sdim // Pass empty strings to the analyzer without warnings. 479243830Sdim // Treat "*" as the universal lock. 480243830Sdim Args.push_back(ArgExp); 481239462Sdim continue; 482243830Sdim } 483239462Sdim 484239462Sdim // We allow constant strings to be used as a placeholder for expressions 485239462Sdim // that are not valid C++ syntax, but warn that they are ignored. 486239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) << 487239462Sdim Attr.getName(); 488243830Sdim Args.push_back(ArgExp); 489239462Sdim continue; 490239462Sdim } 491239462Sdim 492226633Sdim QualType ArgTy = ArgExp->getType(); 493226633Sdim 494239462Sdim // A pointer to member expression of the form &MyClass::mu is treated 495239462Sdim // specially -- we need to look at the type of the member. 496239462Sdim if (UnaryOperator *UOp = dyn_cast<UnaryOperator>(ArgExp)) 497239462Sdim if (UOp->getOpcode() == UO_AddrOf) 498239462Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UOp->getSubExpr())) 499239462Sdim if (DRE->getDecl()->isCXXInstanceMember()) 500239462Sdim ArgTy = DRE->getDecl()->getType(); 501239462Sdim 502226633Sdim // First see if we can just cast to record type, or point to record type. 503226633Sdim const RecordType *RT = getRecordType(ArgTy); 504226633Sdim 505226633Sdim // Now check if we index into a record type function param. 506226633Sdim if(!RT && ParamIdxOk) { 507226633Sdim FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 508226633Sdim IntegerLiteral *IL = dyn_cast<IntegerLiteral>(ArgExp); 509226633Sdim if(FD && IL) { 510226633Sdim unsigned int NumParams = FD->getNumParams(); 511226633Sdim llvm::APInt ArgValue = IL->getValue(); 512226633Sdim uint64_t ParamIdxFromOne = ArgValue.getZExtValue(); 513226633Sdim uint64_t ParamIdxFromZero = ParamIdxFromOne - 1; 514226633Sdim if(!ArgValue.isStrictlyPositive() || ParamIdxFromOne > NumParams) { 515226633Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_range) 516226633Sdim << Attr.getName() << Idx + 1 << NumParams; 517239462Sdim continue; 518226633Sdim } 519226633Sdim ArgTy = FD->getParamDecl(ParamIdxFromZero)->getType(); 520226633Sdim } 521226633Sdim } 522226633Sdim 523234353Sdim checkForLockableRecord(S, D, Attr, ArgTy); 524226633Sdim 525226633Sdim Args.push_back(ArgExp); 526226633Sdim } 527226633Sdim} 528226633Sdim 529193326Sed//===----------------------------------------------------------------------===// 530193326Sed// Attribute Implementations 531193326Sed//===----------------------------------------------------------------------===// 532193326Sed 533193326Sed// FIXME: All this manual attribute parsing code is gross. At the 534193326Sed// least add some helper functions to check most argument patterns (# 535193326Sed// and types of args). 536193326Sed 537239462Sdimenum ThreadAttributeDeclKind { 538239462Sdim ThreadExpectedFieldOrGlobalVar, 539239462Sdim ThreadExpectedFunctionOrMethod, 540239462Sdim ThreadExpectedClassOrStruct 541239462Sdim}; 542239462Sdim 543239462Sdimstatic bool checkGuardedVarAttrCommon(Sema &S, Decl *D, 544239462Sdim const AttributeList &Attr) { 545226633Sdim // D must be either a member field or global (potentially shared) variable. 546226633Sdim if (!mayBeSharedVariable(D)) { 547239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 548239462Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 549239462Sdim return false; 550226633Sdim } 551226633Sdim 552239462Sdim return true; 553239462Sdim} 554239462Sdim 555239462Sdimstatic void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { 556239462Sdim if (!checkGuardedVarAttrCommon(S, D, Attr)) 557226633Sdim return; 558226633Sdim 559249423Sdim D->addAttr(::new (S.Context) 560249423Sdim GuardedVarAttr(Attr.getRange(), S.Context, 561249423Sdim Attr.getAttributeSpellingListIndex())); 562226633Sdim} 563226633Sdim 564239462Sdimstatic void handlePtGuardedVarAttr(Sema &S, Decl *D, 565249423Sdim const AttributeList &Attr) { 566239462Sdim if (!checkGuardedVarAttrCommon(S, D, Attr)) 567239462Sdim return; 568239462Sdim 569239462Sdim if (!threadSafetyCheckIsPointer(S, D, Attr)) 570239462Sdim return; 571239462Sdim 572249423Sdim D->addAttr(::new (S.Context) 573249423Sdim PtGuardedVarAttr(Attr.getRange(), S.Context, 574249423Sdim Attr.getAttributeSpellingListIndex())); 575239462Sdim} 576239462Sdim 577239462Sdimstatic bool checkGuardedByAttrCommon(Sema &S, Decl *D, 578239462Sdim const AttributeList &Attr, 579239462Sdim Expr* &Arg) { 580226633Sdim // D must be either a member field or global (potentially shared) variable. 581226633Sdim if (!mayBeSharedVariable(D)) { 582239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 583239462Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 584239462Sdim return false; 585226633Sdim } 586226633Sdim 587239462Sdim SmallVector<Expr*, 1> Args; 588239462Sdim // check that all arguments are lockable objects 589239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 590239462Sdim unsigned Size = Args.size(); 591239462Sdim if (Size != 1) 592239462Sdim return false; 593239462Sdim 594239462Sdim Arg = Args[0]; 595239462Sdim 596239462Sdim return true; 597239462Sdim} 598239462Sdim 599239462Sdimstatic void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) { 600239462Sdim Expr *Arg = 0; 601239462Sdim if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) 602226633Sdim return; 603226633Sdim 604239462Sdim D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); 605239462Sdim} 606226633Sdim 607239462Sdimstatic void handlePtGuardedByAttr(Sema &S, Decl *D, 608239462Sdim const AttributeList &Attr) { 609239462Sdim Expr *Arg = 0; 610239462Sdim if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) 611239462Sdim return; 612239462Sdim 613239462Sdim if (!threadSafetyCheckIsPointer(S, D, Attr)) 614239462Sdim return; 615239462Sdim 616239462Sdim D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), 617239462Sdim S.Context, Arg)); 618226633Sdim} 619226633Sdim 620239462Sdimstatic bool checkLockableAttrCommon(Sema &S, Decl *D, 621239462Sdim const AttributeList &Attr) { 622226633Sdim // FIXME: Lockable structs for C code. 623263508Sdim if (!isa<RecordDecl>(D)) { 624239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 625239462Sdim << Attr.getName() << ThreadExpectedClassOrStruct; 626239462Sdim return false; 627226633Sdim } 628226633Sdim 629239462Sdim return true; 630226633Sdim} 631226633Sdim 632239462Sdimstatic void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 633239462Sdim if (!checkLockableAttrCommon(S, D, Attr)) 634239462Sdim return; 635239462Sdim 636239462Sdim D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); 637239462Sdim} 638239462Sdim 639239462Sdimstatic void handleScopedLockableAttr(Sema &S, Decl *D, 640239462Sdim const AttributeList &Attr) { 641239462Sdim if (!checkLockableAttrCommon(S, D, Attr)) 642239462Sdim return; 643239462Sdim 644249423Sdim D->addAttr(::new (S.Context) 645249423Sdim ScopedLockableAttr(Attr.getRange(), S.Context, 646249423Sdim Attr.getAttributeSpellingListIndex())); 647239462Sdim} 648239462Sdim 649249423Sdimstatic void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, 650249423Sdim const AttributeList &Attr) { 651226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 652239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 653239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 654226633Sdim return; 655226633Sdim } 656226633Sdim 657226633Sdim D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(), 658226633Sdim S.Context)); 659226633Sdim} 660226633Sdim 661249423Sdimstatic void handleNoSanitizeAddressAttr(Sema &S, Decl *D, 662239462Sdim const AttributeList &Attr) { 663234353Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 664249423Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 665234353Sdim << Attr.getName() << ExpectedFunctionOrMethod; 666234353Sdim return; 667234353Sdim } 668234353Sdim 669249423Sdim D->addAttr(::new (S.Context) 670249423Sdim NoSanitizeAddressAttr(Attr.getRange(), S.Context, 671249423Sdim Attr.getAttributeSpellingListIndex())); 672234353Sdim} 673234353Sdim 674249423Sdimstatic void handleNoSanitizeMemory(Sema &S, Decl *D, 675249423Sdim const AttributeList &Attr) { 676249423Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 677249423Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 678249423Sdim << Attr.getName() << ExpectedFunctionOrMethod; 679249423Sdim return; 680249423Sdim } 681249423Sdim 682249423Sdim D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(), 683249423Sdim S.Context)); 684249423Sdim} 685249423Sdim 686249423Sdimstatic void handleNoSanitizeThread(Sema &S, Decl *D, 687249423Sdim const AttributeList &Attr) { 688249423Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 689249423Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 690249423Sdim << Attr.getName() << ExpectedFunctionOrMethod; 691249423Sdim return; 692249423Sdim } 693249423Sdim 694249423Sdim D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(), 695249423Sdim S.Context)); 696249423Sdim} 697249423Sdim 698239462Sdimstatic bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, 699239462Sdim const AttributeList &Attr, 700263508Sdim SmallVectorImpl<Expr *> &Args) { 701226633Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 702239462Sdim return false; 703226633Sdim 704226633Sdim // D must be either a member field or global (potentially shared) variable. 705226633Sdim ValueDecl *VD = dyn_cast<ValueDecl>(D); 706226633Sdim if (!VD || !mayBeSharedVariable(D)) { 707239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 708239462Sdim << Attr.getName() << ThreadExpectedFieldOrGlobalVar; 709239462Sdim return false; 710226633Sdim } 711226633Sdim 712239462Sdim // Check that this attribute only applies to lockable types. 713226633Sdim QualType QT = VD->getType(); 714226633Sdim if (!QT->isDependentType()) { 715226633Sdim const RecordType *RT = getRecordType(QT); 716226633Sdim if (!RT || !RT->getDecl()->getAttr<LockableAttr>()) { 717239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) 718239462Sdim << Attr.getName(); 719239462Sdim return false; 720226633Sdim } 721226633Sdim } 722226633Sdim 723239462Sdim // Check that all arguments are lockable objects. 724239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 725251662Sdim if (Args.empty()) 726239462Sdim return false; 727239462Sdim 728239462Sdim return true; 729239462Sdim} 730239462Sdim 731239462Sdimstatic void handleAcquiredAfterAttr(Sema &S, Decl *D, 732239462Sdim const AttributeList &Attr) { 733226633Sdim SmallVector<Expr*, 1> Args; 734239462Sdim if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) 735226633Sdim return; 736226633Sdim 737239462Sdim Expr **StartArg = &Args[0]; 738249423Sdim D->addAttr(::new (S.Context) 739249423Sdim AcquiredAfterAttr(Attr.getRange(), S.Context, 740249423Sdim StartArg, Args.size(), 741249423Sdim Attr.getAttributeSpellingListIndex())); 742239462Sdim} 743226633Sdim 744239462Sdimstatic void handleAcquiredBeforeAttr(Sema &S, Decl *D, 745239462Sdim const AttributeList &Attr) { 746239462Sdim SmallVector<Expr*, 1> Args; 747239462Sdim if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) 748239462Sdim return; 749239462Sdim 750239462Sdim Expr **StartArg = &Args[0]; 751249423Sdim D->addAttr(::new (S.Context) 752249423Sdim AcquiredBeforeAttr(Attr.getRange(), S.Context, 753249423Sdim StartArg, Args.size(), 754249423Sdim Attr.getAttributeSpellingListIndex())); 755226633Sdim} 756226633Sdim 757239462Sdimstatic bool checkLockFunAttrCommon(Sema &S, Decl *D, 758239462Sdim const AttributeList &Attr, 759263508Sdim SmallVectorImpl<Expr *> &Args) { 760226633Sdim // zero or more arguments ok 761226633Sdim 762226633Sdim // check that the attribute is applied to a function 763226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 764239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 765239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 766239462Sdim return false; 767226633Sdim } 768226633Sdim 769226633Sdim // check that all arguments are lockable objects 770239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); 771239462Sdim 772239462Sdim return true; 773239462Sdim} 774239462Sdim 775239462Sdimstatic void handleSharedLockFunctionAttr(Sema &S, Decl *D, 776239462Sdim const AttributeList &Attr) { 777226633Sdim SmallVector<Expr*, 1> Args; 778239462Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 779226633Sdim return; 780226633Sdim 781226633Sdim unsigned Size = Args.size(); 782226633Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 783249423Sdim D->addAttr(::new (S.Context) 784249423Sdim SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, 785249423Sdim Attr.getAttributeSpellingListIndex())); 786239462Sdim} 787226633Sdim 788239462Sdimstatic void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, 789239462Sdim const AttributeList &Attr) { 790239462Sdim SmallVector<Expr*, 1> Args; 791239462Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 792239462Sdim return; 793239462Sdim 794239462Sdim unsigned Size = Args.size(); 795239462Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 796249423Sdim D->addAttr(::new (S.Context) 797249423Sdim ExclusiveLockFunctionAttr(Attr.getRange(), S.Context, 798249423Sdim StartArg, Size, 799249423Sdim Attr.getAttributeSpellingListIndex())); 800226633Sdim} 801226633Sdim 802263508Sdimstatic void handleAssertSharedLockAttr(Sema &S, Decl *D, 803263508Sdim const AttributeList &Attr) { 804263508Sdim SmallVector<Expr*, 1> Args; 805263508Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 806263508Sdim return; 807263508Sdim 808263508Sdim unsigned Size = Args.size(); 809263508Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 810263508Sdim D->addAttr(::new (S.Context) 811263508Sdim AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size, 812263508Sdim Attr.getAttributeSpellingListIndex())); 813263508Sdim} 814263508Sdim 815263508Sdimstatic void handleAssertExclusiveLockAttr(Sema &S, Decl *D, 816263508Sdim const AttributeList &Attr) { 817263508Sdim SmallVector<Expr*, 1> Args; 818263508Sdim if (!checkLockFunAttrCommon(S, D, Attr, Args)) 819263508Sdim return; 820263508Sdim 821263508Sdim unsigned Size = Args.size(); 822263508Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 823263508Sdim D->addAttr(::new (S.Context) 824263508Sdim AssertExclusiveLockAttr(Attr.getRange(), S.Context, 825263508Sdim StartArg, Size, 826263508Sdim Attr.getAttributeSpellingListIndex())); 827263508Sdim} 828263508Sdim 829263508Sdim 830239462Sdimstatic bool checkTryLockFunAttrCommon(Sema &S, Decl *D, 831239462Sdim const AttributeList &Attr, 832263508Sdim SmallVectorImpl<Expr *> &Args) { 833226633Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 834239462Sdim return false; 835226633Sdim 836226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 837239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 838239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 839239462Sdim return false; 840226633Sdim } 841226633Sdim 842263508Sdim if (!isIntOrBool(Attr.getArgAsExpr(0))) { 843263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 844263508Sdim << Attr.getName() << 1 << AANT_ArgumentIntOrBool; 845239462Sdim return false; 846226633Sdim } 847226633Sdim 848239462Sdim // check that all arguments are lockable objects 849239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1); 850239462Sdim 851239462Sdim return true; 852239462Sdim} 853239462Sdim 854239462Sdimstatic void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, 855239462Sdim const AttributeList &Attr) { 856226633Sdim SmallVector<Expr*, 2> Args; 857239462Sdim if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) 858226633Sdim return; 859226633Sdim 860249423Sdim D->addAttr(::new (S.Context) 861249423Sdim SharedTrylockFunctionAttr(Attr.getRange(), S.Context, 862263508Sdim Attr.getArgAsExpr(0), 863263508Sdim Args.data(), Args.size(), 864249423Sdim Attr.getAttributeSpellingListIndex())); 865239462Sdim} 866226633Sdim 867239462Sdimstatic void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, 868239462Sdim const AttributeList &Attr) { 869239462Sdim SmallVector<Expr*, 2> Args; 870239462Sdim if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) 871239462Sdim return; 872239462Sdim 873249423Sdim D->addAttr(::new (S.Context) 874249423Sdim ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, 875263508Sdim Attr.getArgAsExpr(0), 876263508Sdim Args.data(), Args.size(), 877249423Sdim Attr.getAttributeSpellingListIndex())); 878226633Sdim} 879226633Sdim 880239462Sdimstatic bool checkLocksRequiredCommon(Sema &S, Decl *D, 881239462Sdim const AttributeList &Attr, 882263508Sdim SmallVectorImpl<Expr *> &Args) { 883226633Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 884239462Sdim return false; 885226633Sdim 886226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 887239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 888239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 889239462Sdim return false; 890226633Sdim } 891226633Sdim 892226633Sdim // check that all arguments are lockable objects 893239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 894251662Sdim if (Args.empty()) 895239462Sdim return false; 896239462Sdim 897239462Sdim return true; 898239462Sdim} 899239462Sdim 900239462Sdimstatic void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, 901239462Sdim const AttributeList &Attr) { 902226633Sdim SmallVector<Expr*, 1> Args; 903239462Sdim if (!checkLocksRequiredCommon(S, D, Attr, Args)) 904226633Sdim return; 905226633Sdim 906239462Sdim Expr **StartArg = &Args[0]; 907249423Sdim D->addAttr(::new (S.Context) 908249423Sdim ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context, 909249423Sdim StartArg, Args.size(), 910249423Sdim Attr.getAttributeSpellingListIndex())); 911239462Sdim} 912226633Sdim 913239462Sdimstatic void handleSharedLocksRequiredAttr(Sema &S, Decl *D, 914239462Sdim const AttributeList &Attr) { 915239462Sdim SmallVector<Expr*, 1> Args; 916239462Sdim if (!checkLocksRequiredCommon(S, D, Attr, Args)) 917239462Sdim return; 918239462Sdim 919239462Sdim Expr **StartArg = &Args[0]; 920249423Sdim D->addAttr(::new (S.Context) 921249423Sdim SharedLocksRequiredAttr(Attr.getRange(), S.Context, 922249423Sdim StartArg, Args.size(), 923249423Sdim Attr.getAttributeSpellingListIndex())); 924226633Sdim} 925226633Sdim 926226633Sdimstatic void handleUnlockFunAttr(Sema &S, Decl *D, 927226633Sdim const AttributeList &Attr) { 928226633Sdim // zero or more arguments ok 929226633Sdim 930226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 931239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 932239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 933226633Sdim return; 934226633Sdim } 935226633Sdim 936226633Sdim // check that all arguments are lockable objects 937226633Sdim SmallVector<Expr*, 1> Args; 938239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); 939226633Sdim unsigned Size = Args.size(); 940226633Sdim Expr **StartArg = Size == 0 ? 0 : &Args[0]; 941226633Sdim 942249423Sdim D->addAttr(::new (S.Context) 943249423Sdim UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, 944249423Sdim Attr.getAttributeSpellingListIndex())); 945226633Sdim} 946226633Sdim 947226633Sdimstatic void handleLockReturnedAttr(Sema &S, Decl *D, 948226633Sdim const AttributeList &Attr) { 949226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 950239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 951239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 952226633Sdim return; 953226633Sdim } 954226633Sdim 955226633Sdim // check that the argument is lockable object 956239462Sdim SmallVector<Expr*, 1> Args; 957239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 958239462Sdim unsigned Size = Args.size(); 959239462Sdim if (Size == 0) 960239462Sdim return; 961226633Sdim 962249423Sdim D->addAttr(::new (S.Context) 963249423Sdim LockReturnedAttr(Attr.getRange(), S.Context, Args[0], 964249423Sdim Attr.getAttributeSpellingListIndex())); 965226633Sdim} 966226633Sdim 967226633Sdimstatic void handleLocksExcludedAttr(Sema &S, Decl *D, 968226633Sdim const AttributeList &Attr) { 969226633Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 970226633Sdim return; 971226633Sdim 972226633Sdim if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { 973239462Sdim S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) 974239462Sdim << Attr.getName() << ThreadExpectedFunctionOrMethod; 975226633Sdim return; 976226633Sdim } 977226633Sdim 978226633Sdim // check that all arguments are lockable objects 979226633Sdim SmallVector<Expr*, 1> Args; 980239462Sdim checkAttrArgsAreLockableObjs(S, D, Attr, Args); 981239462Sdim unsigned Size = Args.size(); 982239462Sdim if (Size == 0) 983226633Sdim return; 984239462Sdim Expr **StartArg = &Args[0]; 985226633Sdim 986249423Sdim D->addAttr(::new (S.Context) 987249423Sdim LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size, 988249423Sdim Attr.getAttributeSpellingListIndex())); 989226633Sdim} 990226633Sdim 991263508Sdimstatic void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 992263508Sdim ConsumableAttr::ConsumedState DefaultState; 993226633Sdim 994263508Sdim if (Attr.isArgIdent(0)) { 995263508Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 996263508Sdim if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), 997263508Sdim DefaultState)) { 998263508Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) 999263508Sdim << Attr.getName() << IL->Ident; 1000263508Sdim return; 1001263508Sdim } 1002263508Sdim } else { 1003263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 1004263508Sdim << Attr.getName() << AANT_ArgumentIdentifier; 1005263508Sdim return; 1006263508Sdim } 1007263508Sdim 1008263508Sdim if (!isa<CXXRecordDecl>(D)) { 1009263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1010263508Sdim Attr.getName() << ExpectedClass; 1011263508Sdim return; 1012263508Sdim } 1013263508Sdim 1014263508Sdim D->addAttr(::new (S.Context) 1015263508Sdim ConsumableAttr(Attr.getRange(), S.Context, DefaultState, 1016263508Sdim Attr.getAttributeSpellingListIndex())); 1017263508Sdim} 1018263508Sdim 1019263508Sdimstatic bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, 1020263508Sdim const AttributeList &Attr) { 1021263508Sdim ASTContext &CurrContext = S.getASTContext(); 1022263508Sdim QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); 1023263508Sdim 1024263508Sdim if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { 1025263508Sdim if (!RD->hasAttr<ConsumableAttr>()) { 1026263508Sdim S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) << 1027263508Sdim RD->getNameAsString(); 1028263508Sdim 1029263508Sdim return false; 1030263508Sdim } 1031263508Sdim } 1032263508Sdim 1033263508Sdim return true; 1034263508Sdim} 1035263508Sdim 1036263508Sdim 1037263508Sdimstatic void handleCallableWhenAttr(Sema &S, Decl *D, 1038263508Sdim const AttributeList &Attr) { 1039263508Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 1040263508Sdim return; 1041263508Sdim 1042263508Sdim if (!isa<CXXMethodDecl>(D)) { 1043263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1044263508Sdim Attr.getName() << ExpectedMethod; 1045263508Sdim return; 1046263508Sdim } 1047263508Sdim 1048263508Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1049263508Sdim return; 1050263508Sdim 1051263508Sdim SmallVector<CallableWhenAttr::ConsumedState, 3> States; 1052263508Sdim for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) { 1053263508Sdim CallableWhenAttr::ConsumedState CallableState; 1054263508Sdim 1055263508Sdim StringRef StateString; 1056263508Sdim SourceLocation Loc; 1057263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc)) 1058263508Sdim return; 1059263508Sdim 1060263508Sdim if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, 1061263508Sdim CallableState)) { 1062263508Sdim S.Diag(Loc, diag::warn_attribute_type_not_supported) 1063263508Sdim << Attr.getName() << StateString; 1064263508Sdim return; 1065263508Sdim } 1066263508Sdim 1067263508Sdim States.push_back(CallableState); 1068263508Sdim } 1069263508Sdim 1070263508Sdim D->addAttr(::new (S.Context) 1071263508Sdim CallableWhenAttr(Attr.getRange(), S.Context, States.data(), 1072263508Sdim States.size(), Attr.getAttributeSpellingListIndex())); 1073263508Sdim} 1074263508Sdim 1075263508Sdim 1076263508Sdimstatic void handleParamTypestateAttr(Sema &S, Decl *D, 1077263508Sdim const AttributeList &Attr) { 1078263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) return; 1079263508Sdim 1080263508Sdim if (!isa<ParmVarDecl>(D)) { 1081263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1082263508Sdim Attr.getName() << ExpectedParameter; 1083263508Sdim return; 1084263508Sdim } 1085263508Sdim 1086263508Sdim ParamTypestateAttr::ConsumedState ParamState; 1087263508Sdim 1088263508Sdim if (Attr.isArgIdent(0)) { 1089263508Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1090263508Sdim StringRef StateString = Ident->Ident->getName(); 1091263508Sdim 1092263508Sdim if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, 1093263508Sdim ParamState)) { 1094263508Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1095263508Sdim << Attr.getName() << StateString; 1096263508Sdim return; 1097263508Sdim } 1098263508Sdim } else { 1099263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1100263508Sdim Attr.getName() << AANT_ArgumentIdentifier; 1101263508Sdim return; 1102263508Sdim } 1103263508Sdim 1104263508Sdim // FIXME: This check is currently being done in the analysis. It can be 1105263508Sdim // enabled here only after the parser propagates attributes at 1106263508Sdim // template specialization definition, not declaration. 1107263508Sdim //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); 1108263508Sdim //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 1109263508Sdim // 1110263508Sdim //if (!RD || !RD->hasAttr<ConsumableAttr>()) { 1111263508Sdim // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << 1112263508Sdim // ReturnType.getAsString(); 1113263508Sdim // return; 1114263508Sdim //} 1115263508Sdim 1116263508Sdim D->addAttr(::new (S.Context) 1117263508Sdim ParamTypestateAttr(Attr.getRange(), S.Context, ParamState, 1118263508Sdim Attr.getAttributeSpellingListIndex())); 1119263508Sdim} 1120263508Sdim 1121263508Sdim 1122263508Sdimstatic void handleReturnTypestateAttr(Sema &S, Decl *D, 1123263508Sdim const AttributeList &Attr) { 1124263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) return; 1125263508Sdim 1126263508Sdim if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) { 1127263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1128263508Sdim Attr.getName() << ExpectedFunctionMethodOrParameter; 1129263508Sdim return; 1130263508Sdim } 1131263508Sdim 1132263508Sdim ReturnTypestateAttr::ConsumedState ReturnState; 1133263508Sdim 1134263508Sdim if (Attr.isArgIdent(0)) { 1135263508Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 1136263508Sdim if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), 1137263508Sdim ReturnState)) { 1138263508Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) 1139263508Sdim << Attr.getName() << IL->Ident; 1140263508Sdim return; 1141263508Sdim } 1142263508Sdim } else { 1143263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1144263508Sdim Attr.getName() << AANT_ArgumentIdentifier; 1145263508Sdim return; 1146263508Sdim } 1147263508Sdim 1148263508Sdim // FIXME: This check is currently being done in the analysis. It can be 1149263508Sdim // enabled here only after the parser propagates attributes at 1150263508Sdim // template specialization definition, not declaration. 1151263508Sdim //QualType ReturnType; 1152263508Sdim // 1153263508Sdim //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { 1154263508Sdim // ReturnType = Param->getType(); 1155263508Sdim // 1156263508Sdim //} else if (const CXXConstructorDecl *Constructor = 1157263508Sdim // dyn_cast<CXXConstructorDecl>(D)) { 1158263508Sdim // ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType(); 1159263508Sdim // 1160263508Sdim //} else { 1161263508Sdim // 1162263508Sdim // ReturnType = cast<FunctionDecl>(D)->getCallResultType(); 1163263508Sdim //} 1164263508Sdim // 1165263508Sdim //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); 1166263508Sdim // 1167263508Sdim //if (!RD || !RD->hasAttr<ConsumableAttr>()) { 1168263508Sdim // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << 1169263508Sdim // ReturnType.getAsString(); 1170263508Sdim // return; 1171263508Sdim //} 1172263508Sdim 1173263508Sdim D->addAttr(::new (S.Context) 1174263508Sdim ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState, 1175263508Sdim Attr.getAttributeSpellingListIndex())); 1176263508Sdim} 1177263508Sdim 1178263508Sdim 1179263508Sdimstatic void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1180263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 1181263508Sdim return; 1182263508Sdim 1183263508Sdim if (!isa<CXXMethodDecl>(D)) { 1184263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1185263508Sdim Attr.getName() << ExpectedMethod; 1186263508Sdim return; 1187263508Sdim } 1188263508Sdim 1189263508Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1190263508Sdim return; 1191263508Sdim 1192263508Sdim SetTypestateAttr::ConsumedState NewState; 1193263508Sdim if (Attr.isArgIdent(0)) { 1194263508Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1195263508Sdim StringRef Param = Ident->Ident->getName(); 1196263508Sdim if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { 1197263508Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1198263508Sdim << Attr.getName() << Param; 1199263508Sdim return; 1200263508Sdim } 1201263508Sdim } else { 1202263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1203263508Sdim Attr.getName() << AANT_ArgumentIdentifier; 1204263508Sdim return; 1205263508Sdim } 1206263508Sdim 1207263508Sdim D->addAttr(::new (S.Context) 1208263508Sdim SetTypestateAttr(Attr.getRange(), S.Context, NewState, 1209263508Sdim Attr.getAttributeSpellingListIndex())); 1210263508Sdim} 1211263508Sdim 1212263508Sdimstatic void handleTestTypestateAttr(Sema &S, Decl *D, 1213263508Sdim const AttributeList &Attr) { 1214263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 1215263508Sdim return; 1216263508Sdim 1217263508Sdim if (!isa<CXXMethodDecl>(D)) { 1218263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << 1219263508Sdim Attr.getName() << ExpectedMethod; 1220263508Sdim return; 1221263508Sdim } 1222263508Sdim 1223263508Sdim if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) 1224263508Sdim return; 1225263508Sdim 1226263508Sdim TestTypestateAttr::ConsumedState TestState; 1227263508Sdim if (Attr.isArgIdent(0)) { 1228263508Sdim IdentifierLoc *Ident = Attr.getArgAsIdent(0); 1229263508Sdim StringRef Param = Ident->Ident->getName(); 1230263508Sdim if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { 1231263508Sdim S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) 1232263508Sdim << Attr.getName() << Param; 1233263508Sdim return; 1234263508Sdim } 1235263508Sdim } else { 1236263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << 1237263508Sdim Attr.getName() << AANT_ArgumentIdentifier; 1238263508Sdim return; 1239263508Sdim } 1240263508Sdim 1241263508Sdim D->addAttr(::new (S.Context) 1242263508Sdim TestTypestateAttr(Attr.getRange(), S.Context, TestState, 1243263508Sdim Attr.getAttributeSpellingListIndex())); 1244263508Sdim} 1245263508Sdim 1246224145Sdimstatic void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, 1247224145Sdim const AttributeList &Attr) { 1248249423Sdim TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); 1249249423Sdim if (TD == 0) { 1250249423Sdim // __attribute__((ext_vector_type(N))) can only be applied to typedefs 1251249423Sdim // and type-ids. 1252193326Sed S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); 1253193326Sed return; 1254193326Sed } 1255198092Srdivacky 1256249423Sdim // Remember this typedef decl, we will need it later for diagnostics. 1257249423Sdim S.ExtVectorDecls.push_back(TD); 1258193326Sed} 1259193326Sed 1260224145Sdimstatic void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1261224145Sdim if (TagDecl *TD = dyn_cast<TagDecl>(D)) 1262226633Sdim TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); 1263224145Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { 1264193326Sed // If the alignment is less than or equal to 8 bits, the packed attribute 1265193326Sed // has no effect. 1266243830Sdim if (!FD->getType()->isDependentType() && 1267243830Sdim !FD->getType()->isIncompleteType() && 1268193326Sed S.Context.getTypeAlign(FD->getType()) <= 8) 1269193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) 1270193326Sed << Attr.getName() << FD->getType(); 1271193326Sed else 1272249423Sdim FD->addAttr(::new (S.Context) 1273249423Sdim PackedAttr(Attr.getRange(), S.Context, 1274249423Sdim Attr.getAttributeSpellingListIndex())); 1275193326Sed } else 1276193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1277193326Sed} 1278193326Sed 1279224145Sdimstatic void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1280243830Sdim if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) 1281249423Sdim RD->addAttr(::new (S.Context) 1282249423Sdim MsStructAttr(Attr.getRange(), S.Context, 1283249423Sdim Attr.getAttributeSpellingListIndex())); 1284221345Sdim else 1285221345Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 1286221345Sdim} 1287221345Sdim 1288224145Sdimstatic void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { 1289204643Srdivacky // The IBAction attributes only apply to instance methods. 1290224145Sdim if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 1291204643Srdivacky if (MD->isInstanceMethod()) { 1292249423Sdim D->addAttr(::new (S.Context) 1293249423Sdim IBActionAttr(Attr.getRange(), S.Context, 1294249423Sdim Attr.getAttributeSpellingListIndex())); 1295204643Srdivacky return; 1296204643Srdivacky } 1297204643Srdivacky 1298218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); 1299204643Srdivacky} 1300204643Srdivacky 1301226633Sdimstatic bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) { 1302226633Sdim // The IBOutlet/IBOutletCollection attributes only apply to instance 1303226633Sdim // variables or properties of Objective-C classes. The outlet must also 1304226633Sdim // have an object reference type. 1305226633Sdim if (const ObjCIvarDecl *VD = dyn_cast<ObjCIvarDecl>(D)) { 1306226633Sdim if (!VD->getType()->getAs<ObjCObjectPointerType>()) { 1307234353Sdim S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) 1308226633Sdim << Attr.getName() << VD->getType() << 0; 1309226633Sdim return false; 1310226633Sdim } 1311226633Sdim } 1312226633Sdim else if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { 1313226633Sdim if (!PD->getType()->getAs<ObjCObjectPointerType>()) { 1314234353Sdim S.Diag(Attr.getLoc(), diag::warn_iboutlet_object_type) 1315226633Sdim << Attr.getName() << PD->getType() << 1; 1316226633Sdim return false; 1317226633Sdim } 1318226633Sdim } 1319226633Sdim else { 1320226633Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); 1321226633Sdim return false; 1322226633Sdim } 1323234353Sdim 1324226633Sdim return true; 1325226633Sdim} 1326226633Sdim 1327224145Sdimstatic void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { 1328226633Sdim if (!checkIBOutletCommon(S, D, Attr)) 1329204643Srdivacky return; 1330204643Srdivacky 1331249423Sdim D->addAttr(::new (S.Context) 1332249423Sdim IBOutletAttr(Attr.getRange(), S.Context, 1333249423Sdim Attr.getAttributeSpellingListIndex())); 1334193326Sed} 1335193326Sed 1336224145Sdimstatic void handleIBOutletCollection(Sema &S, Decl *D, 1337224145Sdim const AttributeList &Attr) { 1338208600Srdivacky 1339208600Srdivacky // The iboutletcollection attribute can have zero or one arguments. 1340263508Sdim if (Attr.getNumArgs() > 1) { 1341263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 1342263508Sdim << Attr.getName() << 1; 1343208600Srdivacky return; 1344208600Srdivacky } 1345208600Srdivacky 1346226633Sdim if (!checkIBOutletCommon(S, D, Attr)) 1347208600Srdivacky return; 1348226633Sdim 1349263508Sdim ParsedType PT; 1350263508Sdim 1351263508Sdim if (Attr.hasParsedType()) 1352263508Sdim PT = Attr.getTypeArg(); 1353263508Sdim else { 1354263508Sdim PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(), 1355263508Sdim S.getScopeForContext(D->getDeclContext()->getParent())); 1356263508Sdim if (!PT) { 1357263508Sdim S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; 1358263508Sdim return; 1359263508Sdim } 1360212904Sdim } 1361263508Sdim 1362263508Sdim TypeSourceInfo *QTLoc = 0; 1363263508Sdim QualType QT = S.GetTypeFromParser(PT, &QTLoc); 1364263508Sdim if (!QTLoc) 1365263508Sdim QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc()); 1366263508Sdim 1367212904Sdim // Diagnose use of non-object type in iboutletcollection attribute. 1368212904Sdim // FIXME. Gnu attribute extension ignores use of builtin types in 1369212904Sdim // attributes. So, __attribute__((iboutletcollection(char))) will be 1370212904Sdim // treated as __attribute__((iboutletcollection())). 1371234353Sdim if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { 1372263508Sdim S.Diag(Attr.getLoc(), 1373263508Sdim QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype 1374263508Sdim : diag::err_iboutletcollection_type) << QT; 1375212904Sdim return; 1376212904Sdim } 1377263508Sdim 1378249423Sdim D->addAttr(::new (S.Context) 1379263508Sdim IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc, 1380249423Sdim Attr.getAttributeSpellingListIndex())); 1381208600Srdivacky} 1382208600Srdivacky 1383224145Sdimstatic void possibleTransparentUnionPointerType(QualType &T) { 1384224145Sdim if (const RecordType *UT = T->getAsUnionType()) 1385224145Sdim if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { 1386224145Sdim RecordDecl *UD = UT->getDecl(); 1387224145Sdim for (RecordDecl::field_iterator it = UD->field_begin(), 1388224145Sdim itend = UD->field_end(); it != itend; ++it) { 1389224145Sdim QualType QT = it->getType(); 1390224145Sdim if (QT->isAnyPointerType() || QT->isBlockPointerType()) { 1391224145Sdim T = QT; 1392224145Sdim return; 1393224145Sdim } 1394224145Sdim } 1395224145Sdim } 1396224145Sdim} 1397224145Sdim 1398239462Sdimstatic void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1399239462Sdim if (!isFunctionOrMethod(D)) { 1400239462Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1401263508Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1402239462Sdim return; 1403239462Sdim } 1404239462Sdim 1405239462Sdim if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) 1406239462Sdim return; 1407239462Sdim 1408239462Sdim SmallVector<unsigned, 8> SizeArgs; 1409263508Sdim for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { 1410263508Sdim Expr *Ex = Attr.getArgAsExpr(i); 1411263508Sdim uint64_t Idx; 1412263508Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 1413263508Sdim Attr.getLoc(), i + 1, Ex, Idx)) 1414239462Sdim return; 1415239462Sdim 1416239462Sdim // check if the function argument is of an integer type 1417263508Sdim QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); 1418239462Sdim if (!T->isIntegerType()) { 1419263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 1420263508Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 1421263508Sdim << Ex->getSourceRange(); 1422239462Sdim return; 1423239462Sdim } 1424263508Sdim SizeArgs.push_back(Idx); 1425239462Sdim } 1426239462Sdim 1427239462Sdim // check if the function returns a pointer 1428239462Sdim if (!getFunctionType(D)->getResultType()->isAnyPointerType()) { 1429239462Sdim S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) 1430263508Sdim << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); 1431239462Sdim } 1432239462Sdim 1433249423Sdim D->addAttr(::new (S.Context) 1434249423Sdim AllocSizeAttr(Attr.getRange(), S.Context, 1435249423Sdim SizeArgs.data(), SizeArgs.size(), 1436249423Sdim Attr.getAttributeSpellingListIndex())); 1437239462Sdim} 1438239462Sdim 1439224145Sdimstatic void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1440198092Srdivacky // GCC ignores the nonnull attribute on K&R style function prototypes, so we 1441198092Srdivacky // ignore it as well 1442224145Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 1443193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1444221345Sdim << Attr.getName() << ExpectedFunction; 1445193326Sed return; 1446193326Sed } 1447198092Srdivacky 1448263508Sdim SmallVector<unsigned, 8> NonNullArgs; 1449263508Sdim for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { 1450263508Sdim Expr *Ex = Attr.getArgAsExpr(i); 1451263508Sdim uint64_t Idx; 1452263508Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 1453263508Sdim Attr.getLoc(), i + 1, Ex, Idx)) 1454193326Sed return; 1455198092Srdivacky 1456193326Sed // Is the function argument a pointer type? 1457263508Sdim QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); 1458224145Sdim possibleTransparentUnionPointerType(T); 1459224145Sdim 1460198092Srdivacky if (!T->isAnyPointerType() && !T->isBlockPointerType()) { 1461193326Sed // FIXME: Should also highlight argument in decl. 1462212904Sdim S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) 1463193326Sed << "nonnull" << Ex->getSourceRange(); 1464193326Sed continue; 1465193326Sed } 1466198092Srdivacky 1467263508Sdim NonNullArgs.push_back(Idx); 1468193326Sed } 1469198092Srdivacky 1470198092Srdivacky // If no arguments were specified to __attribute__((nonnull)) then all pointer 1471198092Srdivacky // arguments have a nonnull attribute. 1472193326Sed if (NonNullArgs.empty()) { 1473249423Sdim for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) { 1474249423Sdim QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType(); 1475224145Sdim possibleTransparentUnionPointerType(T); 1476198092Srdivacky if (T->isAnyPointerType() || T->isBlockPointerType()) 1477249423Sdim NonNullArgs.push_back(i); 1478193326Sed } 1479198092Srdivacky 1480218893Sdim // No pointer arguments? 1481193326Sed if (NonNullArgs.empty()) { 1482218893Sdim // Warn the trivial case only if attribute is not coming from a 1483218893Sdim // macro instantiation. 1484218893Sdim if (Attr.getLoc().isFileID()) 1485218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); 1486193326Sed return; 1487193326Sed } 1488193326Sed } 1489193326Sed 1490249423Sdim unsigned *start = &NonNullArgs[0]; 1491193326Sed unsigned size = NonNullArgs.size(); 1492212904Sdim llvm::array_pod_sort(start, start + size); 1493249423Sdim D->addAttr(::new (S.Context) 1494249423Sdim NonNullAttr(Attr.getRange(), S.Context, start, size, 1495249423Sdim Attr.getAttributeSpellingListIndex())); 1496193326Sed} 1497193326Sed 1498263508Sdimstatic const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) { 1499263508Sdim switch (K) { 1500263508Sdim case OwnershipAttr::Holds: return "'ownership_holds'"; 1501263508Sdim case OwnershipAttr::Takes: return "'ownership_takes'"; 1502263508Sdim case OwnershipAttr::Returns: return "'ownership_returns'"; 1503263508Sdim } 1504263508Sdim llvm_unreachable("unknown ownership"); 1505263508Sdim} 1506263508Sdim 1507224145Sdimstatic void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { 1508263508Sdim // This attribute must be applied to a function declaration. The first 1509263508Sdim // argument to the attribute must be an identifier, the name of the resource, 1510263508Sdim // for example: malloc. The following arguments must be argument indexes, the 1511263508Sdim // arguments must be of integer type for Returns, otherwise of pointer type. 1512212904Sdim // The difference between Holds and Takes is that a pointer may still be used 1513263508Sdim // after being held. free() should be __attribute((ownership_takes)), whereas 1514212904Sdim // a list append function may well be __attribute((ownership_holds)). 1515212904Sdim 1516263508Sdim if (!AL.isArgIdent(0)) { 1517263508Sdim S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) 1518263508Sdim << AL.getName() << 1 << AANT_ArgumentIdentifier; 1519212904Sdim return; 1520212904Sdim } 1521263508Sdim 1522212904Sdim // Figure out our Kind, and check arguments while we're at it. 1523212904Sdim OwnershipAttr::OwnershipKind K; 1524212904Sdim switch (AL.getKind()) { 1525212904Sdim case AttributeList::AT_ownership_takes: 1526212904Sdim K = OwnershipAttr::Takes; 1527263508Sdim if (AL.getNumArgs() < 2) { 1528263508Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; 1529212904Sdim return; 1530212904Sdim } 1531212904Sdim break; 1532212904Sdim case AttributeList::AT_ownership_holds: 1533212904Sdim K = OwnershipAttr::Holds; 1534263508Sdim if (AL.getNumArgs() < 2) { 1535263508Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2; 1536212904Sdim return; 1537212904Sdim } 1538212904Sdim break; 1539212904Sdim case AttributeList::AT_ownership_returns: 1540212904Sdim K = OwnershipAttr::Returns; 1541263508Sdim 1542263508Sdim if (AL.getNumArgs() > 2) { 1543263508Sdim S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1; 1544212904Sdim return; 1545212904Sdim } 1546212904Sdim break; 1547212904Sdim default: 1548212904Sdim // This should never happen given how we are called. 1549212904Sdim llvm_unreachable("Unknown ownership attribute"); 1550212904Sdim } 1551212904Sdim 1552224145Sdim if (!isFunction(D) || !hasFunctionProto(D)) { 1553221345Sdim S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) 1554221345Sdim << AL.getName() << ExpectedFunction; 1555212904Sdim return; 1556212904Sdim } 1557212904Sdim 1558263508Sdim StringRef Module = AL.getArgAsIdent(0)->Ident->getName(); 1559212904Sdim 1560212904Sdim // Normalize the argument, __foo__ becomes foo. 1561212904Sdim if (Module.startswith("__") && Module.endswith("__")) 1562212904Sdim Module = Module.substr(2, Module.size() - 4); 1563212904Sdim 1564263508Sdim SmallVector<unsigned, 8> OwnershipArgs; 1565263508Sdim for (unsigned i = 1; i < AL.getNumArgs(); ++i) { 1566263508Sdim Expr *Ex = AL.getArgAsExpr(i); 1567263508Sdim uint64_t Idx; 1568263508Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(), 1569263508Sdim AL.getLoc(), i, Ex, Idx)) 1570263508Sdim return; 1571212904Sdim 1572263508Sdim // Is the function argument a pointer type? 1573263508Sdim QualType T = getFunctionOrMethodArgType(D, Idx); 1574263508Sdim int Err = -1; // No error 1575212904Sdim switch (K) { 1576263508Sdim case OwnershipAttr::Takes: 1577263508Sdim case OwnershipAttr::Holds: 1578263508Sdim if (!T->isAnyPointerType() && !T->isBlockPointerType()) 1579263508Sdim Err = 0; 1580263508Sdim break; 1581263508Sdim case OwnershipAttr::Returns: 1582263508Sdim if (!T->isIntegerType()) 1583263508Sdim Err = 1; 1584263508Sdim break; 1585212904Sdim } 1586263508Sdim if (-1 != Err) { 1587263508Sdim S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err 1588263508Sdim << Ex->getSourceRange(); 1589263508Sdim return; 1590212904Sdim } 1591212904Sdim 1592212904Sdim // Check we don't have a conflict with another ownership attribute. 1593212904Sdim for (specific_attr_iterator<OwnershipAttr> 1594263508Sdim i = D->specific_attr_begin<OwnershipAttr>(), 1595263508Sdim e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { 1596263508Sdim if ((*i)->getOwnKind() != K && (*i)->args_end() != 1597263508Sdim std::find((*i)->args_begin(), (*i)->args_end(), Idx)) { 1598263508Sdim S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) 1599263508Sdim << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind()); 1600263508Sdim return; 1601212904Sdim } 1602212904Sdim } 1603263508Sdim OwnershipArgs.push_back(Idx); 1604212904Sdim } 1605212904Sdim 1606212904Sdim unsigned* start = OwnershipArgs.data(); 1607212904Sdim unsigned size = OwnershipArgs.size(); 1608212904Sdim llvm::array_pod_sort(start, start + size); 1609212904Sdim 1610249423Sdim D->addAttr(::new (S.Context) 1611249423Sdim OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, 1612249423Sdim AL.getAttributeSpellingListIndex())); 1613212904Sdim} 1614212904Sdim 1615224145Sdimstatic void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1616204643Srdivacky // Check the attribute arguments. 1617204643Srdivacky if (Attr.getNumArgs() > 1) { 1618263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 1619263508Sdim << Attr.getName() << 1; 1620204643Srdivacky return; 1621204643Srdivacky } 1622204643Srdivacky 1623224145Sdim if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { 1624218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1625221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 1626218893Sdim return; 1627218893Sdim } 1628218893Sdim 1629224145Sdim NamedDecl *nd = cast<NamedDecl>(D); 1630218893Sdim 1631204643Srdivacky // gcc rejects 1632204643Srdivacky // class c { 1633204643Srdivacky // static int a __attribute__((weakref ("v2"))); 1634204643Srdivacky // static int b() __attribute__((weakref ("f3"))); 1635204643Srdivacky // }; 1636204643Srdivacky // and ignores the attributes of 1637204643Srdivacky // void f(void) { 1638204643Srdivacky // static int a __attribute__((weakref ("v2"))); 1639204643Srdivacky // } 1640204643Srdivacky // we reject them 1641224145Sdim const DeclContext *Ctx = D->getDeclContext()->getRedeclContext(); 1642212904Sdim if (!Ctx->isFileContext()) { 1643212904Sdim S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << 1644218893Sdim nd->getNameAsString(); 1645212904Sdim return; 1646204643Srdivacky } 1647204643Srdivacky 1648204643Srdivacky // The GCC manual says 1649204643Srdivacky // 1650204643Srdivacky // At present, a declaration to which `weakref' is attached can only 1651204643Srdivacky // be `static'. 1652204643Srdivacky // 1653204643Srdivacky // It also says 1654204643Srdivacky // 1655204643Srdivacky // Without a TARGET, 1656204643Srdivacky // given as an argument to `weakref' or to `alias', `weakref' is 1657204643Srdivacky // equivalent to `weak'. 1658204643Srdivacky // 1659204643Srdivacky // gcc 4.4.1 will accept 1660204643Srdivacky // int a7 __attribute__((weakref)); 1661204643Srdivacky // as 1662204643Srdivacky // int a7 __attribute__((weak)); 1663204643Srdivacky // This looks like a bug in gcc. We reject that for now. We should revisit 1664204643Srdivacky // it if this behaviour is actually used. 1665204643Srdivacky 1666204643Srdivacky // GCC rejects 1667204643Srdivacky // static ((alias ("y"), weakref)). 1668204643Srdivacky // Should we? How to check that weakref is before or after alias? 1669204643Srdivacky 1670263508Sdim // FIXME: it would be good for us to keep the WeakRefAttr as-written instead 1671263508Sdim // of transforming it into an AliasAttr. The WeakRefAttr never uses the 1672263508Sdim // StringRef parameter it was given anyway. 1673263508Sdim StringRef Str; 1674263508Sdim if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 1675204643Srdivacky // GCC will accept anything as the argument of weakref. Should we 1676204643Srdivacky // check for an existing decl? 1677263508Sdim D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, 1678263508Sdim Attr.getAttributeSpellingListIndex())); 1679204643Srdivacky 1680249423Sdim D->addAttr(::new (S.Context) 1681249423Sdim WeakRefAttr(Attr.getRange(), S.Context, 1682249423Sdim Attr.getAttributeSpellingListIndex())); 1683204643Srdivacky} 1684204643Srdivacky 1685224145Sdimstatic void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1686263508Sdim StringRef Str; 1687263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 1688193326Sed return; 1689198092Srdivacky 1690226633Sdim if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { 1691218893Sdim S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); 1692218893Sdim return; 1693218893Sdim } 1694218893Sdim 1695193326Sed // FIXME: check if target symbol exists in current file 1696198092Srdivacky 1697263508Sdim D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, 1698249423Sdim Attr.getAttributeSpellingListIndex())); 1699193326Sed} 1700193326Sed 1701243830Sdimstatic void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1702243830Sdim if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { 1703243830Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1704243830Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1705243830Sdim return; 1706243830Sdim } 1707243830Sdim 1708249423Sdim D->addAttr(::new (S.Context) 1709249423Sdim MinSizeAttr(Attr.getRange(), S.Context, 1710249423Sdim Attr.getAttributeSpellingListIndex())); 1711243830Sdim} 1712243830Sdim 1713239462Sdimstatic void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1714239462Sdim if (!isa<FunctionDecl>(D)) { 1715239462Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1716239462Sdim << Attr.getName() << ExpectedFunction; 1717239462Sdim return; 1718239462Sdim } 1719239462Sdim 1720239462Sdim if (D->hasAttr<HotAttr>()) { 1721239462Sdim S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1722239462Sdim << Attr.getName() << "hot"; 1723239462Sdim return; 1724239462Sdim } 1725239462Sdim 1726249423Sdim D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, 1727249423Sdim Attr.getAttributeSpellingListIndex())); 1728239462Sdim} 1729239462Sdim 1730239462Sdimstatic void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1731239462Sdim if (!isa<FunctionDecl>(D)) { 1732239462Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1733239462Sdim << Attr.getName() << ExpectedFunction; 1734239462Sdim return; 1735239462Sdim } 1736239462Sdim 1737239462Sdim if (D->hasAttr<ColdAttr>()) { 1738239462Sdim S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) 1739239462Sdim << Attr.getName() << "cold"; 1740239462Sdim return; 1741239462Sdim } 1742239462Sdim 1743249423Sdim D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, 1744249423Sdim Attr.getAttributeSpellingListIndex())); 1745239462Sdim} 1746239462Sdim 1747224145Sdimstatic void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1748224145Sdim if (!isa<FunctionDecl>(D)) { 1749218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1750221345Sdim << Attr.getName() << ExpectedFunction; 1751218893Sdim return; 1752218893Sdim } 1753218893Sdim 1754249423Sdim D->addAttr(::new (S.Context) 1755249423Sdim NakedAttr(Attr.getRange(), S.Context, 1756249423Sdim Attr.getAttributeSpellingListIndex())); 1757218893Sdim} 1758218893Sdim 1759224145Sdimstatic void handleAlwaysInlineAttr(Sema &S, Decl *D, 1760224145Sdim const AttributeList &Attr) { 1761224145Sdim if (!isa<FunctionDecl>(D)) { 1762193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1763221345Sdim << Attr.getName() << ExpectedFunction; 1764193326Sed return; 1765193326Sed } 1766198092Srdivacky 1767249423Sdim D->addAttr(::new (S.Context) 1768249423Sdim AlwaysInlineAttr(Attr.getRange(), S.Context, 1769249423Sdim Attr.getAttributeSpellingListIndex())); 1770193326Sed} 1771193326Sed 1772239462Sdimstatic void handleTLSModelAttr(Sema &S, Decl *D, 1773239462Sdim const AttributeList &Attr) { 1774263508Sdim StringRef Model; 1775263508Sdim SourceLocation LiteralLoc; 1776239462Sdim // Check that it is a string. 1777263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc)) 1778239462Sdim return; 1779239462Sdim 1780251662Sdim if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) { 1781239462Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1782239462Sdim << Attr.getName() << ExpectedTLSVar; 1783239462Sdim return; 1784239462Sdim } 1785239462Sdim 1786239462Sdim // Check that the value. 1787239462Sdim if (Model != "global-dynamic" && Model != "local-dynamic" 1788239462Sdim && Model != "initial-exec" && Model != "local-exec") { 1789263508Sdim S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg); 1790239462Sdim return; 1791239462Sdim } 1792239462Sdim 1793249423Sdim D->addAttr(::new (S.Context) 1794249423Sdim TLSModelAttr(Attr.getRange(), S.Context, Model, 1795249423Sdim Attr.getAttributeSpellingListIndex())); 1796239462Sdim} 1797239462Sdim 1798224145Sdimstatic void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1799224145Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1800198092Srdivacky QualType RetTy = FD->getResultType(); 1801198092Srdivacky if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { 1802249423Sdim D->addAttr(::new (S.Context) 1803249423Sdim MallocAttr(Attr.getRange(), S.Context, 1804249423Sdim Attr.getAttributeSpellingListIndex())); 1805198092Srdivacky return; 1806198092Srdivacky } 1807198092Srdivacky } 1808198092Srdivacky 1809198092Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); 1810198092Srdivacky} 1811198092Srdivacky 1812224145Sdimstatic void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1813249423Sdim D->addAttr(::new (S.Context) 1814249423Sdim MayAliasAttr(Attr.getRange(), S.Context, 1815249423Sdim Attr.getAttributeSpellingListIndex())); 1816218893Sdim} 1817218893Sdim 1818224145Sdimstatic void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1819224145Sdim if (isa<VarDecl>(D)) 1820249423Sdim D->addAttr(::new (S.Context) 1821249423Sdim NoCommonAttr(Attr.getRange(), S.Context, 1822249423Sdim Attr.getAttributeSpellingListIndex())); 1823218893Sdim else 1824218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1825221345Sdim << Attr.getName() << ExpectedVariable; 1826212904Sdim} 1827212904Sdim 1828224145Sdimstatic void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1829263508Sdim if (S.LangOpts.CPlusPlus) { 1830263508Sdim S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus); 1831263508Sdim return; 1832263508Sdim } 1833263508Sdim 1834224145Sdim if (isa<VarDecl>(D)) 1835249423Sdim D->addAttr(::new (S.Context) 1836249423Sdim CommonAttr(Attr.getRange(), S.Context, 1837249423Sdim Attr.getAttributeSpellingListIndex())); 1838218893Sdim else 1839218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1840221345Sdim << Attr.getName() << ExpectedVariable; 1841218893Sdim} 1842218893Sdim 1843224145Sdimstatic void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { 1844224145Sdim if (hasDeclarator(D)) return; 1845218893Sdim 1846218893Sdim if (S.CheckNoReturnAttr(attr)) return; 1847218893Sdim 1848224145Sdim if (!isa<ObjCMethodDecl>(D)) { 1849218893Sdim S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1850221345Sdim << attr.getName() << ExpectedFunctionOrMethod; 1851218893Sdim return; 1852218893Sdim } 1853218893Sdim 1854249423Sdim D->addAttr(::new (S.Context) 1855249423Sdim NoReturnAttr(attr.getRange(), S.Context, 1856249423Sdim attr.getAttributeSpellingListIndex())); 1857218893Sdim} 1858218893Sdim 1859218893Sdimbool Sema::CheckNoReturnAttr(const AttributeList &attr) { 1860263508Sdim if (!checkAttributeNumArgs(*this, attr, 0)) { 1861218893Sdim attr.setInvalid(); 1862218893Sdim return true; 1863218893Sdim } 1864218893Sdim 1865218893Sdim return false; 1866218893Sdim} 1867218893Sdim 1868224145Sdimstatic void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, 1869224145Sdim const AttributeList &Attr) { 1870212904Sdim 1871212904Sdim // The checking path for 'noreturn' and 'analyzer_noreturn' are different 1872212904Sdim // because 'analyzer_noreturn' does not impact the type. 1873224145Sdim if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) { 1874224145Sdim ValueDecl *VD = dyn_cast<ValueDecl>(D); 1875200583Srdivacky if (VD == 0 || (!VD->getType()->isBlockPointerType() 1876200583Srdivacky && !VD->getType()->isFunctionPointerType())) { 1877199990Srdivacky S.Diag(Attr.getLoc(), 1878249423Sdim Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type 1879212904Sdim : diag::warn_attribute_wrong_decl_type) 1880221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 1881212904Sdim return; 1882193326Sed } 1883193326Sed } 1884212904Sdim 1885249423Sdim D->addAttr(::new (S.Context) 1886249423Sdim AnalyzerNoReturnAttr(Attr.getRange(), S.Context, 1887249423Sdim Attr.getAttributeSpellingListIndex())); 1888193326Sed} 1889193326Sed 1890249423Sdimstatic void handleCXX11NoReturnAttr(Sema &S, Decl *D, 1891249423Sdim const AttributeList &Attr) { 1892249423Sdim // C++11 [dcl.attr.noreturn]p1: 1893249423Sdim // The attribute may be applied to the declarator-id in a function 1894249423Sdim // declaration. 1895249423Sdim FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 1896249423Sdim if (!FD) { 1897249423Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1898249423Sdim << Attr.getName() << ExpectedFunctionOrMethod; 1899249423Sdim return; 1900249423Sdim } 1901249423Sdim 1902249423Sdim D->addAttr(::new (S.Context) 1903249423Sdim CXX11NoReturnAttr(Attr.getRange(), S.Context, 1904249423Sdim Attr.getAttributeSpellingListIndex())); 1905249423Sdim} 1906249423Sdim 1907212904Sdim// PS3 PPU-specific. 1908224145Sdimstatic void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1909212904Sdim/* 1910212904Sdim Returning a Vector Class in Registers 1911212904Sdim 1912218893Sdim According to the PPU ABI specifications, a class with a single member of 1913218893Sdim vector type is returned in memory when used as the return value of a function. 1914218893Sdim This results in inefficient code when implementing vector classes. To return 1915218893Sdim the value in a single vector register, add the vecreturn attribute to the 1916218893Sdim class definition. This attribute is also applicable to struct types. 1917212904Sdim 1918212904Sdim Example: 1919212904Sdim 1920212904Sdim struct Vector 1921212904Sdim { 1922212904Sdim __vector float xyzw; 1923212904Sdim } __attribute__((vecreturn)); 1924212904Sdim 1925212904Sdim Vector Add(Vector lhs, Vector rhs) 1926212904Sdim { 1927212904Sdim Vector result; 1928212904Sdim result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); 1929212904Sdim return result; // This will be returned in a register 1930212904Sdim } 1931212904Sdim*/ 1932224145Sdim if (!isa<RecordDecl>(D)) { 1933212904Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1934221345Sdim << Attr.getName() << ExpectedClass; 1935212904Sdim return; 1936212904Sdim } 1937193326Sed 1938224145Sdim if (D->getAttr<VecReturnAttr>()) { 1939212904Sdim S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; 1940212904Sdim return; 1941212904Sdim } 1942212904Sdim 1943224145Sdim RecordDecl *record = cast<RecordDecl>(D); 1944218893Sdim int count = 0; 1945218893Sdim 1946218893Sdim if (!isa<CXXRecordDecl>(record)) { 1947218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 1948218893Sdim return; 1949218893Sdim } 1950218893Sdim 1951218893Sdim if (!cast<CXXRecordDecl>(record)->isPOD()) { 1952218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record); 1953218893Sdim return; 1954218893Sdim } 1955218893Sdim 1956218893Sdim for (RecordDecl::field_iterator iter = record->field_begin(); 1957218893Sdim iter != record->field_end(); iter++) { 1958218893Sdim if ((count == 1) || !iter->getType()->isVectorType()) { 1959218893Sdim S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); 1960218893Sdim return; 1961218893Sdim } 1962218893Sdim count++; 1963218893Sdim } 1964218893Sdim 1965249423Sdim D->addAttr(::new (S.Context) 1966249423Sdim VecReturnAttr(Attr.getRange(), S.Context, 1967249423Sdim Attr.getAttributeSpellingListIndex())); 1968193326Sed} 1969193326Sed 1970249423Sdimstatic void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, 1971249423Sdim const AttributeList &Attr) { 1972249423Sdim if (isa<ParmVarDecl>(D)) { 1973249423Sdim // [[carries_dependency]] can only be applied to a parameter if it is a 1974249423Sdim // parameter of a function declaration or lambda. 1975249423Sdim if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { 1976249423Sdim S.Diag(Attr.getLoc(), 1977249423Sdim diag::err_carries_dependency_param_not_function_decl); 1978249423Sdim return; 1979249423Sdim } 1980249423Sdim } else if (!isa<FunctionDecl>(D)) { 1981199990Srdivacky S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 1982221345Sdim << Attr.getName() << ExpectedFunctionMethodOrParameter; 1983199990Srdivacky return; 1984199990Srdivacky } 1985249423Sdim 1986249423Sdim D->addAttr(::new (S.Context) CarriesDependencyAttr( 1987249423Sdim Attr.getRange(), S.Context, 1988249423Sdim Attr.getAttributeSpellingListIndex())); 1989199990Srdivacky} 1990199990Srdivacky 1991224145Sdimstatic void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 1992224145Sdim if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) && 1993239462Sdim !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) { 1994193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 1995221345Sdim << Attr.getName() << ExpectedVariableFunctionOrLabel; 1996193326Sed return; 1997193326Sed } 1998198092Srdivacky 1999249423Sdim D->addAttr(::new (S.Context) 2000249423Sdim UnusedAttr(Attr.getRange(), S.Context, 2001249423Sdim Attr.getAttributeSpellingListIndex())); 2002193326Sed} 2003193326Sed 2004226633Sdimstatic void handleReturnsTwiceAttr(Sema &S, Decl *D, 2005226633Sdim const AttributeList &Attr) { 2006226633Sdim if (!isa<FunctionDecl>(D)) { 2007226633Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2008226633Sdim << Attr.getName() << ExpectedFunction; 2009226633Sdim return; 2010226633Sdim } 2011226633Sdim 2012249423Sdim D->addAttr(::new (S.Context) 2013249423Sdim ReturnsTwiceAttr(Attr.getRange(), S.Context, 2014249423Sdim Attr.getAttributeSpellingListIndex())); 2015226633Sdim} 2016226633Sdim 2017224145Sdimstatic void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2018224145Sdim if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 2019263508Sdim if (VD->hasLocalStorage()) { 2020193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; 2021193326Sed return; 2022193326Sed } 2023224145Sdim } else if (!isFunctionOrMethod(D)) { 2024193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2025221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 2026193326Sed return; 2027193326Sed } 2028198092Srdivacky 2029249423Sdim D->addAttr(::new (S.Context) 2030249423Sdim UsedAttr(Attr.getRange(), S.Context, 2031249423Sdim Attr.getAttributeSpellingListIndex())); 2032193326Sed} 2033193326Sed 2034224145Sdimstatic void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2035193326Sed // check the attribute arguments. 2036221345Sdim if (Attr.getNumArgs() > 1) { 2037221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2038193326Sed return; 2039198092Srdivacky } 2040193326Sed 2041193326Sed int priority = 65535; // FIXME: Do not hardcode such constants. 2042193326Sed if (Attr.getNumArgs() > 0) { 2043263508Sdim Expr *E = Attr.getArgAsExpr(0); 2044193326Sed llvm::APSInt Idx(32); 2045208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2046208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2047263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2048263508Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2049263508Sdim << E->getSourceRange(); 2050193326Sed return; 2051193326Sed } 2052193326Sed priority = Idx.getZExtValue(); 2053193326Sed } 2054198092Srdivacky 2055224145Sdim if (!isa<FunctionDecl>(D)) { 2056193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2057221345Sdim << Attr.getName() << ExpectedFunction; 2058193326Sed return; 2059193326Sed } 2060193326Sed 2061249423Sdim D->addAttr(::new (S.Context) 2062249423Sdim ConstructorAttr(Attr.getRange(), S.Context, priority, 2063249423Sdim Attr.getAttributeSpellingListIndex())); 2064193326Sed} 2065193326Sed 2066224145Sdimstatic void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2067193326Sed // check the attribute arguments. 2068221345Sdim if (Attr.getNumArgs() > 1) { 2069221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2070193326Sed return; 2071198092Srdivacky } 2072193326Sed 2073193326Sed int priority = 65535; // FIXME: Do not hardcode such constants. 2074193326Sed if (Attr.getNumArgs() > 0) { 2075263508Sdim Expr *E = Attr.getArgAsExpr(0); 2076193326Sed llvm::APSInt Idx(32); 2077208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2078208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2079263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2080263508Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2081263508Sdim << E->getSourceRange(); 2082193326Sed return; 2083193326Sed } 2084193326Sed priority = Idx.getZExtValue(); 2085193326Sed } 2086198092Srdivacky 2087224145Sdim if (!isa<FunctionDecl>(D)) { 2088193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2089221345Sdim << Attr.getName() << ExpectedFunction; 2090193326Sed return; 2091193326Sed } 2092193326Sed 2093249423Sdim D->addAttr(::new (S.Context) 2094249423Sdim DestructorAttr(Attr.getRange(), S.Context, priority, 2095249423Sdim Attr.getAttributeSpellingListIndex())); 2096193326Sed} 2097193326Sed 2098239462Sdimtemplate <typename AttrTy> 2099263508Sdimstatic void handleAttrWithMessage(Sema &S, Decl *D, 2100263508Sdim const AttributeList &Attr) { 2101219077Sdim unsigned NumArgs = Attr.getNumArgs(); 2102219077Sdim if (NumArgs > 1) { 2103221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; 2104193326Sed return; 2105193326Sed } 2106239462Sdim 2107239462Sdim // Handle the case where the attribute has a text message. 2108226633Sdim StringRef Str; 2109263508Sdim if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 2110263508Sdim return; 2111198092Srdivacky 2112249423Sdim D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, 2113249423Sdim Attr.getAttributeSpellingListIndex())); 2114193326Sed} 2115193326Sed 2116224145Sdimstatic void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, 2117224145Sdim const AttributeList &Attr) { 2118249423Sdim D->addAttr(::new (S.Context) 2119249423Sdim ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, 2120249423Sdim Attr.getAttributeSpellingListIndex())); 2121224145Sdim} 2122224145Sdim 2123234353Sdimstatic void handleObjCRootClassAttr(Sema &S, Decl *D, 2124234353Sdim const AttributeList &Attr) { 2125234353Sdim if (!isa<ObjCInterfaceDecl>(D)) { 2126263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2127263508Sdim << Attr.getName() << ExpectedObjectiveCInterface; 2128234353Sdim return; 2129234353Sdim } 2130234353Sdim 2131249423Sdim D->addAttr(::new (S.Context) 2132249423Sdim ObjCRootClassAttr(Attr.getRange(), S.Context, 2133249423Sdim Attr.getAttributeSpellingListIndex())); 2134234353Sdim} 2135234353Sdim 2136249423Sdimstatic void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, 2137249423Sdim const AttributeList &Attr) { 2138234353Sdim if (!isa<ObjCInterfaceDecl>(D)) { 2139234353Sdim S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); 2140234353Sdim return; 2141234353Sdim } 2142234353Sdim 2143249423Sdim D->addAttr(::new (S.Context) 2144249423Sdim ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context, 2145249423Sdim Attr.getAttributeSpellingListIndex())); 2146234353Sdim} 2147234353Sdim 2148239462Sdimstatic bool checkAvailabilityAttr(Sema &S, SourceRange Range, 2149239462Sdim IdentifierInfo *Platform, 2150239462Sdim VersionTuple Introduced, 2151239462Sdim VersionTuple Deprecated, 2152239462Sdim VersionTuple Obsoleted) { 2153239462Sdim StringRef PlatformName 2154239462Sdim = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); 2155239462Sdim if (PlatformName.empty()) 2156239462Sdim PlatformName = Platform->getName(); 2157239462Sdim 2158239462Sdim // Ensure that Introduced <= Deprecated <= Obsoleted (although not all 2159239462Sdim // of these steps are needed). 2160239462Sdim if (!Introduced.empty() && !Deprecated.empty() && 2161239462Sdim !(Introduced <= Deprecated)) { 2162239462Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2163239462Sdim << 1 << PlatformName << Deprecated.getAsString() 2164239462Sdim << 0 << Introduced.getAsString(); 2165239462Sdim return true; 2166239462Sdim } 2167239462Sdim 2168239462Sdim if (!Introduced.empty() && !Obsoleted.empty() && 2169239462Sdim !(Introduced <= Obsoleted)) { 2170239462Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2171239462Sdim << 2 << PlatformName << Obsoleted.getAsString() 2172239462Sdim << 0 << Introduced.getAsString(); 2173239462Sdim return true; 2174239462Sdim } 2175239462Sdim 2176239462Sdim if (!Deprecated.empty() && !Obsoleted.empty() && 2177239462Sdim !(Deprecated <= Obsoleted)) { 2178239462Sdim S.Diag(Range.getBegin(), diag::warn_availability_version_ordering) 2179239462Sdim << 2 << PlatformName << Obsoleted.getAsString() 2180239462Sdim << 1 << Deprecated.getAsString(); 2181239462Sdim return true; 2182239462Sdim } 2183239462Sdim 2184239462Sdim return false; 2185239462Sdim} 2186239462Sdim 2187249423Sdim/// \brief Check whether the two versions match. 2188249423Sdim/// 2189249423Sdim/// If either version tuple is empty, then they are assumed to match. If 2190249423Sdim/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. 2191249423Sdimstatic bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, 2192249423Sdim bool BeforeIsOkay) { 2193249423Sdim if (X.empty() || Y.empty()) 2194249423Sdim return true; 2195249423Sdim 2196249423Sdim if (X == Y) 2197249423Sdim return true; 2198249423Sdim 2199249423Sdim if (BeforeIsOkay && X < Y) 2200249423Sdim return true; 2201249423Sdim 2202249423Sdim return false; 2203249423Sdim} 2204249423Sdim 2205249423SdimAvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, 2206239462Sdim IdentifierInfo *Platform, 2207239462Sdim VersionTuple Introduced, 2208239462Sdim VersionTuple Deprecated, 2209239462Sdim VersionTuple Obsoleted, 2210239462Sdim bool IsUnavailable, 2211249423Sdim StringRef Message, 2212249423Sdim bool Override, 2213249423Sdim unsigned AttrSpellingListIndex) { 2214239462Sdim VersionTuple MergedIntroduced = Introduced; 2215239462Sdim VersionTuple MergedDeprecated = Deprecated; 2216239462Sdim VersionTuple MergedObsoleted = Obsoleted; 2217239462Sdim bool FoundAny = false; 2218239462Sdim 2219239462Sdim if (D->hasAttrs()) { 2220239462Sdim AttrVec &Attrs = D->getAttrs(); 2221239462Sdim for (unsigned i = 0, e = Attrs.size(); i != e;) { 2222239462Sdim const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); 2223239462Sdim if (!OldAA) { 2224239462Sdim ++i; 2225239462Sdim continue; 2226239462Sdim } 2227239462Sdim 2228239462Sdim IdentifierInfo *OldPlatform = OldAA->getPlatform(); 2229239462Sdim if (OldPlatform != Platform) { 2230239462Sdim ++i; 2231239462Sdim continue; 2232239462Sdim } 2233239462Sdim 2234239462Sdim FoundAny = true; 2235239462Sdim VersionTuple OldIntroduced = OldAA->getIntroduced(); 2236239462Sdim VersionTuple OldDeprecated = OldAA->getDeprecated(); 2237239462Sdim VersionTuple OldObsoleted = OldAA->getObsoleted(); 2238239462Sdim bool OldIsUnavailable = OldAA->getUnavailable(); 2239239462Sdim 2240249423Sdim if (!versionsMatch(OldIntroduced, Introduced, Override) || 2241249423Sdim !versionsMatch(Deprecated, OldDeprecated, Override) || 2242249423Sdim !versionsMatch(Obsoleted, OldObsoleted, Override) || 2243249423Sdim !(OldIsUnavailable == IsUnavailable || 2244249423Sdim (Override && !OldIsUnavailable && IsUnavailable))) { 2245249423Sdim if (Override) { 2246249423Sdim int Which = -1; 2247249423Sdim VersionTuple FirstVersion; 2248249423Sdim VersionTuple SecondVersion; 2249249423Sdim if (!versionsMatch(OldIntroduced, Introduced, Override)) { 2250249423Sdim Which = 0; 2251249423Sdim FirstVersion = OldIntroduced; 2252249423Sdim SecondVersion = Introduced; 2253249423Sdim } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { 2254249423Sdim Which = 1; 2255249423Sdim FirstVersion = Deprecated; 2256249423Sdim SecondVersion = OldDeprecated; 2257249423Sdim } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { 2258249423Sdim Which = 2; 2259249423Sdim FirstVersion = Obsoleted; 2260249423Sdim SecondVersion = OldObsoleted; 2261249423Sdim } 2262249423Sdim 2263249423Sdim if (Which == -1) { 2264249423Sdim Diag(OldAA->getLocation(), 2265249423Sdim diag::warn_mismatched_availability_override_unavail) 2266249423Sdim << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); 2267249423Sdim } else { 2268249423Sdim Diag(OldAA->getLocation(), 2269249423Sdim diag::warn_mismatched_availability_override) 2270249423Sdim << Which 2271249423Sdim << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) 2272249423Sdim << FirstVersion.getAsString() << SecondVersion.getAsString(); 2273249423Sdim } 2274249423Sdim Diag(Range.getBegin(), diag::note_overridden_method); 2275249423Sdim } else { 2276249423Sdim Diag(OldAA->getLocation(), diag::warn_mismatched_availability); 2277249423Sdim Diag(Range.getBegin(), diag::note_previous_attribute); 2278249423Sdim } 2279249423Sdim 2280239462Sdim Attrs.erase(Attrs.begin() + i); 2281239462Sdim --e; 2282239462Sdim continue; 2283239462Sdim } 2284239462Sdim 2285239462Sdim VersionTuple MergedIntroduced2 = MergedIntroduced; 2286239462Sdim VersionTuple MergedDeprecated2 = MergedDeprecated; 2287239462Sdim VersionTuple MergedObsoleted2 = MergedObsoleted; 2288239462Sdim 2289239462Sdim if (MergedIntroduced2.empty()) 2290239462Sdim MergedIntroduced2 = OldIntroduced; 2291239462Sdim if (MergedDeprecated2.empty()) 2292239462Sdim MergedDeprecated2 = OldDeprecated; 2293239462Sdim if (MergedObsoleted2.empty()) 2294239462Sdim MergedObsoleted2 = OldObsoleted; 2295239462Sdim 2296239462Sdim if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, 2297239462Sdim MergedIntroduced2, MergedDeprecated2, 2298239462Sdim MergedObsoleted2)) { 2299239462Sdim Attrs.erase(Attrs.begin() + i); 2300239462Sdim --e; 2301239462Sdim continue; 2302239462Sdim } 2303239462Sdim 2304239462Sdim MergedIntroduced = MergedIntroduced2; 2305239462Sdim MergedDeprecated = MergedDeprecated2; 2306239462Sdim MergedObsoleted = MergedObsoleted2; 2307239462Sdim ++i; 2308239462Sdim } 2309239462Sdim } 2310239462Sdim 2311239462Sdim if (FoundAny && 2312239462Sdim MergedIntroduced == Introduced && 2313239462Sdim MergedDeprecated == Deprecated && 2314239462Sdim MergedObsoleted == Obsoleted) 2315239462Sdim return NULL; 2316239462Sdim 2317251662Sdim // Only create a new attribute if !Override, but we want to do 2318251662Sdim // the checking. 2319239462Sdim if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, 2320251662Sdim MergedDeprecated, MergedObsoleted) && 2321251662Sdim !Override) { 2322239462Sdim return ::new (Context) AvailabilityAttr(Range, Context, Platform, 2323239462Sdim Introduced, Deprecated, 2324249423Sdim Obsoleted, IsUnavailable, Message, 2325249423Sdim AttrSpellingListIndex); 2326239462Sdim } 2327239462Sdim return NULL; 2328239462Sdim} 2329239462Sdim 2330224145Sdimstatic void handleAvailabilityAttr(Sema &S, Decl *D, 2331224145Sdim const AttributeList &Attr) { 2332263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 2333263508Sdim return; 2334263508Sdim IdentifierLoc *Platform = Attr.getArgAsIdent(0); 2335249423Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2336249423Sdim 2337263508Sdim IdentifierInfo *II = Platform->Ident; 2338263508Sdim if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) 2339263508Sdim S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) 2340263508Sdim << Platform->Ident; 2341221345Sdim 2342249423Sdim NamedDecl *ND = dyn_cast<NamedDecl>(D); 2343249423Sdim if (!ND) { 2344249423Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2345249423Sdim return; 2346249423Sdim } 2347249423Sdim 2348221345Sdim AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); 2349221345Sdim AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); 2350221345Sdim AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); 2351221345Sdim bool IsUnavailable = Attr.getUnavailableLoc().isValid(); 2352234353Sdim StringRef Str; 2353263508Sdim if (const StringLiteral *SE = 2354263508Sdim dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr())) 2355234353Sdim Str = SE->getString(); 2356239462Sdim 2357263508Sdim AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II, 2358239462Sdim Introduced.Version, 2359239462Sdim Deprecated.Version, 2360239462Sdim Obsoleted.Version, 2361249423Sdim IsUnavailable, Str, 2362249423Sdim /*Override=*/false, 2363249423Sdim Index); 2364239462Sdim if (NewAttr) 2365239462Sdim D->addAttr(NewAttr); 2366221345Sdim} 2367221345Sdim 2368249423Sdimtemplate <class T> 2369249423Sdimstatic T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range, 2370249423Sdim typename T::VisibilityType value, 2371249423Sdim unsigned attrSpellingListIndex) { 2372249423Sdim T *existingAttr = D->getAttr<T>(); 2373249423Sdim if (existingAttr) { 2374249423Sdim typename T::VisibilityType existingValue = existingAttr->getVisibility(); 2375249423Sdim if (existingValue == value) 2376249423Sdim return NULL; 2377249423Sdim S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); 2378249423Sdim S.Diag(range.getBegin(), diag::note_previous_attribute); 2379249423Sdim D->dropAttr<T>(); 2380249423Sdim } 2381249423Sdim return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex); 2382249423Sdim} 2383249423Sdim 2384239462SdimVisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, 2385249423Sdim VisibilityAttr::VisibilityType Vis, 2386249423Sdim unsigned AttrSpellingListIndex) { 2387249423Sdim return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis, 2388249423Sdim AttrSpellingListIndex); 2389249423Sdim} 2390249423Sdim 2391249423SdimTypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, 2392249423Sdim TypeVisibilityAttr::VisibilityType Vis, 2393249423Sdim unsigned AttrSpellingListIndex) { 2394249423Sdim return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis, 2395249423Sdim AttrSpellingListIndex); 2396249423Sdim} 2397249423Sdim 2398249423Sdimstatic void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, 2399249423Sdim bool isTypeVisibility) { 2400249423Sdim // Visibility attributes don't mean anything on a typedef. 2401239462Sdim if (isa<TypedefNameDecl>(D)) { 2402249423Sdim S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) 2403249423Sdim << Attr.getName(); 2404249423Sdim return; 2405239462Sdim } 2406249423Sdim 2407249423Sdim // 'type_visibility' can only go on a type or namespace. 2408249423Sdim if (isTypeVisibility && 2409249423Sdim !(isa<TagDecl>(D) || 2410249423Sdim isa<ObjCInterfaceDecl>(D) || 2411249423Sdim isa<NamespaceDecl>(D))) { 2412249423Sdim S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type) 2413249423Sdim << Attr.getName() << ExpectedTypeOrNamespace; 2414249423Sdim return; 2415239462Sdim } 2416239462Sdim 2417263508Sdim // Check that the argument is a string literal. 2418263508Sdim StringRef TypeStr; 2419263508Sdim SourceLocation LiteralLoc; 2420263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc)) 2421193326Sed return; 2422198092Srdivacky 2423263508Sdim VisibilityAttr::VisibilityType type; 2424263508Sdim if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { 2425263508Sdim S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) 2426263508Sdim << Attr.getName() << TypeStr; 2427193326Sed return; 2428193326Sed } 2429249423Sdim 2430263508Sdim // Complain about attempts to use protected visibility on targets 2431263508Sdim // (like Darwin) that don't support it. 2432263508Sdim if (type == VisibilityAttr::Protected && 2433263508Sdim !S.Context.getTargetInfo().hasProtectedVisibility()) { 2434263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); 2435212904Sdim type = VisibilityAttr::Default; 2436193326Sed } 2437198092Srdivacky 2438249423Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2439249423Sdim clang::Attr *newAttr; 2440249423Sdim if (isTypeVisibility) { 2441249423Sdim newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(), 2442249423Sdim (TypeVisibilityAttr::VisibilityType) type, 2443249423Sdim Index); 2444249423Sdim } else { 2445249423Sdim newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index); 2446249423Sdim } 2447249423Sdim if (newAttr) 2448249423Sdim D->addAttr(newAttr); 2449193326Sed} 2450193326Sed 2451224145Sdimstatic void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, 2452224145Sdim const AttributeList &Attr) { 2453221345Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); 2454221345Sdim if (!method) { 2455224145Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2456221345Sdim << ExpectedMethod; 2457221345Sdim return; 2458221345Sdim } 2459221345Sdim 2460263508Sdim if (!Attr.isArgIdent(0)) { 2461263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2462263508Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 2463221345Sdim return; 2464221345Sdim } 2465221345Sdim 2466263508Sdim IdentifierLoc *IL = Attr.getArgAsIdent(0); 2467263508Sdim ObjCMethodFamilyAttr::FamilyKind F; 2468263508Sdim if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { 2469263508Sdim S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName() 2470263508Sdim << IL->Ident; 2471221345Sdim return; 2472221345Sdim } 2473221345Sdim 2474263508Sdim if (F == ObjCMethodFamilyAttr::OMF_init && 2475224145Sdim !method->getResultType()->isObjCObjectPointerType()) { 2476224145Sdim S.Diag(method->getLocation(), diag::err_init_method_bad_return_type) 2477224145Sdim << method->getResultType(); 2478224145Sdim // Ignore the attribute. 2479224145Sdim return; 2480224145Sdim } 2481224145Sdim 2482226633Sdim method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), 2483263508Sdim S.Context, F)); 2484221345Sdim} 2485221345Sdim 2486224145Sdimstatic void handleObjCExceptionAttr(Sema &S, Decl *D, 2487224145Sdim const AttributeList &Attr) { 2488193326Sed ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); 2489193326Sed if (OCI == 0) { 2490263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 2491263508Sdim << Attr.getName() << ExpectedObjectiveCInterface; 2492193326Sed return; 2493193326Sed } 2494198092Srdivacky 2495249423Sdim D->addAttr(::new (S.Context) 2496249423Sdim ObjCExceptionAttr(Attr.getRange(), S.Context, 2497249423Sdim Attr.getAttributeSpellingListIndex())); 2498193326Sed} 2499193326Sed 2500224145Sdimstatic void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { 2501221345Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 2502193326Sed QualType T = TD->getUnderlyingType(); 2503243830Sdim if (!T->isCARCBridgableType()) { 2504193326Sed S.Diag(TD->getLocation(), diag::err_nsobject_attribute); 2505193326Sed return; 2506193326Sed } 2507193326Sed } 2508239462Sdim else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { 2509239462Sdim QualType T = PD->getType(); 2510243830Sdim if (!T->isCARCBridgableType()) { 2511239462Sdim S.Diag(PD->getLocation(), diag::err_nsobject_attribute); 2512239462Sdim return; 2513239462Sdim } 2514239462Sdim } 2515239462Sdim else { 2516234353Sdim // It is okay to include this attribute on properties, e.g.: 2517234353Sdim // 2518234353Sdim // @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject)); 2519234353Sdim // 2520234353Sdim // In this case it follows tradition and suppresses an error in the above 2521234353Sdim // case. 2522234353Sdim S.Diag(D->getLocation(), diag::warn_nsobject_attribute); 2523234353Sdim } 2524249423Sdim D->addAttr(::new (S.Context) 2525249423Sdim ObjCNSObjectAttr(Attr.getRange(), S.Context, 2526249423Sdim Attr.getAttributeSpellingListIndex())); 2527193326Sed} 2528193326Sed 2529198092Srdivackystatic void 2530224145SdimhandleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2531193326Sed if (!isa<FunctionDecl>(D)) { 2532193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); 2533193326Sed return; 2534193326Sed } 2535193326Sed 2536249423Sdim D->addAttr(::new (S.Context) 2537249423Sdim OverloadableAttr(Attr.getRange(), S.Context, 2538249423Sdim Attr.getAttributeSpellingListIndex())); 2539193326Sed} 2540193326Sed 2541224145Sdimstatic void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2542263508Sdim if (!Attr.isArgIdent(0)) { 2543263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2544263508Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 2545193326Sed return; 2546193326Sed } 2547198092Srdivacky 2548263508Sdim IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; 2549212904Sdim BlocksAttr::BlockType type; 2550263508Sdim if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) { 2551193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 2552263508Sdim << Attr.getName() << II; 2553193326Sed return; 2554193326Sed } 2555198092Srdivacky 2556249423Sdim D->addAttr(::new (S.Context) 2557249423Sdim BlocksAttr(Attr.getRange(), S.Context, type, 2558249423Sdim Attr.getAttributeSpellingListIndex())); 2559193326Sed} 2560193326Sed 2561224145Sdimstatic void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2562193326Sed // check the attribute arguments. 2563193326Sed if (Attr.getNumArgs() > 2) { 2564221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; 2565193326Sed return; 2566198092Srdivacky } 2567198092Srdivacky 2568226633Sdim unsigned sentinel = 0; 2569193326Sed if (Attr.getNumArgs() > 0) { 2570263508Sdim Expr *E = Attr.getArgAsExpr(0); 2571193326Sed llvm::APSInt Idx(32); 2572208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2573208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2574263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2575263508Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 2576263508Sdim << E->getSourceRange(); 2577193326Sed return; 2578193326Sed } 2579198092Srdivacky 2580226633Sdim if (Idx.isSigned() && Idx.isNegative()) { 2581193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) 2582193326Sed << E->getSourceRange(); 2583193326Sed return; 2584193326Sed } 2585226633Sdim 2586226633Sdim sentinel = Idx.getZExtValue(); 2587193326Sed } 2588193326Sed 2589226633Sdim unsigned nullPos = 0; 2590193326Sed if (Attr.getNumArgs() > 1) { 2591263508Sdim Expr *E = Attr.getArgAsExpr(1); 2592193326Sed llvm::APSInt Idx(32); 2593208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2594208600Srdivacky !E->isIntegerConstantExpr(Idx, S.Context)) { 2595263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 2596263508Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 2597263508Sdim << E->getSourceRange(); 2598193326Sed return; 2599193326Sed } 2600193326Sed nullPos = Idx.getZExtValue(); 2601198092Srdivacky 2602226633Sdim if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { 2603193326Sed // FIXME: This error message could be improved, it would be nice 2604193326Sed // to say what the bounds actually are. 2605193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) 2606193326Sed << E->getSourceRange(); 2607193326Sed return; 2608193326Sed } 2609193326Sed } 2610193326Sed 2611224145Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 2612226633Sdim const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 2613193326Sed if (isa<FunctionNoProtoType>(FT)) { 2614193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); 2615193326Sed return; 2616193326Sed } 2617198092Srdivacky 2618193326Sed if (!cast<FunctionProtoType>(FT)->isVariadic()) { 2619193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 2620193326Sed return; 2621198092Srdivacky } 2622224145Sdim } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 2623193326Sed if (!MD->isVariadic()) { 2624193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; 2625193326Sed return; 2626193326Sed } 2627234353Sdim } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 2628234353Sdim if (!BD->isVariadic()) { 2629234353Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; 2630234353Sdim return; 2631234353Sdim } 2632224145Sdim } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) { 2633193326Sed QualType Ty = V->getType(); 2634193326Sed if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { 2635224145Sdim const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(D) 2636218893Sdim : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); 2637193326Sed if (!cast<FunctionProtoType>(FT)->isVariadic()) { 2638193326Sed int m = Ty->isFunctionPointerType() ? 0 : 1; 2639193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; 2640193326Sed return; 2641193326Sed } 2642198092Srdivacky } else { 2643193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2644221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 2645193326Sed return; 2646193326Sed } 2647193326Sed } else { 2648193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2649221345Sdim << Attr.getName() << ExpectedFunctionMethodOrBlock; 2650193326Sed return; 2651193326Sed } 2652249423Sdim D->addAttr(::new (S.Context) 2653249423Sdim SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos, 2654249423Sdim Attr.getAttributeSpellingListIndex())); 2655193326Sed} 2656193326Sed 2657263508Sdimstatic void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2658263508Sdim if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) 2659263508Sdim RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context)); 2660263508Sdim else 2661263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2662263508Sdim} 2663263508Sdim 2664224145Sdimstatic void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { 2665249423Sdim if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { 2666193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2667249423Sdim << Attr.getName() << ExpectedFunctionMethodOrClass; 2668193326Sed return; 2669193326Sed } 2670198092Srdivacky 2671206084Srdivacky if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) { 2672206084Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) 2673206084Srdivacky << Attr.getName() << 0; 2674201361Srdivacky return; 2675201361Srdivacky } 2676206084Srdivacky if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 2677206084Srdivacky if (MD->getResultType()->isVoidType()) { 2678206084Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) 2679206084Srdivacky << Attr.getName() << 1; 2680206084Srdivacky return; 2681206084Srdivacky } 2682206084Srdivacky 2683249423Sdim D->addAttr(::new (S.Context) 2684249423Sdim WarnUnusedResultAttr(Attr.getRange(), S.Context, 2685249423Sdim Attr.getAttributeSpellingListIndex())); 2686193326Sed} 2687193326Sed 2688224145Sdimstatic void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2689224145Sdim if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) { 2690234353Sdim if (isa<CXXRecordDecl>(D)) { 2691234353Sdim D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); 2692234353Sdim return; 2693234353Sdim } 2694224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2695224145Sdim << Attr.getName() << ExpectedVariableOrFunction; 2696198092Srdivacky return; 2697198092Srdivacky } 2698198092Srdivacky 2699224145Sdim NamedDecl *nd = cast<NamedDecl>(D); 2700218893Sdim 2701249423Sdim nd->addAttr(::new (S.Context) 2702249423Sdim WeakAttr(Attr.getRange(), S.Context, 2703249423Sdim Attr.getAttributeSpellingListIndex())); 2704193326Sed} 2705193326Sed 2706224145Sdimstatic void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2707193326Sed // weak_import only applies to variable & function declarations. 2708193326Sed bool isDef = false; 2709221345Sdim if (!D->canBeWeakImported(isDef)) { 2710221345Sdim if (isDef) 2711263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition) 2712263508Sdim << "weak_import"; 2713221345Sdim else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || 2714226633Sdim (S.Context.getTargetInfo().getTriple().isOSDarwin() && 2715234353Sdim (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { 2716221345Sdim // Nothing to warn about here. 2717221345Sdim } else 2718207619Srdivacky S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2719221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 2720193326Sed 2721193326Sed return; 2722193326Sed } 2723193326Sed 2724249423Sdim D->addAttr(::new (S.Context) 2725249423Sdim WeakImportAttr(Attr.getRange(), S.Context, 2726249423Sdim Attr.getAttributeSpellingListIndex())); 2727193326Sed} 2728193326Sed 2729239462Sdim// Handles reqd_work_group_size and work_group_size_hint. 2730239462Sdimstatic void handleWorkGroupSize(Sema &S, Decl *D, 2731239462Sdim const AttributeList &Attr) { 2732195099Sed unsigned WGSize[3]; 2733195099Sed for (unsigned i = 0; i < 3; ++i) { 2734263508Sdim Expr *E = Attr.getArgAsExpr(i); 2735195099Sed llvm::APSInt ArgNum(32); 2736208600Srdivacky if (E->isTypeDependent() || E->isValueDependent() || 2737208600Srdivacky !E->isIntegerConstantExpr(ArgNum, S.Context)) { 2738263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 2739263508Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 2740263508Sdim << E->getSourceRange(); 2741195099Sed return; 2742195099Sed } 2743195099Sed WGSize[i] = (unsigned) ArgNum.getZExtValue(); 2744195099Sed } 2745239462Sdim 2746239462Sdim if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize 2747239462Sdim && D->hasAttr<ReqdWorkGroupSizeAttr>()) { 2748239462Sdim ReqdWorkGroupSizeAttr *A = D->getAttr<ReqdWorkGroupSizeAttr>(); 2749239462Sdim if (!(A->getXDim() == WGSize[0] && 2750239462Sdim A->getYDim() == WGSize[1] && 2751239462Sdim A->getZDim() == WGSize[2])) { 2752239462Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << 2753239462Sdim Attr.getName(); 2754239462Sdim } 2755239462Sdim } 2756239462Sdim 2757239462Sdim if (Attr.getKind() == AttributeList::AT_WorkGroupSizeHint 2758239462Sdim && D->hasAttr<WorkGroupSizeHintAttr>()) { 2759239462Sdim WorkGroupSizeHintAttr *A = D->getAttr<WorkGroupSizeHintAttr>(); 2760239462Sdim if (!(A->getXDim() == WGSize[0] && 2761239462Sdim A->getYDim() == WGSize[1] && 2762239462Sdim A->getZDim() == WGSize[2])) { 2763239462Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << 2764239462Sdim Attr.getName(); 2765239462Sdim } 2766239462Sdim } 2767239462Sdim 2768239462Sdim if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) 2769239462Sdim D->addAttr(::new (S.Context) 2770239462Sdim ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, 2771249423Sdim WGSize[0], WGSize[1], WGSize[2], 2772249423Sdim Attr.getAttributeSpellingListIndex())); 2773239462Sdim else 2774239462Sdim D->addAttr(::new (S.Context) 2775239462Sdim WorkGroupSizeHintAttr(Attr.getRange(), S.Context, 2776249423Sdim WGSize[0], WGSize[1], WGSize[2], 2777249423Sdim Attr.getAttributeSpellingListIndex())); 2778195099Sed} 2779195099Sed 2780249423Sdimstatic void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { 2781249423Sdim assert(Attr.getKind() == AttributeList::AT_VecTypeHint); 2782249423Sdim 2783263508Sdim if (!Attr.hasParsedType()) { 2784263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 2785263508Sdim << Attr.getName() << 1; 2786249423Sdim return; 2787263508Sdim } 2788249423Sdim 2789263508Sdim TypeSourceInfo *ParmTSI = 0; 2790263508Sdim QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI); 2791263508Sdim assert(ParmTSI && "no type source info for attribute argument"); 2792249423Sdim 2793249423Sdim if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && 2794249423Sdim (ParmType->isBooleanType() || 2795249423Sdim !ParmType->isIntegralType(S.getASTContext()))) { 2796249423Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) 2797249423Sdim << ParmType; 2798249423Sdim return; 2799249423Sdim } 2800249423Sdim 2801249423Sdim if (Attr.getKind() == AttributeList::AT_VecTypeHint && 2802249423Sdim D->hasAttr<VecTypeHintAttr>()) { 2803249423Sdim VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); 2804263508Sdim if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) { 2805249423Sdim S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); 2806249423Sdim return; 2807249423Sdim } 2808249423Sdim } 2809249423Sdim 2810249423Sdim D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, 2811263508Sdim ParmTSI)); 2812249423Sdim} 2813249423Sdim 2814239462SdimSectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, 2815249423Sdim StringRef Name, 2816249423Sdim unsigned AttrSpellingListIndex) { 2817239462Sdim if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { 2818239462Sdim if (ExistingAttr->getName() == Name) 2819239462Sdim return NULL; 2820239462Sdim Diag(ExistingAttr->getLocation(), diag::warn_mismatched_section); 2821239462Sdim Diag(Range.getBegin(), diag::note_previous_attribute); 2822239462Sdim return NULL; 2823239462Sdim } 2824249423Sdim return ::new (Context) SectionAttr(Range, Context, Name, 2825249423Sdim AttrSpellingListIndex); 2826239462Sdim} 2827239462Sdim 2828224145Sdimstatic void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2829193326Sed // Make sure that there is a string literal as the sections's single 2830193326Sed // argument. 2831263508Sdim StringRef Str; 2832263508Sdim SourceLocation LiteralLoc; 2833263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc)) 2834193326Sed return; 2835198092Srdivacky 2836198092Srdivacky // If the target wants to validate the section specifier, make it happen. 2837263508Sdim std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str); 2838202379Srdivacky if (!Error.empty()) { 2839263508Sdim S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target) 2840202379Srdivacky << Error; 2841198092Srdivacky return; 2842198092Srdivacky } 2843198092Srdivacky 2844202379Srdivacky // This attribute cannot be applied to local variables. 2845202379Srdivacky if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { 2846263508Sdim S.Diag(LiteralLoc, diag::err_attribute_section_local_variable); 2847202379Srdivacky return; 2848202379Srdivacky } 2849249423Sdim 2850249423Sdim unsigned Index = Attr.getAttributeSpellingListIndex(); 2851263508Sdim SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index); 2852239462Sdim if (NewAttr) 2853239462Sdim D->addAttr(NewAttr); 2854193326Sed} 2855193326Sed 2856199482Srdivacky 2857224145Sdimstatic void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2858224145Sdim if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) { 2859224145Sdim if (Existing->getLocation().isInvalid()) 2860226633Sdim Existing->setRange(Attr.getRange()); 2861224145Sdim } else { 2862249423Sdim D->addAttr(::new (S.Context) 2863249423Sdim NoThrowAttr(Attr.getRange(), S.Context, 2864249423Sdim Attr.getAttributeSpellingListIndex())); 2865224145Sdim } 2866193326Sed} 2867193326Sed 2868224145Sdimstatic void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2869224145Sdim if (ConstAttr *Existing = D->getAttr<ConstAttr>()) { 2870224145Sdim if (Existing->getLocation().isInvalid()) 2871226633Sdim Existing->setRange(Attr.getRange()); 2872224145Sdim } else { 2873249423Sdim D->addAttr(::new (S.Context) 2874249423Sdim ConstAttr(Attr.getRange(), S.Context, 2875249423Sdim Attr.getAttributeSpellingListIndex() )); 2876224145Sdim } 2877193326Sed} 2878193326Sed 2879224145Sdimstatic void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2880249423Sdim D->addAttr(::new (S.Context) 2881249423Sdim PureAttr(Attr.getRange(), S.Context, 2882249423Sdim Attr.getAttributeSpellingListIndex())); 2883193326Sed} 2884193326Sed 2885224145Sdimstatic void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2886224145Sdim VarDecl *VD = dyn_cast<VarDecl>(D); 2887193326Sed if (!VD || !VD->hasLocalStorage()) { 2888263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 2889193326Sed return; 2890193326Sed } 2891198092Srdivacky 2892263508Sdim Expr *E = Attr.getArgAsExpr(0); 2893263508Sdim SourceLocation Loc = E->getExprLoc(); 2894263508Sdim FunctionDecl *FD = 0; 2895263508Sdim DeclarationNameInfo NI; 2896198092Srdivacky 2897263508Sdim // gcc only allows for simple identifiers. Since we support more than gcc, we 2898263508Sdim // will warn the user. 2899263508Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { 2900263508Sdim if (DRE->hasQualifier()) 2901263508Sdim S.Diag(Loc, diag::warn_cleanup_ext); 2902263508Sdim FD = dyn_cast<FunctionDecl>(DRE->getDecl()); 2903263508Sdim NI = DRE->getNameInfo(); 2904263508Sdim if (!FD) { 2905263508Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 2906263508Sdim << NI.getName(); 2907263508Sdim return; 2908263508Sdim } 2909263508Sdim } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { 2910263508Sdim if (ULE->hasExplicitTemplateArgs()) 2911263508Sdim S.Diag(Loc, diag::warn_cleanup_ext); 2912263508Sdim FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); 2913263508Sdim NI = ULE->getNameInfo(); 2914263508Sdim if (!FD) { 2915263508Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 2916263508Sdim << NI.getName(); 2917263508Sdim if (ULE->getType() == S.Context.OverloadTy) 2918263508Sdim S.NoteAllOverloadCandidates(ULE); 2919263508Sdim return; 2920263508Sdim } 2921263508Sdim } else { 2922263508Sdim S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0; 2923193326Sed return; 2924193326Sed } 2925193326Sed 2926193326Sed if (FD->getNumParams() != 1) { 2927263508Sdim S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) 2928263508Sdim << NI.getName(); 2929193326Sed return; 2930193326Sed } 2931198092Srdivacky 2932193326Sed // We're currently more strict than GCC about what function types we accept. 2933193326Sed // If this ever proves to be a problem it should be easy to fix. 2934193326Sed QualType Ty = S.Context.getPointerType(VD->getType()); 2935193326Sed QualType ParamTy = FD->getParamDecl(0)->getType(); 2936218893Sdim if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), 2937218893Sdim ParamTy, Ty) != Sema::Compatible) { 2938263508Sdim S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) 2939263508Sdim << NI.getName() << ParamTy << Ty; 2940193326Sed return; 2941193326Sed } 2942198092Srdivacky 2943249423Sdim D->addAttr(::new (S.Context) 2944249423Sdim CleanupAttr(Attr.getRange(), S.Context, FD, 2945249423Sdim Attr.getAttributeSpellingListIndex())); 2946193326Sed} 2947193326Sed 2948198092Srdivacky/// Handle __attribute__((format_arg((idx)))) attribute based on 2949198092Srdivacky/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 2950224145Sdimstatic void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { 2951224145Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 2952193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 2953221345Sdim << Attr.getName() << ExpectedFunction; 2954193326Sed return; 2955193326Sed } 2956218893Sdim 2957263508Sdim Expr *IdxExpr = Attr.getArgAsExpr(0); 2958263508Sdim uint64_t ArgIdx; 2959263508Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), 2960263508Sdim Attr.getLoc(), 1, IdxExpr, ArgIdx)) 2961193326Sed return; 2962198092Srdivacky 2963193326Sed // make sure the format string is really a string 2964224145Sdim QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); 2965198092Srdivacky 2966193326Sed bool not_nsstring_type = !isNSStringType(Ty, S.Context); 2967193326Sed if (not_nsstring_type && 2968193326Sed !isCFStringType(Ty, S.Context) && 2969193326Sed (!Ty->isPointerType() || 2970198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { 2971193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 2972193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 2973198092Srdivacky << (not_nsstring_type ? "a string type" : "an NSString") 2974193326Sed << IdxExpr->getSourceRange(); 2975193326Sed return; 2976198092Srdivacky } 2977224145Sdim Ty = getFunctionOrMethodResultType(D); 2978193326Sed if (!isNSStringType(Ty, S.Context) && 2979193326Sed !isCFStringType(Ty, S.Context) && 2980193326Sed (!Ty->isPointerType() || 2981198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { 2982193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 2983193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) 2984198092Srdivacky << (not_nsstring_type ? "string type" : "NSString") 2985193326Sed << IdxExpr->getSourceRange(); 2986193326Sed return; 2987198092Srdivacky } 2988198092Srdivacky 2989263508Sdim // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex 2990263508Sdim // because that has corrected for the implicit this parameter, and is zero- 2991263508Sdim // based. The attribute expects what the user wrote explicitly. 2992263508Sdim llvm::APSInt Val; 2993263508Sdim IdxExpr->EvaluateAsInt(Val, S.Context); 2994263508Sdim 2995249423Sdim D->addAttr(::new (S.Context) 2996263508Sdim FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(), 2997249423Sdim Attr.getAttributeSpellingListIndex())); 2998193326Sed} 2999193326Sed 3000198398Srdivackyenum FormatAttrKind { 3001198398Srdivacky CFStringFormat, 3002198398Srdivacky NSStringFormat, 3003198398Srdivacky StrftimeFormat, 3004198398Srdivacky SupportedFormat, 3005206084Srdivacky IgnoredFormat, 3006198398Srdivacky InvalidFormat 3007198398Srdivacky}; 3008198398Srdivacky 3009198398Srdivacky/// getFormatAttrKind - Map from format attribute names to supported format 3010198398Srdivacky/// types. 3011226633Sdimstatic FormatAttrKind getFormatAttrKind(StringRef Format) { 3012239462Sdim return llvm::StringSwitch<FormatAttrKind>(Format) 3013239462Sdim // Check for formats that get handled specially. 3014239462Sdim .Case("NSString", NSStringFormat) 3015239462Sdim .Case("CFString", CFStringFormat) 3016239462Sdim .Case("strftime", StrftimeFormat) 3017198398Srdivacky 3018239462Sdim // Otherwise, check for supported formats. 3019239462Sdim .Cases("scanf", "printf", "printf0", "strfmon", SupportedFormat) 3020239462Sdim .Cases("cmn_err", "vcmn_err", "zcmn_err", SupportedFormat) 3021239462Sdim .Case("kprintf", SupportedFormat) // OpenBSD. 3022198398Srdivacky 3023239462Sdim .Cases("gcc_diag", "gcc_cdiag", "gcc_cxxdiag", "gcc_tdiag", IgnoredFormat) 3024239462Sdim .Default(InvalidFormat); 3025198398Srdivacky} 3026198398Srdivacky 3027210299Sed/// Handle __attribute__((init_priority(priority))) attributes based on 3028210299Sed/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html 3029224145Sdimstatic void handleInitPriorityAttr(Sema &S, Decl *D, 3030224145Sdim const AttributeList &Attr) { 3031234353Sdim if (!S.getLangOpts().CPlusPlus) { 3032210299Sed S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 3033210299Sed return; 3034210299Sed } 3035210299Sed 3036224145Sdim if (!isa<VarDecl>(D) || S.getCurFunctionOrMethodDecl()) { 3037210299Sed S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); 3038210299Sed Attr.setInvalid(); 3039210299Sed return; 3040210299Sed } 3041224145Sdim QualType T = dyn_cast<VarDecl>(D)->getType(); 3042210299Sed if (S.Context.getAsArrayType(T)) 3043210299Sed T = S.Context.getBaseElementType(T); 3044210299Sed if (!T->getAs<RecordType>()) { 3045210299Sed S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); 3046210299Sed Attr.setInvalid(); 3047210299Sed return; 3048210299Sed } 3049210299Sed 3050263508Sdim Expr *priorityExpr = Attr.getArgAsExpr(0); 3051210299Sed 3052210299Sed llvm::APSInt priority(32); 3053210299Sed if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || 3054210299Sed !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { 3055263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3056263508Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3057263508Sdim << priorityExpr->getSourceRange(); 3058210299Sed Attr.setInvalid(); 3059210299Sed return; 3060210299Sed } 3061210299Sed unsigned prioritynum = priority.getZExtValue(); 3062210299Sed if (prioritynum < 101 || prioritynum > 65535) { 3063210299Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) 3064210299Sed << priorityExpr->getSourceRange(); 3065210299Sed Attr.setInvalid(); 3066210299Sed return; 3067210299Sed } 3068249423Sdim D->addAttr(::new (S.Context) 3069249423Sdim InitPriorityAttr(Attr.getRange(), S.Context, prioritynum, 3070249423Sdim Attr.getAttributeSpellingListIndex())); 3071210299Sed} 3072210299Sed 3073263508SdimFormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, 3074263508Sdim IdentifierInfo *Format, int FormatIdx, 3075263508Sdim int FirstArg, 3076249423Sdim unsigned AttrSpellingListIndex) { 3077239462Sdim // Check whether we already have an equivalent format attribute. 3078239462Sdim for (specific_attr_iterator<FormatAttr> 3079239462Sdim i = D->specific_attr_begin<FormatAttr>(), 3080239462Sdim e = D->specific_attr_end<FormatAttr>(); 3081239462Sdim i != e ; ++i) { 3082239462Sdim FormatAttr *f = *i; 3083239462Sdim if (f->getType() == Format && 3084239462Sdim f->getFormatIdx() == FormatIdx && 3085239462Sdim f->getFirstArg() == FirstArg) { 3086239462Sdim // If we don't have a valid location for this attribute, adopt the 3087239462Sdim // location. 3088239462Sdim if (f->getLocation().isInvalid()) 3089239462Sdim f->setRange(Range); 3090239462Sdim return NULL; 3091239462Sdim } 3092239462Sdim } 3093239462Sdim 3094263508Sdim return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, 3095263508Sdim FirstArg, AttrSpellingListIndex); 3096239462Sdim} 3097239462Sdim 3098198092Srdivacky/// Handle __attribute__((format(type,idx,firstarg))) attributes based on 3099198092Srdivacky/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html 3100224145Sdimstatic void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3101263508Sdim if (!Attr.isArgIdent(0)) { 3102263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3103263508Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 3104193326Sed return; 3105193326Sed } 3106193326Sed 3107224145Sdim if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) { 3108193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3109221345Sdim << Attr.getName() << ExpectedFunction; 3110193326Sed return; 3111193326Sed } 3112193326Sed 3113218893Sdim // In C++ the implicit 'this' function parameter also counts, and they are 3114218893Sdim // counted from one. 3115224145Sdim bool HasImplicitThisParam = isInstanceMethod(D); 3116224145Sdim unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; 3117193326Sed unsigned FirstIdx = 1; 3118193326Sed 3119263508Sdim IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; 3120263508Sdim StringRef Format = II->getName(); 3121193326Sed 3122193326Sed // Normalize the argument, __foo__ becomes foo. 3123263508Sdim if (Format.startswith("__") && Format.endswith("__")) { 3124198398Srdivacky Format = Format.substr(2, Format.size() - 4); 3125263508Sdim // If we've modified the string name, we need a new identifier for it. 3126263508Sdim II = &S.Context.Idents.get(Format); 3127263508Sdim } 3128193326Sed 3129198398Srdivacky // Check for supported formats. 3130198398Srdivacky FormatAttrKind Kind = getFormatAttrKind(Format); 3131206084Srdivacky 3132206084Srdivacky if (Kind == IgnoredFormat) 3133206084Srdivacky return; 3134206084Srdivacky 3135198398Srdivacky if (Kind == InvalidFormat) { 3136193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) 3137263508Sdim << "format" << II->getName(); 3138193326Sed return; 3139193326Sed } 3140193326Sed 3141193326Sed // checks for the 2nd argument 3142263508Sdim Expr *IdxExpr = Attr.getArgAsExpr(1); 3143193326Sed llvm::APSInt Idx(32); 3144208600Srdivacky if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || 3145208600Srdivacky !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { 3146263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3147263508Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 3148263508Sdim << IdxExpr->getSourceRange(); 3149193326Sed return; 3150193326Sed } 3151193326Sed 3152193326Sed if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { 3153193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 3154193326Sed << "format" << 2 << IdxExpr->getSourceRange(); 3155193326Sed return; 3156193326Sed } 3157193326Sed 3158193326Sed // FIXME: Do we need to bounds check? 3159193326Sed unsigned ArgIdx = Idx.getZExtValue() - 1; 3160198092Srdivacky 3161199482Srdivacky if (HasImplicitThisParam) { 3162199482Srdivacky if (ArgIdx == 0) { 3163218893Sdim S.Diag(Attr.getLoc(), 3164218893Sdim diag::err_format_attribute_implicit_this_format_string) 3165218893Sdim << IdxExpr->getSourceRange(); 3166199482Srdivacky return; 3167199482Srdivacky } 3168199482Srdivacky ArgIdx--; 3169199482Srdivacky } 3170198092Srdivacky 3171193326Sed // make sure the format string is really a string 3172224145Sdim QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); 3173193326Sed 3174198398Srdivacky if (Kind == CFStringFormat) { 3175193326Sed if (!isCFStringType(Ty, S.Context)) { 3176193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3177193326Sed << "a CFString" << IdxExpr->getSourceRange(); 3178193326Sed return; 3179193326Sed } 3180198398Srdivacky } else if (Kind == NSStringFormat) { 3181193326Sed // FIXME: do we need to check if the type is NSString*? What are the 3182193326Sed // semantics? 3183193326Sed if (!isNSStringType(Ty, S.Context)) { 3184193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 3185193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3186193326Sed << "an NSString" << IdxExpr->getSourceRange(); 3187193326Sed return; 3188198092Srdivacky } 3189193326Sed } else if (!Ty->isPointerType() || 3190198092Srdivacky !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) { 3191193326Sed // FIXME: Should highlight the actual expression that has the wrong type. 3192193326Sed S.Diag(Attr.getLoc(), diag::err_format_attribute_not) 3193193326Sed << "a string type" << IdxExpr->getSourceRange(); 3194193326Sed return; 3195193326Sed } 3196193326Sed 3197193326Sed // check the 3rd argument 3198263508Sdim Expr *FirstArgExpr = Attr.getArgAsExpr(2); 3199193326Sed llvm::APSInt FirstArg(32); 3200208600Srdivacky if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || 3201208600Srdivacky !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { 3202263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 3203263508Sdim << Attr.getName() << 3 << AANT_ArgumentIntegerConstant 3204263508Sdim << FirstArgExpr->getSourceRange(); 3205193326Sed return; 3206193326Sed } 3207193326Sed 3208193326Sed // check if the function is variadic if the 3rd argument non-zero 3209193326Sed if (FirstArg != 0) { 3210224145Sdim if (isFunctionOrMethodVariadic(D)) { 3211193326Sed ++NumArgs; // +1 for ... 3212193326Sed } else { 3213224145Sdim S.Diag(D->getLocation(), diag::err_format_attribute_requires_variadic); 3214193326Sed return; 3215193326Sed } 3216193326Sed } 3217193326Sed 3218193326Sed // strftime requires FirstArg to be 0 because it doesn't read from any 3219193326Sed // variable the input is just the current time + the format string. 3220198398Srdivacky if (Kind == StrftimeFormat) { 3221193326Sed if (FirstArg != 0) { 3222193326Sed S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) 3223193326Sed << FirstArgExpr->getSourceRange(); 3224193326Sed return; 3225193326Sed } 3226193326Sed // if 0 it disables parameter checking (to use with e.g. va_list) 3227193326Sed } else if (FirstArg != 0 && FirstArg != NumArgs) { 3228193326Sed S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) 3229193326Sed << "format" << 3 << FirstArgExpr->getSourceRange(); 3230193326Sed return; 3231193326Sed } 3232193326Sed 3233263508Sdim FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II, 3234212904Sdim Idx.getZExtValue(), 3235249423Sdim FirstArg.getZExtValue(), 3236249423Sdim Attr.getAttributeSpellingListIndex()); 3237239462Sdim if (NewAttr) 3238239462Sdim D->addAttr(NewAttr); 3239193326Sed} 3240193326Sed 3241224145Sdimstatic void handleTransparentUnionAttr(Sema &S, Decl *D, 3242224145Sdim const AttributeList &Attr) { 3243193326Sed // Try to find the underlying union declaration. 3244193326Sed RecordDecl *RD = 0; 3245224145Sdim TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); 3246193326Sed if (TD && TD->getUnderlyingType()->isUnionType()) 3247193326Sed RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); 3248193326Sed else 3249224145Sdim RD = dyn_cast<RecordDecl>(D); 3250193326Sed 3251193326Sed if (!RD || !RD->isUnion()) { 3252193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3253221345Sdim << Attr.getName() << ExpectedUnion; 3254193326Sed return; 3255193326Sed } 3256193326Sed 3257226633Sdim if (!RD->isCompleteDefinition()) { 3258198092Srdivacky S.Diag(Attr.getLoc(), 3259193326Sed diag::warn_transparent_union_attribute_not_definition); 3260193326Sed return; 3261193326Sed } 3262193326Sed 3263195341Sed RecordDecl::field_iterator Field = RD->field_begin(), 3264195341Sed FieldEnd = RD->field_end(); 3265193326Sed if (Field == FieldEnd) { 3266193326Sed S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); 3267193326Sed return; 3268193326Sed } 3269193326Sed 3270193326Sed FieldDecl *FirstField = *Field; 3271193326Sed QualType FirstType = FirstField->getType(); 3272210299Sed if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { 3273198092Srdivacky S.Diag(FirstField->getLocation(), 3274210299Sed diag::warn_transparent_union_attribute_floating) 3275210299Sed << FirstType->isVectorType() << FirstType; 3276193326Sed return; 3277193326Sed } 3278193326Sed 3279193326Sed uint64_t FirstSize = S.Context.getTypeSize(FirstType); 3280193326Sed uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); 3281193326Sed for (; Field != FieldEnd; ++Field) { 3282193326Sed QualType FieldType = Field->getType(); 3283193326Sed if (S.Context.getTypeSize(FieldType) != FirstSize || 3284193326Sed S.Context.getTypeAlign(FieldType) != FirstAlign) { 3285193326Sed // Warn if we drop the attribute. 3286193326Sed bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; 3287198092Srdivacky unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) 3288193326Sed : S.Context.getTypeAlign(FieldType); 3289198092Srdivacky S.Diag(Field->getLocation(), 3290193326Sed diag::warn_transparent_union_attribute_field_size_align) 3291193326Sed << isSize << Field->getDeclName() << FieldBits; 3292193326Sed unsigned FirstBits = isSize? FirstSize : FirstAlign; 3293198092Srdivacky S.Diag(FirstField->getLocation(), 3294193326Sed diag::note_transparent_union_first_field_size_align) 3295193326Sed << isSize << FirstBits; 3296193326Sed return; 3297193326Sed } 3298193326Sed } 3299193326Sed 3300249423Sdim RD->addAttr(::new (S.Context) 3301249423Sdim TransparentUnionAttr(Attr.getRange(), S.Context, 3302249423Sdim Attr.getAttributeSpellingListIndex())); 3303193326Sed} 3304193326Sed 3305224145Sdimstatic void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3306193326Sed // Make sure that there is a string literal as the annotation's single 3307193326Sed // argument. 3308263508Sdim StringRef Str; 3309263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str)) 3310193326Sed return; 3311226633Sdim 3312226633Sdim // Don't duplicate annotations that are already set. 3313226633Sdim for (specific_attr_iterator<AnnotateAttr> 3314226633Sdim i = D->specific_attr_begin<AnnotateAttr>(), 3315226633Sdim e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) { 3316263508Sdim if ((*i)->getAnnotation() == Str) 3317263508Sdim return; 3318226633Sdim } 3319249423Sdim 3320249423Sdim D->addAttr(::new (S.Context) 3321263508Sdim AnnotateAttr(Attr.getRange(), S.Context, Str, 3322249423Sdim Attr.getAttributeSpellingListIndex())); 3323193326Sed} 3324193326Sed 3325224145Sdimstatic void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3326193326Sed // check the attribute arguments. 3327193326Sed if (Attr.getNumArgs() > 1) { 3328263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 3329263508Sdim << Attr.getName() << 1; 3330193326Sed return; 3331193326Sed } 3332239462Sdim 3333193326Sed if (Attr.getNumArgs() == 0) { 3334249423Sdim D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, 3335249423Sdim true, 0, Attr.getAttributeSpellingListIndex())); 3336193326Sed return; 3337193326Sed } 3338198092Srdivacky 3339263508Sdim Expr *E = Attr.getArgAsExpr(0); 3340249423Sdim if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { 3341249423Sdim S.Diag(Attr.getEllipsisLoc(), 3342249423Sdim diag::err_pack_expansion_without_parameter_packs); 3343249423Sdim return; 3344249423Sdim } 3345210299Sed 3346249423Sdim if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) 3347234353Sdim return; 3348234353Sdim 3349249423Sdim S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), 3350249423Sdim Attr.isPackExpansion()); 3351249423Sdim} 3352249423Sdim 3353249423Sdimvoid Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, 3354249423Sdim unsigned SpellingListIndex, bool IsPackExpansion) { 3355249423Sdim AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); 3356249423Sdim SourceLocation AttrLoc = AttrRange.getBegin(); 3357249423Sdim 3358249423Sdim // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. 3359249423Sdim if (TmpAttr.isAlignas()) { 3360249423Sdim // C++11 [dcl.align]p1: 3361249423Sdim // An alignment-specifier may be applied to a variable or to a class 3362249423Sdim // data member, but it shall not be applied to a bit-field, a function 3363249423Sdim // parameter, the formal parameter of a catch clause, or a variable 3364249423Sdim // declared with the register storage class specifier. An 3365249423Sdim // alignment-specifier may also be applied to the declaration of a class 3366249423Sdim // or enumeration type. 3367249423Sdim // C11 6.7.5/2: 3368249423Sdim // An alignment attribute shall not be specified in a declaration of 3369249423Sdim // a typedef, or a bit-field, or a function, or a parameter, or an 3370249423Sdim // object declared with the register storage-class specifier. 3371249423Sdim int DiagKind = -1; 3372249423Sdim if (isa<ParmVarDecl>(D)) { 3373249423Sdim DiagKind = 0; 3374249423Sdim } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { 3375249423Sdim if (VD->getStorageClass() == SC_Register) 3376249423Sdim DiagKind = 1; 3377249423Sdim if (VD->isExceptionVariable()) 3378249423Sdim DiagKind = 2; 3379249423Sdim } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { 3380249423Sdim if (FD->isBitField()) 3381249423Sdim DiagKind = 3; 3382249423Sdim } else if (!isa<TagDecl>(D)) { 3383249423Sdim Diag(AttrLoc, diag::err_attribute_wrong_decl_type) 3384249423Sdim << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'") 3385249423Sdim << (TmpAttr.isC11() ? ExpectedVariableOrField 3386249423Sdim : ExpectedVariableFieldOrTag); 3387249423Sdim return; 3388249423Sdim } 3389249423Sdim if (DiagKind != -1) { 3390249423Sdim Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) 3391249423Sdim << TmpAttr.isC11() << DiagKind; 3392249423Sdim return; 3393249423Sdim } 3394249423Sdim } 3395249423Sdim 3396210299Sed if (E->isTypeDependent() || E->isValueDependent()) { 3397210299Sed // Save dependent expressions in the AST to be instantiated. 3398249423Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); 3399249423Sdim AA->setPackExpansion(IsPackExpansion); 3400249423Sdim D->addAttr(AA); 3401210299Sed return; 3402210299Sed } 3403249423Sdim 3404212904Sdim // FIXME: Cache the number on the Attr object? 3405193326Sed llvm::APSInt Alignment(32); 3406239462Sdim ExprResult ICE 3407239462Sdim = VerifyIntegerConstantExpression(E, &Alignment, 3408239462Sdim diag::err_aligned_attribute_argument_not_int, 3409239462Sdim /*AllowFold*/ false); 3410234353Sdim if (ICE.isInvalid()) 3411193326Sed return; 3412249423Sdim 3413249423Sdim // C++11 [dcl.align]p2: 3414249423Sdim // -- if the constant expression evaluates to zero, the alignment 3415249423Sdim // specifier shall have no effect 3416249423Sdim // C11 6.7.5p6: 3417249423Sdim // An alignment specification of zero has no effect. 3418249423Sdim if (!(TmpAttr.isAlignas() && !Alignment) && 3419249423Sdim !llvm::isPowerOf2_64(Alignment.getZExtValue())) { 3420210299Sed Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) 3421210299Sed << E->getSourceRange(); 3422193326Sed return; 3423193326Sed } 3424249423Sdim 3425249423Sdim if (TmpAttr.isDeclspec()) { 3426239462Sdim // We've already verified it's a power of 2, now let's make sure it's 3427239462Sdim // 8192 or less. 3428239462Sdim if (Alignment.getZExtValue() > 8192) { 3429249423Sdim Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) 3430239462Sdim << E->getSourceRange(); 3431239462Sdim return; 3432239462Sdim } 3433239462Sdim } 3434193326Sed 3435249423Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, 3436249423Sdim ICE.take(), SpellingListIndex); 3437249423Sdim AA->setPackExpansion(IsPackExpansion); 3438249423Sdim D->addAttr(AA); 3439193326Sed} 3440193326Sed 3441249423Sdimvoid Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, 3442249423Sdim unsigned SpellingListIndex, bool IsPackExpansion) { 3443212904Sdim // FIXME: Cache the number on the Attr object if non-dependent? 3444212904Sdim // FIXME: Perform checking of type validity 3445249423Sdim AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, 3446249423Sdim SpellingListIndex); 3447249423Sdim AA->setPackExpansion(IsPackExpansion); 3448249423Sdim D->addAttr(AA); 3449212904Sdim} 3450212904Sdim 3451249423Sdimvoid Sema::CheckAlignasUnderalignment(Decl *D) { 3452249423Sdim assert(D->hasAttrs() && "no attributes on decl"); 3453249423Sdim 3454249423Sdim QualType Ty; 3455249423Sdim if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 3456249423Sdim Ty = VD->getType(); 3457249423Sdim else 3458249423Sdim Ty = Context.getTagDeclType(cast<TagDecl>(D)); 3459249423Sdim if (Ty->isDependentType() || Ty->isIncompleteType()) 3460249423Sdim return; 3461249423Sdim 3462249423Sdim // C++11 [dcl.align]p5, C11 6.7.5/4: 3463249423Sdim // The combined effect of all alignment attributes in a declaration shall 3464249423Sdim // not specify an alignment that is less strict than the alignment that 3465249423Sdim // would otherwise be required for the entity being declared. 3466249423Sdim AlignedAttr *AlignasAttr = 0; 3467249423Sdim unsigned Align = 0; 3468249423Sdim for (specific_attr_iterator<AlignedAttr> 3469249423Sdim I = D->specific_attr_begin<AlignedAttr>(), 3470249423Sdim E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) { 3471249423Sdim if (I->isAlignmentDependent()) 3472249423Sdim return; 3473249423Sdim if (I->isAlignas()) 3474249423Sdim AlignasAttr = *I; 3475249423Sdim Align = std::max(Align, I->getAlignment(Context)); 3476249423Sdim } 3477249423Sdim 3478249423Sdim if (AlignasAttr && Align) { 3479249423Sdim CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); 3480249423Sdim CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); 3481249423Sdim if (NaturalAlign > RequestedAlign) 3482249423Sdim Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) 3483249423Sdim << Ty << (unsigned)NaturalAlign.getQuantity(); 3484249423Sdim } 3485249423Sdim} 3486249423Sdim 3487224145Sdim/// handleModeAttr - This attribute modifies the width of a decl with primitive 3488198092Srdivacky/// type. 3489193326Sed/// 3490198092Srdivacky/// Despite what would be logical, the mode attribute is a decl attribute, not a 3491198092Srdivacky/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be 3492198092Srdivacky/// HImode, not an intermediate pointer. 3493224145Sdimstatic void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3494193326Sed // This attribute isn't documented, but glibc uses it. It changes 3495193326Sed // the width of an int or unsigned int to the specified size. 3496263508Sdim if (!Attr.isArgIdent(0)) { 3497263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() 3498263508Sdim << AANT_ArgumentIdentifier; 3499193326Sed return; 3500193326Sed } 3501263508Sdim 3502263508Sdim IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; 3503263508Sdim StringRef Str = Name->getName(); 3504193326Sed 3505193326Sed // Normalize the attribute name, __foo__ becomes foo. 3506198398Srdivacky if (Str.startswith("__") && Str.endswith("__")) 3507198398Srdivacky Str = Str.substr(2, Str.size() - 4); 3508193326Sed 3509193326Sed unsigned DestWidth = 0; 3510193326Sed bool IntegerMode = true; 3511193326Sed bool ComplexMode = false; 3512198398Srdivacky switch (Str.size()) { 3513193326Sed case 2: 3514193326Sed switch (Str[0]) { 3515193326Sed case 'Q': DestWidth = 8; break; 3516193326Sed case 'H': DestWidth = 16; break; 3517193326Sed case 'S': DestWidth = 32; break; 3518193326Sed case 'D': DestWidth = 64; break; 3519193326Sed case 'X': DestWidth = 96; break; 3520193326Sed case 'T': DestWidth = 128; break; 3521193326Sed } 3522193326Sed if (Str[1] == 'F') { 3523193326Sed IntegerMode = false; 3524193326Sed } else if (Str[1] == 'C') { 3525193326Sed IntegerMode = false; 3526193326Sed ComplexMode = true; 3527193326Sed } else if (Str[1] != 'I') { 3528193326Sed DestWidth = 0; 3529193326Sed } 3530193326Sed break; 3531193326Sed case 4: 3532193326Sed // FIXME: glibc uses 'word' to define register_t; this is narrower than a 3533193326Sed // pointer on PIC16 and other embedded platforms. 3534198398Srdivacky if (Str == "word") 3535226633Sdim DestWidth = S.Context.getTargetInfo().getPointerWidth(0); 3536198398Srdivacky else if (Str == "byte") 3537226633Sdim DestWidth = S.Context.getTargetInfo().getCharWidth(); 3538193326Sed break; 3539193326Sed case 7: 3540198398Srdivacky if (Str == "pointer") 3541226633Sdim DestWidth = S.Context.getTargetInfo().getPointerWidth(0); 3542193326Sed break; 3543249423Sdim case 11: 3544249423Sdim if (Str == "unwind_word") 3545249423Sdim DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); 3546249423Sdim break; 3547193326Sed } 3548193326Sed 3549193326Sed QualType OldTy; 3550221345Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) 3551193326Sed OldTy = TD->getUnderlyingType(); 3552193326Sed else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) 3553193326Sed OldTy = VD->getType(); 3554193326Sed else { 3555193326Sed S.Diag(D->getLocation(), diag::err_attr_wrong_decl) 3556226633Sdim << "mode" << Attr.getRange(); 3557193326Sed return; 3558193326Sed } 3559193326Sed 3560198092Srdivacky if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) 3561193326Sed S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); 3562193326Sed else if (IntegerMode) { 3563210299Sed if (!OldTy->isIntegralOrEnumerationType()) 3564193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3565193326Sed } else if (ComplexMode) { 3566193326Sed if (!OldTy->isComplexType()) 3567193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3568193326Sed } else { 3569193326Sed if (!OldTy->isFloatingType()) 3570193326Sed S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); 3571193326Sed } 3572193326Sed 3573193326Sed // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t 3574193326Sed // and friends, at least with glibc. 3575193326Sed // FIXME: Make sure floating-point mappings are accurate 3576193326Sed // FIXME: Support XF and TF types 3577263508Sdim if (!DestWidth) { 3578193326Sed S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; 3579193326Sed return; 3580263508Sdim } 3581263508Sdim 3582263508Sdim QualType NewTy; 3583263508Sdim 3584263508Sdim if (IntegerMode) 3585263508Sdim NewTy = S.Context.getIntTypeForBitwidth(DestWidth, 3586263508Sdim OldTy->isSignedIntegerType()); 3587263508Sdim else 3588263508Sdim NewTy = S.Context.getRealTypeForBitwidth(DestWidth); 3589263508Sdim 3590263508Sdim if (NewTy.isNull()) { 3591193326Sed S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; 3592193326Sed return; 3593193326Sed } 3594193326Sed 3595193326Sed if (ComplexMode) { 3596193326Sed NewTy = S.Context.getComplexType(NewTy); 3597193326Sed } 3598193326Sed 3599193326Sed // Install the new type. 3600263508Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) 3601263508Sdim TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); 3602263508Sdim else 3603193326Sed cast<ValueDecl>(D)->setType(NewTy); 3604263508Sdim 3605263508Sdim D->addAttr(::new (S.Context) 3606263508Sdim ModeAttr(Attr.getRange(), S.Context, Name, 3607263508Sdim Attr.getAttributeSpellingListIndex())); 3608193326Sed} 3609193326Sed 3610224145Sdimstatic void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3611239462Sdim if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { 3612239462Sdim if (!VD->hasGlobalStorage()) 3613239462Sdim S.Diag(Attr.getLoc(), 3614239462Sdim diag::warn_attribute_requires_functions_or_static_globals) 3615239462Sdim << Attr.getName(); 3616239462Sdim } else if (!isFunctionOrMethod(D)) { 3617239462Sdim S.Diag(Attr.getLoc(), 3618239462Sdim diag::warn_attribute_requires_functions_or_static_globals) 3619239462Sdim << Attr.getName(); 3620193326Sed return; 3621193326Sed } 3622198092Srdivacky 3623249423Sdim D->addAttr(::new (S.Context) 3624249423Sdim NoDebugAttr(Attr.getRange(), S.Context, 3625249423Sdim Attr.getAttributeSpellingListIndex())); 3626193326Sed} 3627193326Sed 3628224145Sdimstatic void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3629224145Sdim if (!isa<FunctionDecl>(D)) { 3630193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3631221345Sdim << Attr.getName() << ExpectedFunction; 3632193326Sed return; 3633193326Sed } 3634198092Srdivacky 3635249423Sdim D->addAttr(::new (S.Context) 3636249423Sdim NoInlineAttr(Attr.getRange(), S.Context, 3637249423Sdim Attr.getAttributeSpellingListIndex())); 3638193326Sed} 3639193326Sed 3640224145Sdimstatic void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, 3641224145Sdim const AttributeList &Attr) { 3642224145Sdim if (!isa<FunctionDecl>(D)) { 3643210299Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3644221345Sdim << Attr.getName() << ExpectedFunction; 3645210299Sed return; 3646210299Sed } 3647210299Sed 3648249423Sdim D->addAttr(::new (S.Context) 3649249423Sdim NoInstrumentFunctionAttr(Attr.getRange(), S.Context, 3650249423Sdim Attr.getAttributeSpellingListIndex())); 3651210299Sed} 3652210299Sed 3653224145Sdimstatic void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3654218893Sdim if (S.LangOpts.CUDA) { 3655224145Sdim if (!isa<VarDecl>(D)) { 3656218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3657221345Sdim << Attr.getName() << ExpectedVariable; 3658218893Sdim return; 3659218893Sdim } 3660218893Sdim 3661249423Sdim D->addAttr(::new (S.Context) 3662249423Sdim CUDAConstantAttr(Attr.getRange(), S.Context, 3663249423Sdim Attr.getAttributeSpellingListIndex())); 3664218893Sdim } else { 3665218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; 3666218893Sdim } 3667218893Sdim} 3668218893Sdim 3669224145Sdimstatic void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3670218893Sdim if (S.LangOpts.CUDA) { 3671218893Sdim // check the attribute arguments. 3672218893Sdim if (Attr.getNumArgs() != 0) { 3673263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) 3674263508Sdim << Attr.getName() << 0; 3675218893Sdim return; 3676218893Sdim } 3677218893Sdim 3678224145Sdim if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) { 3679218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3680221345Sdim << Attr.getName() << ExpectedVariableOrFunction; 3681218893Sdim return; 3682218893Sdim } 3683218893Sdim 3684249423Sdim D->addAttr(::new (S.Context) 3685249423Sdim CUDADeviceAttr(Attr.getRange(), S.Context, 3686249423Sdim Attr.getAttributeSpellingListIndex())); 3687218893Sdim } else { 3688218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; 3689218893Sdim } 3690218893Sdim} 3691218893Sdim 3692224145Sdimstatic void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3693218893Sdim if (S.LangOpts.CUDA) { 3694224145Sdim if (!isa<FunctionDecl>(D)) { 3695218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3696221345Sdim << Attr.getName() << ExpectedFunction; 3697218893Sdim return; 3698218893Sdim } 3699218893Sdim 3700224145Sdim FunctionDecl *FD = cast<FunctionDecl>(D); 3701218893Sdim if (!FD->getResultType()->isVoidType()) { 3702218893Sdim TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); 3703249423Sdim if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { 3704218893Sdim S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) 3705218893Sdim << FD->getType() 3706249423Sdim << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(), 3707218893Sdim "void"); 3708218893Sdim } else { 3709218893Sdim S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) 3710218893Sdim << FD->getType(); 3711218893Sdim } 3712218893Sdim return; 3713218893Sdim } 3714218893Sdim 3715249423Sdim D->addAttr(::new (S.Context) 3716249423Sdim CUDAGlobalAttr(Attr.getRange(), S.Context, 3717249423Sdim Attr.getAttributeSpellingListIndex())); 3718218893Sdim } else { 3719218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; 3720218893Sdim } 3721218893Sdim} 3722218893Sdim 3723224145Sdimstatic void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3724218893Sdim if (S.LangOpts.CUDA) { 3725224145Sdim if (!isa<FunctionDecl>(D)) { 3726218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3727221345Sdim << Attr.getName() << ExpectedFunction; 3728218893Sdim return; 3729218893Sdim } 3730218893Sdim 3731249423Sdim D->addAttr(::new (S.Context) 3732249423Sdim CUDAHostAttr(Attr.getRange(), S.Context, 3733249423Sdim Attr.getAttributeSpellingListIndex())); 3734218893Sdim } else { 3735218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; 3736218893Sdim } 3737218893Sdim} 3738218893Sdim 3739224145Sdimstatic void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3740218893Sdim if (S.LangOpts.CUDA) { 3741224145Sdim if (!isa<VarDecl>(D)) { 3742218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3743221345Sdim << Attr.getName() << ExpectedVariable; 3744218893Sdim return; 3745218893Sdim } 3746218893Sdim 3747249423Sdim D->addAttr(::new (S.Context) 3748249423Sdim CUDASharedAttr(Attr.getRange(), S.Context, 3749249423Sdim Attr.getAttributeSpellingListIndex())); 3750218893Sdim } else { 3751218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; 3752218893Sdim } 3753218893Sdim} 3754218893Sdim 3755224145Sdimstatic void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3756224145Sdim FunctionDecl *Fn = dyn_cast<FunctionDecl>(D); 3757193326Sed if (Fn == 0) { 3758193326Sed S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3759221345Sdim << Attr.getName() << ExpectedFunction; 3760193326Sed return; 3761193326Sed } 3762198092Srdivacky 3763198893Srdivacky if (!Fn->isInlineSpecified()) { 3764193326Sed S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); 3765193326Sed return; 3766193326Sed } 3767198092Srdivacky 3768249423Sdim D->addAttr(::new (S.Context) 3769249423Sdim GNUInlineAttr(Attr.getRange(), S.Context, 3770249423Sdim Attr.getAttributeSpellingListIndex())); 3771193326Sed} 3772193326Sed 3773224145Sdimstatic void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3774224145Sdim if (hasDeclarator(D)) return; 3775218893Sdim 3776249423Sdim const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); 3777224145Sdim // Diagnostic is emitted elsewhere: here we store the (valid) Attr 3778207619Srdivacky // in the Decl node for syntactic reasoning, e.g., pretty-printing. 3779218893Sdim CallingConv CC; 3780249423Sdim if (S.CheckCallingConvAttr(Attr, CC, FD)) 3781218893Sdim return; 3782207619Srdivacky 3783224145Sdim if (!isa<ObjCMethodDecl>(D)) { 3784224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3785224145Sdim << Attr.getName() << ExpectedFunctionOrMethod; 3786218893Sdim return; 3787218893Sdim } 3788218893Sdim 3789224145Sdim switch (Attr.getKind()) { 3790239462Sdim case AttributeList::AT_FastCall: 3791249423Sdim D->addAttr(::new (S.Context) 3792249423Sdim FastCallAttr(Attr.getRange(), S.Context, 3793249423Sdim Attr.getAttributeSpellingListIndex())); 3794207619Srdivacky return; 3795239462Sdim case AttributeList::AT_StdCall: 3796249423Sdim D->addAttr(::new (S.Context) 3797249423Sdim StdCallAttr(Attr.getRange(), S.Context, 3798249423Sdim Attr.getAttributeSpellingListIndex())); 3799207619Srdivacky return; 3800239462Sdim case AttributeList::AT_ThisCall: 3801249423Sdim D->addAttr(::new (S.Context) 3802249423Sdim ThisCallAttr(Attr.getRange(), S.Context, 3803249423Sdim Attr.getAttributeSpellingListIndex())); 3804212904Sdim return; 3805239462Sdim case AttributeList::AT_CDecl: 3806249423Sdim D->addAttr(::new (S.Context) 3807249423Sdim CDeclAttr(Attr.getRange(), S.Context, 3808249423Sdim Attr.getAttributeSpellingListIndex())); 3809207619Srdivacky return; 3810239462Sdim case AttributeList::AT_Pascal: 3811249423Sdim D->addAttr(::new (S.Context) 3812249423Sdim PascalAttr(Attr.getRange(), S.Context, 3813249423Sdim Attr.getAttributeSpellingListIndex())); 3814212904Sdim return; 3815256030Sdim case AttributeList::AT_MSABI: 3816256030Sdim D->addAttr(::new (S.Context) 3817256030Sdim MSABIAttr(Attr.getRange(), S.Context, 3818256030Sdim Attr.getAttributeSpellingListIndex())); 3819256030Sdim return; 3820256030Sdim case AttributeList::AT_SysVABI: 3821256030Sdim D->addAttr(::new (S.Context) 3822256030Sdim SysVABIAttr(Attr.getRange(), S.Context, 3823256030Sdim Attr.getAttributeSpellingListIndex())); 3824256030Sdim return; 3825239462Sdim case AttributeList::AT_Pcs: { 3826221345Sdim PcsAttr::PCSType PCS; 3827239462Sdim switch (CC) { 3828239462Sdim case CC_AAPCS: 3829221345Sdim PCS = PcsAttr::AAPCS; 3830239462Sdim break; 3831239462Sdim case CC_AAPCS_VFP: 3832221345Sdim PCS = PcsAttr::AAPCS_VFP; 3833239462Sdim break; 3834239462Sdim default: 3835239462Sdim llvm_unreachable("unexpected calling convention in pcs attribute"); 3836221345Sdim } 3837221345Sdim 3838249423Sdim D->addAttr(::new (S.Context) 3839249423Sdim PcsAttr(Attr.getRange(), S.Context, PCS, 3840249423Sdim Attr.getAttributeSpellingListIndex())); 3841243830Sdim return; 3842221345Sdim } 3843243830Sdim case AttributeList::AT_PnaclCall: 3844249423Sdim D->addAttr(::new (S.Context) 3845249423Sdim PnaclCallAttr(Attr.getRange(), S.Context, 3846249423Sdim Attr.getAttributeSpellingListIndex())); 3847243830Sdim return; 3848249423Sdim case AttributeList::AT_IntelOclBicc: 3849249423Sdim D->addAttr(::new (S.Context) 3850249423Sdim IntelOclBiccAttr(Attr.getRange(), S.Context, 3851249423Sdim Attr.getAttributeSpellingListIndex())); 3852249423Sdim return; 3853243830Sdim 3854207619Srdivacky default: 3855207619Srdivacky llvm_unreachable("unexpected attribute kind"); 3856207619Srdivacky } 3857207619Srdivacky} 3858207619Srdivacky 3859224145Sdimstatic void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ 3860226633Sdim D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); 3861218893Sdim} 3862218893Sdim 3863249423Sdimstatic void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ 3864263508Sdim Expr *E = Attr.getArgAsExpr(0); 3865249423Sdim llvm::APSInt ArgNum(32); 3866249423Sdim if (E->isTypeDependent() || E->isValueDependent() || 3867249423Sdim !E->isIntegerConstantExpr(ArgNum, S.Context)) { 3868263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3869263508Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3870263508Sdim << E->getSourceRange(); 3871249423Sdim return; 3872249423Sdim } 3873249423Sdim 3874249423Sdim D->addAttr(::new (S.Context) OpenCLImageAccessAttr( 3875249423Sdim Attr.getRange(), S.Context, ArgNum.getZExtValue())); 3876249423Sdim} 3877249423Sdim 3878249423Sdimbool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 3879249423Sdim const FunctionDecl *FD) { 3880218893Sdim if (attr.isInvalid()) 3881218893Sdim return true; 3882218893Sdim 3883239462Sdim unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; 3884263508Sdim if (!checkAttributeNumArgs(*this, attr, ReqArgs)) { 3885218893Sdim attr.setInvalid(); 3886218893Sdim return true; 3887193326Sed } 3888193326Sed 3889221345Sdim // TODO: diagnose uses of these conventions on the wrong target. Or, better 3890221345Sdim // move to TargetAttributesSema one day. 3891218893Sdim switch (attr.getKind()) { 3892239462Sdim case AttributeList::AT_CDecl: CC = CC_C; break; 3893239462Sdim case AttributeList::AT_FastCall: CC = CC_X86FastCall; break; 3894239462Sdim case AttributeList::AT_StdCall: CC = CC_X86StdCall; break; 3895239462Sdim case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break; 3896239462Sdim case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; 3897256030Sdim case AttributeList::AT_MSABI: 3898256030Sdim CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : 3899256030Sdim CC_X86_64Win64; 3900256030Sdim break; 3901256030Sdim case AttributeList::AT_SysVABI: 3902256030Sdim CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : 3903256030Sdim CC_C; 3904256030Sdim break; 3905239462Sdim case AttributeList::AT_Pcs: { 3906263508Sdim StringRef StrRef; 3907263508Sdim if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) { 3908221345Sdim attr.setInvalid(); 3909221345Sdim return true; 3910221345Sdim } 3911221345Sdim if (StrRef == "aapcs") { 3912221345Sdim CC = CC_AAPCS; 3913221345Sdim break; 3914221345Sdim } else if (StrRef == "aapcs-vfp") { 3915221345Sdim CC = CC_AAPCS_VFP; 3916221345Sdim break; 3917221345Sdim } 3918239462Sdim 3919239462Sdim attr.setInvalid(); 3920239462Sdim Diag(attr.getLoc(), diag::err_invalid_pcs); 3921239462Sdim return true; 3922221345Sdim } 3923243830Sdim case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; 3924249423Sdim case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; 3925234353Sdim default: llvm_unreachable("unexpected attribute kind"); 3926218893Sdim } 3927218893Sdim 3928243830Sdim const TargetInfo &TI = Context.getTargetInfo(); 3929243830Sdim TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); 3930243830Sdim if (A == TargetInfo::CCCR_Warning) { 3931243830Sdim Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); 3932249423Sdim 3933249423Sdim TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; 3934249423Sdim if (FD) 3935249423Sdim MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : 3936249423Sdim TargetInfo::CCMT_NonMember; 3937249423Sdim CC = TI.getDefaultCallingConv(MT); 3938243830Sdim } 3939243830Sdim 3940218893Sdim return false; 3941218893Sdim} 3942218893Sdim 3943224145Sdimstatic void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { 3944224145Sdim if (hasDeclarator(D)) return; 3945218893Sdim 3946218893Sdim unsigned numParams; 3947224145Sdim if (S.CheckRegparmAttr(Attr, numParams)) 3948193326Sed return; 3949218893Sdim 3950224145Sdim if (!isa<ObjCMethodDecl>(D)) { 3951224145Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 3952224145Sdim << Attr.getName() << ExpectedFunctionOrMethod; 3953218893Sdim return; 3954193326Sed } 3955193326Sed 3956249423Sdim D->addAttr(::new (S.Context) 3957249423Sdim RegparmAttr(Attr.getRange(), S.Context, numParams, 3958249423Sdim Attr.getAttributeSpellingListIndex())); 3959218893Sdim} 3960218893Sdim 3961218893Sdim/// Checks a regparm attribute, returning true if it is ill-formed and 3962218893Sdim/// otherwise setting numParams to the appropriate value. 3963224145Sdimbool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) { 3964224145Sdim if (Attr.isInvalid()) 3965218893Sdim return true; 3966218893Sdim 3967263508Sdim if (!checkAttributeNumArgs(*this, Attr, 1)) { 3968224145Sdim Attr.setInvalid(); 3969218893Sdim return true; 3970218893Sdim } 3971218893Sdim 3972263508Sdim Expr *NumParamsExpr = Attr.getArgAsExpr(0); 3973193326Sed llvm::APSInt NumParams(32); 3974208600Srdivacky if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || 3975218893Sdim !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { 3976263508Sdim Diag(Attr.getLoc(), diag::err_attribute_argument_type) 3977263508Sdim << Attr.getName() << AANT_ArgumentIntegerConstant 3978263508Sdim << NumParamsExpr->getSourceRange(); 3979224145Sdim Attr.setInvalid(); 3980218893Sdim return true; 3981193326Sed } 3982193326Sed 3983226633Sdim if (Context.getTargetInfo().getRegParmMax() == 0) { 3984224145Sdim Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform) 3985193326Sed << NumParamsExpr->getSourceRange(); 3986224145Sdim Attr.setInvalid(); 3987218893Sdim return true; 3988193326Sed } 3989193326Sed 3990218893Sdim numParams = NumParams.getZExtValue(); 3991226633Sdim if (numParams > Context.getTargetInfo().getRegParmMax()) { 3992224145Sdim Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number) 3993226633Sdim << Context.getTargetInfo().getRegParmMax() << NumParamsExpr->getSourceRange(); 3994224145Sdim Attr.setInvalid(); 3995218893Sdim return true; 3996193326Sed } 3997193326Sed 3998218893Sdim return false; 3999193326Sed} 4000193326Sed 4001224145Sdimstatic void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ 4002218893Sdim if (S.LangOpts.CUDA) { 4003218893Sdim // check the attribute arguments. 4004218893Sdim if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { 4005221345Sdim // FIXME: 0 is not okay. 4006221345Sdim S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; 4007218893Sdim return; 4008218893Sdim } 4009199990Srdivacky 4010224145Sdim if (!isFunctionOrMethod(D)) { 4011218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) 4012221345Sdim << Attr.getName() << ExpectedFunctionOrMethod; 4013218893Sdim return; 4014218893Sdim } 4015218893Sdim 4016263508Sdim Expr *MaxThreadsExpr = Attr.getArgAsExpr(0); 4017218893Sdim llvm::APSInt MaxThreads(32); 4018218893Sdim if (MaxThreadsExpr->isTypeDependent() || 4019218893Sdim MaxThreadsExpr->isValueDependent() || 4020218893Sdim !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { 4021263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4022263508Sdim << Attr.getName() << 1 << AANT_ArgumentIntegerConstant 4023263508Sdim << MaxThreadsExpr->getSourceRange(); 4024218893Sdim return; 4025218893Sdim } 4026218893Sdim 4027218893Sdim llvm::APSInt MinBlocks(32); 4028218893Sdim if (Attr.getNumArgs() > 1) { 4029263508Sdim Expr *MinBlocksExpr = Attr.getArgAsExpr(1); 4030218893Sdim if (MinBlocksExpr->isTypeDependent() || 4031218893Sdim MinBlocksExpr->isValueDependent() || 4032218893Sdim !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { 4033263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4034263508Sdim << Attr.getName() << 2 << AANT_ArgumentIntegerConstant 4035263508Sdim << MinBlocksExpr->getSourceRange(); 4036218893Sdim return; 4037218893Sdim } 4038218893Sdim } 4039218893Sdim 4040249423Sdim D->addAttr(::new (S.Context) 4041249423Sdim CUDALaunchBoundsAttr(Attr.getRange(), S.Context, 4042249423Sdim MaxThreads.getZExtValue(), 4043249423Sdim MinBlocks.getZExtValue(), 4044249423Sdim Attr.getAttributeSpellingListIndex())); 4045218893Sdim } else { 4046218893Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; 4047199990Srdivacky } 4048199990Srdivacky} 4049199990Srdivacky 4050239462Sdimstatic void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, 4051239462Sdim const AttributeList &Attr) { 4052263508Sdim if (!Attr.isArgIdent(0)) { 4053263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4054263508Sdim << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier; 4055239462Sdim return; 4056239462Sdim } 4057263508Sdim 4058263508Sdim if (!checkAttributeNumArgs(S, Attr, 3)) 4059239462Sdim return; 4060239462Sdim 4061263508Sdim StringRef AttrName = Attr.getName()->getName(); 4062263508Sdim IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident; 4063239462Sdim 4064239462Sdim if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) { 4065239462Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 4066239462Sdim << Attr.getName() << ExpectedFunctionOrMethod; 4067239462Sdim return; 4068239462Sdim } 4069239462Sdim 4070239462Sdim uint64_t ArgumentIdx; 4071239462Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, 4072239462Sdim Attr.getLoc(), 2, 4073263508Sdim Attr.getArgAsExpr(1), ArgumentIdx)) 4074239462Sdim return; 4075239462Sdim 4076239462Sdim uint64_t TypeTagIdx; 4077239462Sdim if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName, 4078239462Sdim Attr.getLoc(), 3, 4079263508Sdim Attr.getArgAsExpr(2), TypeTagIdx)) 4080239462Sdim return; 4081239462Sdim 4082239462Sdim bool IsPointer = (AttrName == "pointer_with_type_tag"); 4083239462Sdim if (IsPointer) { 4084239462Sdim // Ensure that buffer has a pointer type. 4085239462Sdim QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx); 4086239462Sdim if (!BufferTy->isPointerType()) { 4087239462Sdim S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) 4088263508Sdim << Attr.getName(); 4089239462Sdim } 4090239462Sdim } 4091239462Sdim 4092249423Sdim D->addAttr(::new (S.Context) 4093249423Sdim ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind, 4094249423Sdim ArgumentIdx, TypeTagIdx, IsPointer, 4095249423Sdim Attr.getAttributeSpellingListIndex())); 4096239462Sdim} 4097239462Sdim 4098239462Sdimstatic void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, 4099239462Sdim const AttributeList &Attr) { 4100263508Sdim if (!Attr.isArgIdent(0)) { 4101263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) 4102263508Sdim << Attr.getName() << 1 << AANT_ArgumentIdentifier; 4103239462Sdim return; 4104239462Sdim } 4105263508Sdim 4106263508Sdim if (!checkAttributeNumArgs(S, Attr, 1)) 4107263508Sdim return; 4108239462Sdim 4109263508Sdim IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident; 4110263508Sdim TypeSourceInfo *MatchingCTypeLoc = 0; 4111263508Sdim S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc); 4112263508Sdim assert(MatchingCTypeLoc && "no type source info for attribute argument"); 4113239462Sdim 4114249423Sdim D->addAttr(::new (S.Context) 4115249423Sdim TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, 4116263508Sdim MatchingCTypeLoc, 4117249423Sdim Attr.getLayoutCompatible(), 4118249423Sdim Attr.getMustBeNull(), 4119249423Sdim Attr.getAttributeSpellingListIndex())); 4120239462Sdim} 4121239462Sdim 4122193326Sed//===----------------------------------------------------------------------===// 4123218893Sdim// Checker-specific attribute handlers. 4124199990Srdivacky//===----------------------------------------------------------------------===// 4125199990Srdivacky 4126218893Sdimstatic bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { 4127226633Sdim return type->isDependentType() || 4128226633Sdim type->isObjCObjectPointerType() || 4129226633Sdim S.Context.isObjCNSObjectType(type); 4130199990Srdivacky} 4131218893Sdimstatic bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { 4132226633Sdim return type->isDependentType() || 4133226633Sdim type->isPointerType() || 4134226633Sdim isValidSubjectOfNSAttribute(S, type); 4135218893Sdim} 4136199990Srdivacky 4137224145Sdimstatic void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4138224145Sdim ParmVarDecl *param = dyn_cast<ParmVarDecl>(D); 4139218893Sdim if (!param) { 4140224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4141226633Sdim << Attr.getRange() << Attr.getName() << ExpectedParameter; 4142199990Srdivacky return; 4143199990Srdivacky } 4144199990Srdivacky 4145218893Sdim bool typeOK, cf; 4146239462Sdim if (Attr.getKind() == AttributeList::AT_NSConsumed) { 4147218893Sdim typeOK = isValidSubjectOfNSAttribute(S, param->getType()); 4148218893Sdim cf = false; 4149218893Sdim } else { 4150218893Sdim typeOK = isValidSubjectOfCFAttribute(S, param->getType()); 4151218893Sdim cf = true; 4152199990Srdivacky } 4153199990Srdivacky 4154218893Sdim if (!typeOK) { 4155224145Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) 4156226633Sdim << Attr.getRange() << Attr.getName() << cf; 4157199990Srdivacky return; 4158199990Srdivacky } 4159199990Srdivacky 4160218893Sdim if (cf) 4161249423Sdim param->addAttr(::new (S.Context) 4162249423Sdim CFConsumedAttr(Attr.getRange(), S.Context, 4163249423Sdim Attr.getAttributeSpellingListIndex())); 4164218893Sdim else 4165249423Sdim param->addAttr(::new (S.Context) 4166249423Sdim NSConsumedAttr(Attr.getRange(), S.Context, 4167249423Sdim Attr.getAttributeSpellingListIndex())); 4168199990Srdivacky} 4169199990Srdivacky 4170224145Sdimstatic void handleNSConsumesSelfAttr(Sema &S, Decl *D, 4171224145Sdim const AttributeList &Attr) { 4172224145Sdim if (!isa<ObjCMethodDecl>(D)) { 4173224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4174226633Sdim << Attr.getRange() << Attr.getName() << ExpectedMethod; 4175199990Srdivacky return; 4176199990Srdivacky } 4177199990Srdivacky 4178249423Sdim D->addAttr(::new (S.Context) 4179249423Sdim NSConsumesSelfAttr(Attr.getRange(), S.Context, 4180249423Sdim Attr.getAttributeSpellingListIndex())); 4181199990Srdivacky} 4182199990Srdivacky 4183224145Sdimstatic void handleNSReturnsRetainedAttr(Sema &S, Decl *D, 4184224145Sdim const AttributeList &Attr) { 4185193326Sed 4186218893Sdim QualType returnType; 4187198092Srdivacky 4188224145Sdim if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 4189218893Sdim returnType = MD->getResultType(); 4190234353Sdim else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && 4191239462Sdim (Attr.getKind() == AttributeList::AT_NSReturnsRetained)) 4192224145Sdim return; // ignore: was handled as a type attribute 4193243830Sdim else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) 4194243830Sdim returnType = PD->getType(); 4195224145Sdim else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 4196218893Sdim returnType = FD->getResultType(); 4197193326Sed else { 4198224145Sdim S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type) 4199226633Sdim << Attr.getRange() << Attr.getName() 4200221345Sdim << ExpectedFunctionOrMethod; 4201193326Sed return; 4202193326Sed } 4203198092Srdivacky 4204218893Sdim bool typeOK; 4205218893Sdim bool cf; 4206224145Sdim switch (Attr.getKind()) { 4207234353Sdim default: llvm_unreachable("invalid ownership attribute"); 4208239462Sdim case AttributeList::AT_NSReturnsAutoreleased: 4209239462Sdim case AttributeList::AT_NSReturnsRetained: 4210239462Sdim case AttributeList::AT_NSReturnsNotRetained: 4211218893Sdim typeOK = isValidSubjectOfNSAttribute(S, returnType); 4212218893Sdim cf = false; 4213218893Sdim break; 4214218893Sdim 4215239462Sdim case AttributeList::AT_CFReturnsRetained: 4216239462Sdim case AttributeList::AT_CFReturnsNotRetained: 4217218893Sdim typeOK = isValidSubjectOfCFAttribute(S, returnType); 4218218893Sdim cf = true; 4219218893Sdim break; 4220218893Sdim } 4221218893Sdim 4222218893Sdim if (!typeOK) { 4223224145Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) 4224226633Sdim << Attr.getRange() << Attr.getName() << isa<ObjCMethodDecl>(D) << cf; 4225198092Srdivacky return; 4226193326Sed } 4227198092Srdivacky 4228224145Sdim switch (Attr.getKind()) { 4229193326Sed default: 4230226633Sdim llvm_unreachable("invalid ownership attribute"); 4231239462Sdim case AttributeList::AT_NSReturnsAutoreleased: 4232249423Sdim D->addAttr(::new (S.Context) 4233249423Sdim NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context, 4234249423Sdim Attr.getAttributeSpellingListIndex())); 4235218893Sdim return; 4236239462Sdim case AttributeList::AT_CFReturnsNotRetained: 4237249423Sdim D->addAttr(::new (S.Context) 4238249423Sdim CFReturnsNotRetainedAttr(Attr.getRange(), S.Context, 4239249423Sdim Attr.getAttributeSpellingListIndex())); 4240204643Srdivacky return; 4241239462Sdim case AttributeList::AT_NSReturnsNotRetained: 4242249423Sdim D->addAttr(::new (S.Context) 4243249423Sdim NSReturnsNotRetainedAttr(Attr.getRange(), S.Context, 4244249423Sdim Attr.getAttributeSpellingListIndex())); 4245204643Srdivacky return; 4246239462Sdim case AttributeList::AT_CFReturnsRetained: 4247249423Sdim D->addAttr(::new (S.Context) 4248249423Sdim CFReturnsRetainedAttr(Attr.getRange(), S.Context, 4249249423Sdim Attr.getAttributeSpellingListIndex())); 4250193326Sed return; 4251239462Sdim case AttributeList::AT_NSReturnsRetained: 4252249423Sdim D->addAttr(::new (S.Context) 4253249423Sdim NSReturnsRetainedAttr(Attr.getRange(), S.Context, 4254249423Sdim Attr.getAttributeSpellingListIndex())); 4255193326Sed return; 4256193326Sed }; 4257193326Sed} 4258193326Sed 4259226633Sdimstatic void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, 4260226633Sdim const AttributeList &attr) { 4261263508Sdim const int EP_ObjCMethod = 1; 4262263508Sdim const int EP_ObjCProperty = 2; 4263263508Sdim 4264226633Sdim SourceLocation loc = attr.getLoc(); 4265263508Sdim QualType resultType; 4266263508Sdim 4267226633Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); 4268226633Sdim 4269239462Sdim if (!method) { 4270263508Sdim ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D); 4271263508Sdim if (!property) { 4272263508Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4273263508Sdim << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty; 4274263508Sdim return; 4275263508Sdim } 4276263508Sdim resultType = property->getType(); 4277226633Sdim } 4278263508Sdim else 4279263508Sdim // Check that the method returns a normal pointer. 4280263508Sdim resultType = method->getResultType(); 4281226633Sdim 4282226633Sdim if (!resultType->isReferenceType() && 4283226633Sdim (!resultType->isPointerType() || resultType->isObjCRetainableType())) { 4284263508Sdim S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type) 4285226633Sdim << SourceRange(loc) 4286263508Sdim << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty) 4287263508Sdim << /*non-retainable pointer*/ 2; 4288226633Sdim 4289226633Sdim // Drop the attribute. 4290226633Sdim return; 4291226633Sdim } 4292226633Sdim 4293263508Sdim D->addAttr(::new (S.Context) 4294249423Sdim ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, 4295249423Sdim attr.getAttributeSpellingListIndex())); 4296226633Sdim} 4297226633Sdim 4298243830Sdimstatic void handleObjCRequiresSuperAttr(Sema &S, Decl *D, 4299243830Sdim const AttributeList &attr) { 4300243830Sdim SourceLocation loc = attr.getLoc(); 4301243830Sdim ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); 4302243830Sdim 4303243830Sdim if (!method) { 4304243830Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4305243830Sdim << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; 4306243830Sdim return; 4307243830Sdim } 4308243830Sdim DeclContext *DC = method->getDeclContext(); 4309243830Sdim if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { 4310243830Sdim S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) 4311243830Sdim << attr.getName() << 0; 4312243830Sdim S.Diag(PDecl->getLocation(), diag::note_protocol_decl); 4313243830Sdim return; 4314243830Sdim } 4315243830Sdim if (method->getMethodFamily() == OMF_dealloc) { 4316243830Sdim S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) 4317243830Sdim << attr.getName() << 1; 4318243830Sdim return; 4319243830Sdim } 4320243830Sdim 4321249423Sdim method->addAttr(::new (S.Context) 4322249423Sdim ObjCRequiresSuperAttr(attr.getRange(), S.Context, 4323249423Sdim attr.getAttributeSpellingListIndex())); 4324243830Sdim} 4325243830Sdim 4326226633Sdim/// Handle cf_audited_transfer and cf_unknown_transfer. 4327226633Sdimstatic void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { 4328226633Sdim if (!isa<FunctionDecl>(D)) { 4329226633Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4330234353Sdim << A.getRange() << A.getName() << ExpectedFunction; 4331226633Sdim return; 4332226633Sdim } 4333226633Sdim 4334239462Sdim bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer); 4335226633Sdim 4336226633Sdim // Check whether there's a conflicting attribute already present. 4337226633Sdim Attr *Existing; 4338226633Sdim if (IsAudited) { 4339226633Sdim Existing = D->getAttr<CFUnknownTransferAttr>(); 4340226633Sdim } else { 4341226633Sdim Existing = D->getAttr<CFAuditedTransferAttr>(); 4342226633Sdim } 4343226633Sdim if (Existing) { 4344226633Sdim S.Diag(D->getLocStart(), diag::err_attributes_are_not_compatible) 4345226633Sdim << A.getName() 4346226633Sdim << (IsAudited ? "cf_unknown_transfer" : "cf_audited_transfer") 4347226633Sdim << A.getRange() << Existing->getRange(); 4348226633Sdim return; 4349226633Sdim } 4350226633Sdim 4351226633Sdim // All clear; add the attribute. 4352226633Sdim if (IsAudited) { 4353249423Sdim D->addAttr(::new (S.Context) 4354249423Sdim CFAuditedTransferAttr(A.getRange(), S.Context, 4355249423Sdim A.getAttributeSpellingListIndex())); 4356226633Sdim } else { 4357249423Sdim D->addAttr(::new (S.Context) 4358249423Sdim CFUnknownTransferAttr(A.getRange(), S.Context, 4359249423Sdim A.getAttributeSpellingListIndex())); 4360226633Sdim } 4361226633Sdim} 4362226633Sdim 4363226633Sdimstatic void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, 4364226633Sdim const AttributeList &Attr) { 4365226633Sdim RecordDecl *RD = dyn_cast<RecordDecl>(D); 4366226633Sdim if (!RD || RD->isUnion()) { 4367226633Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4368234353Sdim << Attr.getRange() << Attr.getName() << ExpectedStruct; 4369226633Sdim } 4370226633Sdim 4371263508Sdim IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; 4372226633Sdim 4373226633Sdim // In Objective-C, verify that the type names an Objective-C type. 4374226633Sdim // We don't want to check this outside of ObjC because people sometimes 4375226633Sdim // do crazy C declarations of Objective-C types. 4376263508Sdim if (Parm && S.getLangOpts().ObjC1) { 4377226633Sdim // Check for an existing type with this name. 4378263508Sdim LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc, 4379226633Sdim Sema::LookupOrdinaryName); 4380226633Sdim if (S.LookupName(R, Sc)) { 4381226633Sdim NamedDecl *Target = R.getFoundDecl(); 4382226633Sdim if (Target && !isa<ObjCInterfaceDecl>(Target)) { 4383226633Sdim S.Diag(D->getLocStart(), diag::err_ns_bridged_not_interface); 4384226633Sdim S.Diag(Target->getLocStart(), diag::note_declared_at); 4385226633Sdim } 4386226633Sdim } 4387226633Sdim } 4388226633Sdim 4389249423Sdim D->addAttr(::new (S.Context) 4390263508Sdim NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, 4391249423Sdim Attr.getAttributeSpellingListIndex())); 4392226633Sdim} 4393226633Sdim 4394263508Sdimstatic void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D, 4395263508Sdim const AttributeList &Attr) { 4396263508Sdim if (!isa<RecordDecl>(D)) { 4397263508Sdim S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) 4398263508Sdim << Attr.getName() 4399263508Sdim << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass 4400263508Sdim : ExpectedStructOrUnion); 4401263508Sdim return; 4402263508Sdim } 4403263508Sdim 4404263508Sdim if (Attr.getNumArgs() != 1) { 4405263508Sdim S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); 4406263508Sdim return; 4407263508Sdim } 4408263508Sdim IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; 4409263508Sdim if (!Parm) { 4410263508Sdim S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); 4411263508Sdim return; 4412263508Sdim } 4413263508Sdim 4414263508Sdim D->addAttr(::new (S.Context) 4415263508Sdim ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, 4416263508Sdim Attr.getAttributeSpellingListIndex())); 4417263508Sdim} 4418263508Sdim 4419224145Sdimstatic void handleObjCOwnershipAttr(Sema &S, Decl *D, 4420224145Sdim const AttributeList &Attr) { 4421224145Sdim if (hasDeclarator(D)) return; 4422224145Sdim 4423224145Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4424234353Sdim << Attr.getRange() << Attr.getName() << ExpectedVariable; 4425224145Sdim} 4426224145Sdim 4427224145Sdimstatic void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, 4428224145Sdim const AttributeList &Attr) { 4429224145Sdim if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) { 4430224145Sdim S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) 4431234353Sdim << Attr.getRange() << Attr.getName() << ExpectedVariable; 4432224145Sdim return; 4433224145Sdim } 4434224145Sdim 4435224145Sdim ValueDecl *vd = cast<ValueDecl>(D); 4436224145Sdim QualType type = vd->getType(); 4437224145Sdim 4438224145Sdim if (!type->isDependentType() && 4439224145Sdim !type->isObjCLifetimeType()) { 4440224145Sdim S.Diag(Attr.getLoc(), diag::err_objc_precise_lifetime_bad_type) 4441224145Sdim << type; 4442224145Sdim return; 4443224145Sdim } 4444224145Sdim 4445224145Sdim Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); 4446224145Sdim 4447224145Sdim // If we have no lifetime yet, check the lifetime we're presumably 4448224145Sdim // going to infer. 4449224145Sdim if (lifetime == Qualifiers::OCL_None && !type->isDependentType()) 4450224145Sdim lifetime = type->getObjCARCImplicitLifetime(); 4451224145Sdim 4452224145Sdim switch (lifetime) { 4453224145Sdim case Qualifiers::OCL_None: 4454224145Sdim assert(type->isDependentType() && 4455224145Sdim "didn't infer lifetime for non-dependent type?"); 4456224145Sdim break; 4457224145Sdim 4458224145Sdim case Qualifiers::OCL_Weak: // meaningful 4459224145Sdim case Qualifiers::OCL_Strong: // meaningful 4460224145Sdim break; 4461224145Sdim 4462224145Sdim case Qualifiers::OCL_ExplicitNone: 4463224145Sdim case Qualifiers::OCL_Autoreleasing: 4464224145Sdim S.Diag(Attr.getLoc(), diag::warn_objc_precise_lifetime_meaningless) 4465224145Sdim << (lifetime == Qualifiers::OCL_Autoreleasing); 4466224145Sdim break; 4467224145Sdim } 4468224145Sdim 4469224145Sdim D->addAttr(::new (S.Context) 4470249423Sdim ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context, 4471249423Sdim Attr.getAttributeSpellingListIndex())); 4472224145Sdim} 4473224145Sdim 4474193326Sed//===----------------------------------------------------------------------===// 4475218893Sdim// Microsoft specific attribute handlers. 4476218893Sdim//===----------------------------------------------------------------------===// 4477218893Sdim 4478263508Sdim// Check if MS extensions or some other language extensions are enabled. If 4479263508Sdim// not, issue a diagnostic that the given attribute is unused. 4480263508Sdimstatic bool checkMicrosoftExt(Sema &S, const AttributeList &Attr, 4481263508Sdim bool OtherExtension = false) { 4482263508Sdim if (S.LangOpts.MicrosoftExt || OtherExtension) 4483263508Sdim return true; 4484263508Sdim S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); 4485263508Sdim return false; 4486263508Sdim} 4487263508Sdim 4488224145Sdimstatic void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4489263508Sdim if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland)) 4490263508Sdim return; 4491224145Sdim 4492263508Sdim StringRef StrRef; 4493263508Sdim SourceLocation LiteralLoc; 4494263508Sdim if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) 4495263508Sdim return; 4496218893Sdim 4497263508Sdim // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or 4498263508Sdim // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. 4499263508Sdim if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') 4500263508Sdim StrRef = StrRef.drop_front().drop_back(); 4501218893Sdim 4502263508Sdim // Validate GUID length. 4503263508Sdim if (StrRef.size() != 36) { 4504263508Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4505263508Sdim return; 4506263508Sdim } 4507234353Sdim 4508263508Sdim for (unsigned i = 0; i < 36; ++i) { 4509263508Sdim if (i == 8 || i == 13 || i == 18 || i == 23) { 4510263508Sdim if (StrRef[i] != '-') { 4511263508Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4512218893Sdim return; 4513218893Sdim } 4514263508Sdim } else if (!isHexDigit(StrRef[i])) { 4515263508Sdim S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); 4516263508Sdim return; 4517218893Sdim } 4518263508Sdim } 4519218893Sdim 4520263508Sdim D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef, 4521263508Sdim Attr.getAttributeSpellingListIndex())); 4522218893Sdim} 4523218893Sdim 4524239462Sdimstatic void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4525263508Sdim if (!checkMicrosoftExt(S, Attr)) 4526243830Sdim return; 4527243830Sdim 4528243830Sdim AttributeList::Kind Kind = Attr.getKind(); 4529243830Sdim if (Kind == AttributeList::AT_SingleInheritance) 4530243830Sdim D->addAttr( 4531249423Sdim ::new (S.Context) 4532249423Sdim SingleInheritanceAttr(Attr.getRange(), S.Context, 4533249423Sdim Attr.getAttributeSpellingListIndex())); 4534243830Sdim else if (Kind == AttributeList::AT_MultipleInheritance) 4535243830Sdim D->addAttr( 4536249423Sdim ::new (S.Context) 4537249423Sdim MultipleInheritanceAttr(Attr.getRange(), S.Context, 4538249423Sdim Attr.getAttributeSpellingListIndex())); 4539243830Sdim else if (Kind == AttributeList::AT_VirtualInheritance) 4540243830Sdim D->addAttr( 4541249423Sdim ::new (S.Context) 4542249423Sdim VirtualInheritanceAttr(Attr.getRange(), S.Context, 4543249423Sdim Attr.getAttributeSpellingListIndex())); 4544239462Sdim} 4545239462Sdim 4546239462Sdimstatic void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4547263508Sdim if (!checkMicrosoftExt(S, Attr)) 4548263508Sdim return; 4549263508Sdim 4550263508Sdim AttributeList::Kind Kind = Attr.getKind(); 4551263508Sdim if (Kind == AttributeList::AT_Win64) 4552263508Sdim D->addAttr( 4553263508Sdim ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, 4554263508Sdim Attr.getAttributeSpellingListIndex())); 4555239462Sdim} 4556239462Sdim 4557239462Sdimstatic void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4558263508Sdim if (!checkMicrosoftExt(S, Attr)) 4559263508Sdim return; 4560263508Sdim D->addAttr(::new (S.Context) 4561263508Sdim ForceInlineAttr(Attr.getRange(), S.Context, 4562263508Sdim Attr.getAttributeSpellingListIndex())); 4563239462Sdim} 4564239462Sdim 4565263508Sdimstatic void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) { 4566263508Sdim if (!checkMicrosoftExt(S, Attr)) 4567263508Sdim return; 4568263508Sdim // Check linkage after possibly merging declaratinos. See 4569263508Sdim // checkAttributesAfterMerging(). 4570263508Sdim D->addAttr(::new (S.Context) 4571263508Sdim SelectAnyAttr(Attr.getRange(), S.Context, 4572263508Sdim Attr.getAttributeSpellingListIndex())); 4573263508Sdim} 4574263508Sdim 4575263508Sdim/// Handles semantic checking for features that are common to all attributes, 4576263508Sdim/// such as checking whether a parameter was properly specified, or the correct 4577263508Sdim/// number of arguments were passed, etc. 4578263508Sdimstatic bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, 4579263508Sdim const AttributeList &Attr) { 4580263508Sdim // Several attributes carry different semantics than the parsing requires, so 4581263508Sdim // those are opted out of the common handling. 4582263508Sdim // 4583263508Sdim // We also bail on unknown and ignored attributes because those are handled 4584263508Sdim // as part of the target-specific handling logic. 4585263508Sdim if (Attr.hasCustomParsing() || 4586263508Sdim Attr.getKind() == AttributeList::UnknownAttribute || 4587263508Sdim Attr.getKind() == AttributeList::IgnoredAttribute) 4588263508Sdim return false; 4589263508Sdim 4590263508Sdim // If there are no optional arguments, then checking for the argument count 4591263508Sdim // is trivial. 4592263508Sdim if (Attr.getMinArgs() == Attr.getMaxArgs() && 4593263508Sdim !checkAttributeNumArgs(S, Attr, Attr.getMinArgs())) 4594263508Sdim return true; 4595263508Sdim return false; 4596263508Sdim} 4597263508Sdim 4598218893Sdim//===----------------------------------------------------------------------===// 4599193326Sed// Top Level Sema Entry Points 4600193326Sed//===----------------------------------------------------------------------===// 4601193326Sed 4602263508Sdim/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if 4603263508Sdim/// the attribute applies to decls. If the attribute is a type attribute, just 4604263508Sdim/// silently ignore it if a GNU attribute. 4605263508Sdimstatic void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 4606263508Sdim const AttributeList &Attr, 4607263508Sdim bool IncludeCXX11Attributes) { 4608263508Sdim if (Attr.isInvalid()) 4609263508Sdim return; 4610207619Srdivacky 4611263508Sdim // Ignore C++11 attributes on declarator chunks: they appertain to the type 4612263508Sdim // instead. 4613263508Sdim if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) 4614263508Sdim return; 4615263508Sdim 4616263508Sdim if (handleCommonAttributeFeatures(S, scope, D, Attr)) 4617263508Sdim return; 4618263508Sdim 4619193326Sed switch (Attr.getKind()) { 4620249423Sdim case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; 4621249423Sdim case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; 4622249423Sdim case AttributeList::AT_IBOutletCollection: 4623249423Sdim handleIBOutletCollection(S, D, Attr); break; 4624239462Sdim case AttributeList::AT_AddressSpace: 4625239462Sdim case AttributeList::AT_ObjCGC: 4626239462Sdim case AttributeList::AT_VectorSize: 4627239462Sdim case AttributeList::AT_NeonVectorType: 4628239462Sdim case AttributeList::AT_NeonPolyVectorType: 4629263508Sdim case AttributeList::AT_Ptr32: 4630263508Sdim case AttributeList::AT_Ptr64: 4631263508Sdim case AttributeList::AT_SPtr: 4632263508Sdim case AttributeList::AT_UPtr: 4633198092Srdivacky // Ignore these, these are type attributes, handled by 4634198092Srdivacky // ProcessTypeAttributes. 4635193326Sed break; 4636239462Sdim case AttributeList::AT_Alias: handleAliasAttr (S, D, Attr); break; 4637239462Sdim case AttributeList::AT_Aligned: handleAlignedAttr (S, D, Attr); break; 4638239462Sdim case AttributeList::AT_AllocSize: handleAllocSizeAttr (S, D, Attr); break; 4639239462Sdim case AttributeList::AT_AlwaysInline: 4640224145Sdim handleAlwaysInlineAttr (S, D, Attr); break; 4641239462Sdim case AttributeList::AT_AnalyzerNoReturn: 4642224145Sdim handleAnalyzerNoReturnAttr (S, D, Attr); break; 4643239462Sdim case AttributeList::AT_TLSModel: handleTLSModelAttr (S, D, Attr); break; 4644239462Sdim case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break; 4645239462Sdim case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; 4646239462Sdim case AttributeList::AT_CarriesDependency: 4647249423Sdim handleDependencyAttr(S, scope, D, Attr); 4648249423Sdim break; 4649239462Sdim case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break; 4650239462Sdim case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break; 4651239462Sdim case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; 4652249423Sdim case AttributeList::AT_CXX11NoReturn: 4653249423Sdim handleCXX11NoReturnAttr(S, D, Attr); 4654249423Sdim break; 4655239462Sdim case AttributeList::AT_Deprecated: 4656263508Sdim handleAttrWithMessage<DeprecatedAttr>(S, D, Attr); 4657239462Sdim break; 4658239462Sdim case AttributeList::AT_Destructor: handleDestructorAttr (S, D, Attr); break; 4659239462Sdim case AttributeList::AT_ExtVectorType: 4660224145Sdim handleExtVectorTypeAttr(S, scope, D, Attr); 4661193326Sed break; 4662243830Sdim case AttributeList::AT_MinSize: 4663243830Sdim handleMinSizeAttr(S, D, Attr); 4664243830Sdim break; 4665239462Sdim case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break; 4666239462Sdim case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break; 4667239462Sdim case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break; 4668263508Sdim case AttributeList::AT_CUDADevice: handleDeviceAttr (S, D, Attr); break; 4669263508Sdim case AttributeList::AT_CUDAHost: handleHostAttr (S, D, Attr); break; 4670239462Sdim case AttributeList::AT_GNUInline: handleGNUInlineAttr (S, D, Attr); break; 4671239462Sdim case AttributeList::AT_CUDALaunchBounds: 4672224145Sdim handleLaunchBoundsAttr(S, D, Attr); 4673218893Sdim break; 4674239462Sdim case AttributeList::AT_Malloc: handleMallocAttr (S, D, Attr); break; 4675239462Sdim case AttributeList::AT_MayAlias: handleMayAliasAttr (S, D, Attr); break; 4676263508Sdim case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break; 4677239462Sdim case AttributeList::AT_NoCommon: handleNoCommonAttr (S, D, Attr); break; 4678239462Sdim case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break; 4679263508Sdim case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; 4680212904Sdim case AttributeList::AT_ownership_returns: 4681212904Sdim case AttributeList::AT_ownership_takes: 4682212904Sdim case AttributeList::AT_ownership_holds: 4683224145Sdim handleOwnershipAttr (S, D, Attr); break; 4684239462Sdim case AttributeList::AT_Cold: handleColdAttr (S, D, Attr); break; 4685239462Sdim case AttributeList::AT_Hot: handleHotAttr (S, D, Attr); break; 4686239462Sdim case AttributeList::AT_Naked: handleNakedAttr (S, D, Attr); break; 4687239462Sdim case AttributeList::AT_NoReturn: handleNoReturnAttr (S, D, Attr); break; 4688239462Sdim case AttributeList::AT_NoThrow: handleNothrowAttr (S, D, Attr); break; 4689239462Sdim case AttributeList::AT_CUDAShared: handleSharedAttr (S, D, Attr); break; 4690239462Sdim case AttributeList::AT_VecReturn: handleVecReturnAttr (S, D, Attr); break; 4691193326Sed 4692239462Sdim case AttributeList::AT_ObjCOwnership: 4693224145Sdim handleObjCOwnershipAttr(S, D, Attr); break; 4694239462Sdim case AttributeList::AT_ObjCPreciseLifetime: 4695224145Sdim handleObjCPreciseLifetimeAttr(S, D, Attr); break; 4696224145Sdim 4697239462Sdim case AttributeList::AT_ObjCReturnsInnerPointer: 4698226633Sdim handleObjCReturnsInnerPointerAttr(S, D, Attr); break; 4699226633Sdim 4700243830Sdim case AttributeList::AT_ObjCRequiresSuper: 4701243830Sdim handleObjCRequiresSuperAttr(S, D, Attr); break; 4702243830Sdim 4703239462Sdim case AttributeList::AT_NSBridged: 4704226633Sdim handleNSBridgedAttr(S, scope, D, Attr); break; 4705263508Sdim 4706263508Sdim case AttributeList::AT_ObjCBridge: 4707263508Sdim handleObjCBridgeAttr(S, scope, D, Attr); break; 4708226633Sdim 4709239462Sdim case AttributeList::AT_CFAuditedTransfer: 4710239462Sdim case AttributeList::AT_CFUnknownTransfer: 4711226633Sdim handleCFTransferAttr(S, D, Attr); break; 4712226633Sdim 4713193326Sed // Checker-specific. 4714239462Sdim case AttributeList::AT_CFConsumed: 4715239462Sdim case AttributeList::AT_NSConsumed: handleNSConsumedAttr (S, D, Attr); break; 4716239462Sdim case AttributeList::AT_NSConsumesSelf: 4717224145Sdim handleNSConsumesSelfAttr(S, D, Attr); break; 4718218893Sdim 4719239462Sdim case AttributeList::AT_NSReturnsAutoreleased: 4720239462Sdim case AttributeList::AT_NSReturnsNotRetained: 4721239462Sdim case AttributeList::AT_CFReturnsNotRetained: 4722239462Sdim case AttributeList::AT_NSReturnsRetained: 4723239462Sdim case AttributeList::AT_CFReturnsRetained: 4724224145Sdim handleNSReturnsRetainedAttr(S, D, Attr); break; 4725193326Sed 4726239462Sdim case AttributeList::AT_WorkGroupSizeHint: 4727239462Sdim case AttributeList::AT_ReqdWorkGroupSize: 4728239462Sdim handleWorkGroupSize(S, D, Attr); break; 4729195099Sed 4730249423Sdim case AttributeList::AT_VecTypeHint: 4731249423Sdim handleVecTypeHint(S, D, Attr); break; 4732249423Sdim 4733239462Sdim case AttributeList::AT_InitPriority: 4734224145Sdim handleInitPriorityAttr(S, D, Attr); break; 4735210299Sed 4736239462Sdim case AttributeList::AT_Packed: handlePackedAttr (S, D, Attr); break; 4737239462Sdim case AttributeList::AT_Section: handleSectionAttr (S, D, Attr); break; 4738239462Sdim case AttributeList::AT_Unavailable: 4739263508Sdim handleAttrWithMessage<UnavailableAttr>(S, D, Attr); 4740239462Sdim break; 4741239462Sdim case AttributeList::AT_ArcWeakrefUnavailable: 4742224145Sdim handleArcWeakrefUnavailableAttr (S, D, Attr); 4743193326Sed break; 4744239462Sdim case AttributeList::AT_ObjCRootClass: 4745234353Sdim handleObjCRootClassAttr(S, D, Attr); 4746234353Sdim break; 4747239462Sdim case AttributeList::AT_ObjCRequiresPropertyDefs: 4748234353Sdim handleObjCRequiresPropertyDefsAttr (S, D, Attr); 4749234353Sdim break; 4750239462Sdim case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break; 4751239462Sdim case AttributeList::AT_ReturnsTwice: 4752226633Sdim handleReturnsTwiceAttr(S, D, Attr); 4753226633Sdim break; 4754239462Sdim case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break; 4755249423Sdim case AttributeList::AT_Visibility: 4756249423Sdim handleVisibilityAttr(S, D, Attr, false); 4757249423Sdim break; 4758249423Sdim case AttributeList::AT_TypeVisibility: 4759249423Sdim handleVisibilityAttr(S, D, Attr, true); 4760249423Sdim break; 4761263508Sdim case AttributeList::AT_WarnUnused: 4762263508Sdim handleWarnUnusedAttr(S, D, Attr); 4763263508Sdim break; 4764239462Sdim case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); 4765224145Sdim break; 4766239462Sdim case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; 4767239462Sdim case AttributeList::AT_WeakRef: handleWeakRefAttr (S, D, Attr); break; 4768239462Sdim case AttributeList::AT_WeakImport: handleWeakImportAttr (S, D, Attr); break; 4769239462Sdim case AttributeList::AT_TransparentUnion: 4770224145Sdim handleTransparentUnionAttr(S, D, Attr); 4771193326Sed break; 4772239462Sdim case AttributeList::AT_ObjCException: 4773224145Sdim handleObjCExceptionAttr(S, D, Attr); 4774193326Sed break; 4775239462Sdim case AttributeList::AT_ObjCMethodFamily: 4776224145Sdim handleObjCMethodFamilyAttr(S, D, Attr); 4777221345Sdim break; 4778239462Sdim case AttributeList::AT_ObjCNSObject:handleObjCNSObject (S, D, Attr); break; 4779239462Sdim case AttributeList::AT_Blocks: handleBlocksAttr (S, D, Attr); break; 4780239462Sdim case AttributeList::AT_Sentinel: handleSentinelAttr (S, D, Attr); break; 4781239462Sdim case AttributeList::AT_Const: handleConstAttr (S, D, Attr); break; 4782239462Sdim case AttributeList::AT_Pure: handlePureAttr (S, D, Attr); break; 4783239462Sdim case AttributeList::AT_Cleanup: handleCleanupAttr (S, D, Attr); break; 4784239462Sdim case AttributeList::AT_NoDebug: handleNoDebugAttr (S, D, Attr); break; 4785239462Sdim case AttributeList::AT_NoInline: handleNoInlineAttr (S, D, Attr); break; 4786239462Sdim case AttributeList::AT_Regparm: handleRegparmAttr (S, D, Attr); break; 4787198092Srdivacky case AttributeList::IgnoredAttribute: 4788193326Sed // Just ignore 4789193326Sed break; 4790239462Sdim case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. 4791224145Sdim handleNoInstrumentFunctionAttr(S, D, Attr); 4792210299Sed break; 4793239462Sdim case AttributeList::AT_StdCall: 4794239462Sdim case AttributeList::AT_CDecl: 4795239462Sdim case AttributeList::AT_FastCall: 4796239462Sdim case AttributeList::AT_ThisCall: 4797239462Sdim case AttributeList::AT_Pascal: 4798256030Sdim case AttributeList::AT_MSABI: 4799256030Sdim case AttributeList::AT_SysVABI: 4800239462Sdim case AttributeList::AT_Pcs: 4801243830Sdim case AttributeList::AT_PnaclCall: 4802249423Sdim case AttributeList::AT_IntelOclBicc: 4803224145Sdim handleCallConvAttr(S, D, Attr); 4804203955Srdivacky break; 4805239462Sdim case AttributeList::AT_OpenCLKernel: 4806224145Sdim handleOpenCLKernelAttr(S, D, Attr); 4807218893Sdim break; 4808249423Sdim case AttributeList::AT_OpenCLImageAccess: 4809249423Sdim handleOpenCLImageAccessAttr(S, D, Attr); 4810249423Sdim break; 4811239462Sdim 4812239462Sdim // Microsoft attributes: 4813239462Sdim case AttributeList::AT_MsStruct: 4814239462Sdim handleMsStructAttr(S, D, Attr); 4815239462Sdim break; 4816239462Sdim case AttributeList::AT_Uuid: 4817224145Sdim handleUuidAttr(S, D, Attr); 4818218893Sdim break; 4819239462Sdim case AttributeList::AT_SingleInheritance: 4820239462Sdim case AttributeList::AT_MultipleInheritance: 4821239462Sdim case AttributeList::AT_VirtualInheritance: 4822239462Sdim handleInheritanceAttr(S, D, Attr); 4823239462Sdim break; 4824239462Sdim case AttributeList::AT_Win64: 4825239462Sdim handlePortabilityAttr(S, D, Attr); 4826239462Sdim break; 4827239462Sdim case AttributeList::AT_ForceInline: 4828239462Sdim handleForceInlineAttr(S, D, Attr); 4829239462Sdim break; 4830263508Sdim case AttributeList::AT_SelectAny: 4831263508Sdim handleSelectAnyAttr(S, D, Attr); 4832263508Sdim break; 4833226633Sdim 4834226633Sdim // Thread safety attributes: 4835263508Sdim case AttributeList::AT_AssertExclusiveLock: 4836263508Sdim handleAssertExclusiveLockAttr(S, D, Attr); 4837263508Sdim break; 4838263508Sdim case AttributeList::AT_AssertSharedLock: 4839263508Sdim handleAssertSharedLockAttr(S, D, Attr); 4840263508Sdim break; 4841239462Sdim case AttributeList::AT_GuardedVar: 4842226633Sdim handleGuardedVarAttr(S, D, Attr); 4843226633Sdim break; 4844239462Sdim case AttributeList::AT_PtGuardedVar: 4845239462Sdim handlePtGuardedVarAttr(S, D, Attr); 4846226633Sdim break; 4847239462Sdim case AttributeList::AT_ScopedLockable: 4848239462Sdim handleScopedLockableAttr(S, D, Attr); 4849226633Sdim break; 4850249423Sdim case AttributeList::AT_NoSanitizeAddress: 4851249423Sdim handleNoSanitizeAddressAttr(S, D, Attr); 4852234353Sdim break; 4853239462Sdim case AttributeList::AT_NoThreadSafetyAnalysis: 4854249423Sdim handleNoThreadSafetyAnalysis(S, D, Attr); 4855226633Sdim break; 4856249423Sdim case AttributeList::AT_NoSanitizeThread: 4857249423Sdim handleNoSanitizeThread(S, D, Attr); 4858249423Sdim break; 4859249423Sdim case AttributeList::AT_NoSanitizeMemory: 4860249423Sdim handleNoSanitizeMemory(S, D, Attr); 4861249423Sdim break; 4862239462Sdim case AttributeList::AT_Lockable: 4863226633Sdim handleLockableAttr(S, D, Attr); 4864226633Sdim break; 4865239462Sdim case AttributeList::AT_GuardedBy: 4866226633Sdim handleGuardedByAttr(S, D, Attr); 4867226633Sdim break; 4868239462Sdim case AttributeList::AT_PtGuardedBy: 4869239462Sdim handlePtGuardedByAttr(S, D, Attr); 4870226633Sdim break; 4871239462Sdim case AttributeList::AT_ExclusiveLockFunction: 4872239462Sdim handleExclusiveLockFunctionAttr(S, D, Attr); 4873226633Sdim break; 4874239462Sdim case AttributeList::AT_ExclusiveLocksRequired: 4875239462Sdim handleExclusiveLocksRequiredAttr(S, D, Attr); 4876226633Sdim break; 4877239462Sdim case AttributeList::AT_ExclusiveTrylockFunction: 4878239462Sdim handleExclusiveTrylockFunctionAttr(S, D, Attr); 4879226633Sdim break; 4880239462Sdim case AttributeList::AT_LockReturned: 4881226633Sdim handleLockReturnedAttr(S, D, Attr); 4882226633Sdim break; 4883239462Sdim case AttributeList::AT_LocksExcluded: 4884226633Sdim handleLocksExcludedAttr(S, D, Attr); 4885226633Sdim break; 4886239462Sdim case AttributeList::AT_SharedLockFunction: 4887239462Sdim handleSharedLockFunctionAttr(S, D, Attr); 4888226633Sdim break; 4889239462Sdim case AttributeList::AT_SharedLocksRequired: 4890239462Sdim handleSharedLocksRequiredAttr(S, D, Attr); 4891226633Sdim break; 4892239462Sdim case AttributeList::AT_SharedTrylockFunction: 4893239462Sdim handleSharedTrylockFunctionAttr(S, D, Attr); 4894226633Sdim break; 4895239462Sdim case AttributeList::AT_UnlockFunction: 4896226633Sdim handleUnlockFunAttr(S, D, Attr); 4897226633Sdim break; 4898239462Sdim case AttributeList::AT_AcquiredBefore: 4899239462Sdim handleAcquiredBeforeAttr(S, D, Attr); 4900226633Sdim break; 4901239462Sdim case AttributeList::AT_AcquiredAfter: 4902239462Sdim handleAcquiredAfterAttr(S, D, Attr); 4903226633Sdim break; 4904226633Sdim 4905263508Sdim // Consumed analysis attributes. 4906263508Sdim case AttributeList::AT_Consumable: 4907263508Sdim handleConsumableAttr(S, D, Attr); 4908263508Sdim break; 4909263508Sdim case AttributeList::AT_CallableWhen: 4910263508Sdim handleCallableWhenAttr(S, D, Attr); 4911263508Sdim break; 4912263508Sdim case AttributeList::AT_ParamTypestate: 4913263508Sdim handleParamTypestateAttr(S, D, Attr); 4914263508Sdim break; 4915263508Sdim case AttributeList::AT_ReturnTypestate: 4916263508Sdim handleReturnTypestateAttr(S, D, Attr); 4917263508Sdim break; 4918263508Sdim case AttributeList::AT_SetTypestate: 4919263508Sdim handleSetTypestateAttr(S, D, Attr); 4920263508Sdim break; 4921263508Sdim case AttributeList::AT_TestTypestate: 4922263508Sdim handleTestTypestateAttr(S, D, Attr); 4923263508Sdim break; 4924263508Sdim 4925239462Sdim // Type safety attributes. 4926239462Sdim case AttributeList::AT_ArgumentWithTypeTag: 4927239462Sdim handleArgumentWithTypeTagAttr(S, D, Attr); 4928239462Sdim break; 4929239462Sdim case AttributeList::AT_TypeTagForDatatype: 4930239462Sdim handleTypeTagForDatatypeAttr(S, D, Attr); 4931239462Sdim break; 4932239462Sdim 4933193326Sed default: 4934202379Srdivacky // Ask target about the attribute. 4935202379Srdivacky const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); 4936202379Srdivacky if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) 4937239462Sdim S.Diag(Attr.getLoc(), Attr.isDeclspecAttribute() ? 4938239462Sdim diag::warn_unhandled_ms_attribute_ignored : 4939239462Sdim diag::warn_unknown_attribute_ignored) << Attr.getName(); 4940193326Sed break; 4941193326Sed } 4942193326Sed} 4943193326Sed 4944193326Sed/// ProcessDeclAttributeList - Apply all the decl attributes in the specified 4945193326Sed/// attribute list to the specified decl, ignoring any type attributes. 4946218893Sdimvoid Sema::ProcessDeclAttributeList(Scope *S, Decl *D, 4947218893Sdim const AttributeList *AttrList, 4948249423Sdim bool IncludeCXX11Attributes) { 4949249423Sdim for (const AttributeList* l = AttrList; l; l = l->getNext()) 4950263508Sdim ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); 4951204643Srdivacky 4952204643Srdivacky // GCC accepts 4953204643Srdivacky // static int a9 __attribute__((weakref)); 4954204643Srdivacky // but that looks really pointless. We reject it. 4955263508Sdim if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { 4956204643Srdivacky Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << 4957249423Sdim cast<NamedDecl>(D)->getNameAsString(); 4958249423Sdim D->dropAttr<WeakRefAttr>(); 4959204643Srdivacky return; 4960204643Srdivacky } 4961193326Sed} 4962193326Sed 4963226633Sdim// Annotation attributes are the only attributes allowed after an access 4964226633Sdim// specifier. 4965226633Sdimbool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, 4966226633Sdim const AttributeList *AttrList) { 4967226633Sdim for (const AttributeList* l = AttrList; l; l = l->getNext()) { 4968239462Sdim if (l->getKind() == AttributeList::AT_Annotate) { 4969226633Sdim handleAnnotateAttr(*this, ASDecl, *l); 4970226633Sdim } else { 4971226633Sdim Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); 4972226633Sdim return true; 4973226633Sdim } 4974226633Sdim } 4975226633Sdim 4976226633Sdim return false; 4977226633Sdim} 4978226633Sdim 4979226633Sdim/// checkUnusedDeclAttributes - Check a list of attributes to see if it 4980226633Sdim/// contains any decl attributes that we should warn about. 4981226633Sdimstatic void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { 4982226633Sdim for ( ; A; A = A->getNext()) { 4983226633Sdim // Only warn if the attribute is an unignored, non-type attribute. 4984249423Sdim if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; 4985226633Sdim if (A->getKind() == AttributeList::IgnoredAttribute) continue; 4986226633Sdim 4987226633Sdim if (A->getKind() == AttributeList::UnknownAttribute) { 4988226633Sdim S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) 4989226633Sdim << A->getName() << A->getRange(); 4990226633Sdim } else { 4991226633Sdim S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) 4992226633Sdim << A->getName() << A->getRange(); 4993226633Sdim } 4994226633Sdim } 4995226633Sdim} 4996226633Sdim 4997226633Sdim/// checkUnusedDeclAttributes - Given a declarator which is not being 4998226633Sdim/// used to build a declaration, complain about any decl attributes 4999226633Sdim/// which might be lying around on it. 5000226633Sdimvoid Sema::checkUnusedDeclAttributes(Declarator &D) { 5001226633Sdim ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); 5002226633Sdim ::checkUnusedDeclAttributes(*this, D.getAttributes()); 5003226633Sdim for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) 5004226633Sdim ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); 5005226633Sdim} 5006226633Sdim 5007198092Srdivacky/// DeclClonePragmaWeak - clone existing decl (maybe definition), 5008239462Sdim/// \#pragma weak needs a non-definition decl and source may not have one. 5009226633SdimNamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, 5010226633Sdim SourceLocation Loc) { 5011198092Srdivacky assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); 5012198092Srdivacky NamedDecl *NewD = 0; 5013198092Srdivacky if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 5014226633Sdim FunctionDecl *NewFD; 5015226633Sdim // FIXME: Missing call to CheckFunctionDeclaration(). 5016226633Sdim // FIXME: Mangling? 5017226633Sdim // FIXME: Is the qualifier info correct? 5018226633Sdim // FIXME: Is the DeclContext correct? 5019226633Sdim NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), 5020226633Sdim Loc, Loc, DeclarationName(II), 5021226633Sdim FD->getType(), FD->getTypeSourceInfo(), 5022249423Sdim SC_None, false/*isInlineSpecified*/, 5023226633Sdim FD->hasPrototype(), 5024226633Sdim false/*isConstexprSpecified*/); 5025226633Sdim NewD = NewFD; 5026226633Sdim 5027226633Sdim if (FD->getQualifier()) 5028219077Sdim NewFD->setQualifierInfo(FD->getQualifierLoc()); 5029226633Sdim 5030226633Sdim // Fake up parameter variables; they are declared as if this were 5031226633Sdim // a typedef. 5032226633Sdim QualType FDTy = FD->getType(); 5033226633Sdim if (const FunctionProtoType *FT = FDTy->getAs<FunctionProtoType>()) { 5034226633Sdim SmallVector<ParmVarDecl*, 16> Params; 5035226633Sdim for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), 5036226633Sdim AE = FT->arg_type_end(); AI != AE; ++AI) { 5037226633Sdim ParmVarDecl *Param = BuildParmVarDeclForTypedef(NewFD, Loc, *AI); 5038226633Sdim Param->setScopeInfo(0, Params.size()); 5039226633Sdim Params.push_back(Param); 5040226633Sdim } 5041226633Sdim NewFD->setParams(Params); 5042205219Srdivacky } 5043198092Srdivacky } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { 5044198092Srdivacky NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), 5045221345Sdim VD->getInnerLocStart(), VD->getLocation(), II, 5046200583Srdivacky VD->getType(), VD->getTypeSourceInfo(), 5047249423Sdim VD->getStorageClass()); 5048205219Srdivacky if (VD->getQualifier()) { 5049205219Srdivacky VarDecl *NewVD = cast<VarDecl>(NewD); 5050219077Sdim NewVD->setQualifierInfo(VD->getQualifierLoc()); 5051205219Srdivacky } 5052198092Srdivacky } 5053198092Srdivacky return NewD; 5054198092Srdivacky} 5055198092Srdivacky 5056239462Sdim/// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak 5057198092Srdivacky/// applied to it, possibly with an alias. 5058198092Srdivackyvoid Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { 5059198092Srdivacky if (W.getUsed()) return; // only do this once 5060198092Srdivacky W.setUsed(true); 5061198092Srdivacky if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) 5062198092Srdivacky IdentifierInfo *NDId = ND->getIdentifier(); 5063226633Sdim NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias(), W.getLocation()); 5064212904Sdim NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, 5065212904Sdim NDId->getName())); 5066212904Sdim NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); 5067198092Srdivacky WeakTopLevelDecl.push_back(NewD); 5068198092Srdivacky // FIXME: "hideous" code from Sema::LazilyCreateBuiltin 5069198092Srdivacky // to insert Decl at TU scope, sorry. 5070198092Srdivacky DeclContext *SavedContext = CurContext; 5071198092Srdivacky CurContext = Context.getTranslationUnitDecl(); 5072198092Srdivacky PushOnScopeChains(NewD, S); 5073198092Srdivacky CurContext = SavedContext; 5074198092Srdivacky } else { // just add weak to existing 5075212904Sdim ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); 5076198092Srdivacky } 5077198092Srdivacky} 5078198092Srdivacky 5079249423Sdimvoid Sema::ProcessPragmaWeak(Scope *S, Decl *D) { 5080218893Sdim // It's valid to "forward-declare" #pragma weak, in which case we 5081218893Sdim // have to do this. 5082249423Sdim LoadExternalWeakUndeclaredIdentifiers(); 5083249423Sdim if (!WeakUndeclaredIdentifiers.empty()) { 5084249423Sdim NamedDecl *ND = NULL; 5085249423Sdim if (VarDecl *VD = dyn_cast<VarDecl>(D)) 5086249423Sdim if (VD->isExternC()) 5087249423Sdim ND = VD; 5088249423Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 5089249423Sdim if (FD->isExternC()) 5090249423Sdim ND = FD; 5091249423Sdim if (ND) { 5092249423Sdim if (IdentifierInfo *Id = ND->getIdentifier()) { 5093249423Sdim llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I 5094249423Sdim = WeakUndeclaredIdentifiers.find(Id); 5095249423Sdim if (I != WeakUndeclaredIdentifiers.end()) { 5096249423Sdim WeakInfo W = I->second; 5097249423Sdim DeclApplyPragmaWeak(S, ND, W); 5098249423Sdim WeakUndeclaredIdentifiers[Id] = W; 5099218893Sdim } 5100198092Srdivacky } 5101198092Srdivacky } 5102198092Srdivacky } 5103249423Sdim} 5104198092Srdivacky 5105249423Sdim/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in 5106249423Sdim/// it, apply them to D. This is a bit tricky because PD can have attributes 5107249423Sdim/// specified in many different places, and we need to find and apply them all. 5108263508Sdimvoid Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { 5109193326Sed // Apply decl attributes from the DeclSpec if present. 5110218893Sdim if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) 5111263508Sdim ProcessDeclAttributeList(S, D, Attrs); 5112198092Srdivacky 5113193326Sed // Walk the declarator structure, applying decl attributes that were in a type 5114193326Sed // position to the decl itself. This handles cases like: 5115193326Sed // int *__attr__(x)** D; 5116193326Sed // when X is a decl attribute. 5117193326Sed for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) 5118193326Sed if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) 5119263508Sdim ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); 5120198092Srdivacky 5121193326Sed // Finally, apply any attributes on the decl itself. 5122193326Sed if (const AttributeList *Attrs = PD.getAttributes()) 5123263508Sdim ProcessDeclAttributeList(S, D, Attrs); 5124193326Sed} 5125198893Srdivacky 5126224145Sdim/// Is the given declaration allowed to use a forbidden type? 5127224145Sdimstatic bool isForbiddenTypeAllowed(Sema &S, Decl *decl) { 5128224145Sdim // Private ivars are always okay. Unfortunately, people don't 5129224145Sdim // always properly make their ivars private, even in system headers. 5130224145Sdim // Plus we need to make fields okay, too. 5131226633Sdim // Function declarations in sys headers will be marked unavailable. 5132226633Sdim if (!isa<FieldDecl>(decl) && !isa<ObjCPropertyDecl>(decl) && 5133226633Sdim !isa<FunctionDecl>(decl)) 5134224145Sdim return false; 5135224145Sdim 5136224145Sdim // Require it to be declared in a system header. 5137224145Sdim return S.Context.getSourceManager().isInSystemHeader(decl->getLocation()); 5138224145Sdim} 5139224145Sdim 5140224145Sdim/// Handle a delayed forbidden-type diagnostic. 5141224145Sdimstatic void handleDelayedForbiddenType(Sema &S, DelayedDiagnostic &diag, 5142224145Sdim Decl *decl) { 5143224145Sdim if (decl && isForbiddenTypeAllowed(S, decl)) { 5144224145Sdim decl->addAttr(new (S.Context) UnavailableAttr(diag.Loc, S.Context, 5145224145Sdim "this system declaration uses an unsupported type")); 5146224145Sdim return; 5147224145Sdim } 5148234353Sdim if (S.getLangOpts().ObjCAutoRefCount) 5149226633Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) { 5150239462Sdim // FIXME: we may want to suppress diagnostics for all 5151226633Sdim // kind of forbidden type messages on unavailable functions. 5152226633Sdim if (FD->hasAttr<UnavailableAttr>() && 5153226633Sdim diag.getForbiddenTypeDiagnostic() == 5154226633Sdim diag::err_arc_array_param_no_ownership) { 5155226633Sdim diag.Triggered = true; 5156226633Sdim return; 5157226633Sdim } 5158226633Sdim } 5159224145Sdim 5160224145Sdim S.Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) 5161224145Sdim << diag.getForbiddenTypeOperand() << diag.getForbiddenTypeArgument(); 5162224145Sdim diag.Triggered = true; 5163224145Sdim} 5164224145Sdim 5165239462Sdimvoid Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { 5166239462Sdim assert(DelayedDiagnostics.getCurrentPool()); 5167239462Sdim DelayedDiagnosticPool &poppedPool = *DelayedDiagnostics.getCurrentPool(); 5168239462Sdim DelayedDiagnostics.popWithoutEmitting(state); 5169218893Sdim 5170239462Sdim // When delaying diagnostics to run in the context of a parsed 5171239462Sdim // declaration, we only want to actually emit anything if parsing 5172239462Sdim // succeeds. 5173239462Sdim if (!decl) return; 5174218893Sdim 5175239462Sdim // We emit all the active diagnostics in this pool or any of its 5176239462Sdim // parents. In general, we'll get one pool for the decl spec 5177239462Sdim // and a child pool for each declarator; in a decl group like: 5178239462Sdim // deprecated_typedef foo, *bar, baz(); 5179239462Sdim // only the declarator pops will be passed decls. This is correct; 5180239462Sdim // we really do need to consider delayed diagnostics from the decl spec 5181239462Sdim // for each of the different declarations. 5182239462Sdim const DelayedDiagnosticPool *pool = &poppedPool; 5183239462Sdim do { 5184239462Sdim for (DelayedDiagnosticPool::pool_iterator 5185239462Sdim i = pool->pool_begin(), e = pool->pool_end(); i != e; ++i) { 5186239462Sdim // This const_cast is a bit lame. Really, Triggered should be mutable. 5187239462Sdim DelayedDiagnostic &diag = const_cast<DelayedDiagnostic&>(*i); 5188218893Sdim if (diag.Triggered) 5189203955Srdivacky continue; 5190198893Srdivacky 5191218893Sdim switch (diag.Kind) { 5192203955Srdivacky case DelayedDiagnostic::Deprecation: 5193234353Sdim // Don't bother giving deprecation diagnostics if the decl is invalid. 5194234353Sdim if (!decl->isInvalidDecl()) 5195239462Sdim HandleDelayedDeprecationCheck(diag, decl); 5196203955Srdivacky break; 5197203955Srdivacky 5198203955Srdivacky case DelayedDiagnostic::Access: 5199239462Sdim HandleDelayedAccessCheck(diag, decl); 5200203955Srdivacky break; 5201224145Sdim 5202224145Sdim case DelayedDiagnostic::ForbiddenType: 5203239462Sdim handleDelayedForbiddenType(*this, diag, decl); 5204224145Sdim break; 5205198893Srdivacky } 5206198893Srdivacky } 5207239462Sdim } while ((pool = pool->getParent())); 5208239462Sdim} 5209198893Srdivacky 5210239462Sdim/// Given a set of delayed diagnostics, re-emit them as if they had 5211239462Sdim/// been delayed in the current context instead of in the given pool. 5212239462Sdim/// Essentially, this just moves them to the current pool. 5213239462Sdimvoid Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { 5214239462Sdim DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); 5215239462Sdim assert(curPool && "re-emitting in undelayed context not supported"); 5216239462Sdim curPool->steal(pool); 5217198893Srdivacky} 5218198893Srdivacky 5219203955Srdivackystatic bool isDeclDeprecated(Decl *D) { 5220203955Srdivacky do { 5221221345Sdim if (D->isDeprecated()) 5222203955Srdivacky return true; 5223226633Sdim // A category implicitly has the availability of the interface. 5224226633Sdim if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) 5225226633Sdim return CatD->getClassInterface()->isDeprecated(); 5226203955Srdivacky } while ((D = cast_or_null<Decl>(D->getDeclContext()))); 5227203955Srdivacky return false; 5228203955Srdivacky} 5229203955Srdivacky 5230239462Sdimstatic void 5231239462SdimDoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, 5232239462Sdim SourceLocation Loc, 5233243830Sdim const ObjCInterfaceDecl *UnknownObjCClass, 5234243830Sdim const ObjCPropertyDecl *ObjCPropery) { 5235239462Sdim DeclarationName Name = D->getDeclName(); 5236239462Sdim if (!Message.empty()) { 5237239462Sdim S.Diag(Loc, diag::warn_deprecated_message) << Name << Message; 5238239462Sdim S.Diag(D->getLocation(), 5239239462Sdim isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at 5240239462Sdim : diag::note_previous_decl) << Name; 5241243830Sdim if (ObjCPropery) 5242243830Sdim S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) 5243243830Sdim << ObjCPropery->getDeclName() << 0; 5244239462Sdim } else if (!UnknownObjCClass) { 5245239462Sdim S.Diag(Loc, diag::warn_deprecated) << D->getDeclName(); 5246239462Sdim S.Diag(D->getLocation(), 5247239462Sdim isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at 5248239462Sdim : diag::note_previous_decl) << Name; 5249243830Sdim if (ObjCPropery) 5250243830Sdim S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) 5251243830Sdim << ObjCPropery->getDeclName() << 0; 5252239462Sdim } else { 5253239462Sdim S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; 5254239462Sdim S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); 5255239462Sdim } 5256239462Sdim} 5257239462Sdim 5258212904Sdimvoid Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, 5259203955Srdivacky Decl *Ctx) { 5260203955Srdivacky if (isDeclDeprecated(Ctx)) 5261203955Srdivacky return; 5262203955Srdivacky 5263203955Srdivacky DD.Triggered = true; 5264239462Sdim DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), 5265239462Sdim DD.getDeprecationMessage(), DD.Loc, 5266243830Sdim DD.getUnknownObjCClass(), 5267243830Sdim DD.getObjCProperty()); 5268203955Srdivacky} 5269203955Srdivacky 5270226633Sdimvoid Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, 5271218893Sdim SourceLocation Loc, 5272243830Sdim const ObjCInterfaceDecl *UnknownObjCClass, 5273243830Sdim const ObjCPropertyDecl *ObjCProperty) { 5274198893Srdivacky // Delay if we're currently parsing a declaration. 5275218893Sdim if (DelayedDiagnostics.shouldDelayDiagnostics()) { 5276234353Sdim DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, 5277234353Sdim UnknownObjCClass, 5278243830Sdim ObjCProperty, 5279234353Sdim Message)); 5280198893Srdivacky return; 5281198893Srdivacky } 5282198893Srdivacky 5283198893Srdivacky // Otherwise, don't warn if our current context is deprecated. 5284226633Sdim if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) 5285198893Srdivacky return; 5286243830Sdim DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); 5287198893Srdivacky} 5288