zcov: / lib/Sema/SemaDeclAttr.cpp


Files: 1 Branches Taken: 74.0% 743 / 1004
Generated: 2010-02-10 01:31 Branches Executed: 93.6% 940 / 1004
Line Coverage: 82.8% 856 / 1034


Programs: 2 Runs 3018


       1                 : //===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : //  This file implements decl-related attribute processing.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "Sema.h"
      15                 : #include "TargetAttributesSema.h"
      16                 : #include "clang/AST/ASTContext.h"
      17                 : #include "clang/AST/DeclObjC.h"
      18                 : #include "clang/AST/Expr.h"
      19                 : #include "clang/Basic/TargetInfo.h"
      20                 : #include "clang/Parse/DeclSpec.h"
      21                 : #include "llvm/ADT/StringExtras.h"
      22                 : using namespace clang;
      23                 : 
      24                 : //===----------------------------------------------------------------------===//
      25                 : //  Helper functions
      26                 : //===----------------------------------------------------------------------===//
      27                 : 
      28                 : static const FunctionType *getFunctionType(const Decl *d,
      29             3536:                                            bool blocksToo = true) {
      30             3536:   QualType Ty;
                     3483: branch 1 taken
                       53: branch 2 taken
      31             3536:   if (const ValueDecl *decl = dyn_cast<ValueDecl>(d))
      32             3483:     Ty = decl->getType();
                        0: branch 1 not taken
                       53: branch 2 taken
      33               53:   else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
      34                0:     Ty = decl->getType();
                        5: branch 1 taken
                       48: branch 2 taken
      35               53:   else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
      36                5:     Ty = decl->getUnderlyingType();
      37                 :   else
      38               48:     return 0;
      39                 : 
                       29: branch 2 taken
                     3459: branch 3 taken
      40             3488:   if (Ty->isFunctionPointerType())
      41               29:     Ty = Ty->getAs<PointerType>()->getPointeeType();
                     1699: branch 0 taken
                     1760: branch 1 taken
                        7: branch 4 taken
                     1692: branch 5 taken
                        7: branch 6 taken
                     3452: branch 7 taken
      42             3459:   else if (blocksToo && Ty->isBlockPointerType())
      43                7:     Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
      44                 : 
      45             3488:   return Ty->getAs<FunctionType>();
      46                 : }
      47                 : 
      48                 : // FIXME: We should provide an abstraction around a method or function
      49                 : // to provide the following bits of information.
      50                 : 
      51                 : /// isFunction - Return true if the given decl has function
      52                 : /// type (function or function-typed variable).
      53             1785: static bool isFunction(const Decl *d) {
      54             1785:   return getFunctionType(d, false) != NULL;
      55                 : }
      56                 : 
      57                 : /// isFunctionOrMethod - Return true if the given decl has function
      58                 : /// type (function or function-typed variable) or an Objective-C
      59                 : /// method.
      60             1785: static bool isFunctionOrMethod(const Decl *d) {
                       22: branch 1 taken
                     1763: branch 2 taken
                        9: branch 4 taken
                       13: branch 5 taken
      61             1785:   return isFunction(d)|| isa<ObjCMethodDecl>(d);
      62                 : }
      63                 : 
      64                 : /// isFunctionOrMethodOrBlock - Return true if the given decl has function
      65                 : /// type (function or function-typed variable) or an Objective-C
      66                 : /// method or a block.
      67               75: static bool isFunctionOrMethodOrBlock(const Decl *d) {
                       71: branch 1 taken
                        4: branch 2 taken
      68               75:   if (isFunctionOrMethod(d))
      69               71:     return true;
      70                 :   // check for block is more involved.
                        2: branch 1 taken
                        2: branch 2 taken
      71                4:   if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
      72                2:     QualType Ty = V->getType();
      73                2:     return Ty->isBlockPointerType();
      74                 :   }
      75                2:   return isa<BlockDecl>(d);
      76                 : }
      77                 : 
      78                 : /// hasFunctionProto - Return true if the given decl has a argument
      79                 : /// information. This decl should have already passed
      80                 : /// isFunctionOrMethod or isFunctionOrMethodOrBlock.
      81              495: static bool hasFunctionProto(const Decl *d) {
                      487: branch 1 taken
                        8: branch 2 taken
      82              495:   if (const FunctionType *FnTy = getFunctionType(d))
      83              487:     return isa<FunctionProtoType>(FnTy);
      84                 :   else {
                        2: branch 1 taken
                        6: branch 2 taken
                        0: branch 4 not taken
                        2: branch 5 taken
      85                8:     assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d));
      86                8:     return true;
      87                 :   }
      88                 : }
      89                 : 
      90                 : /// getFunctionOrMethodNumArgs - Return number of function or method
      91                 : /// arguments. It is an error to call this on a K&R function (use
      92                 : /// hasFunctionProto first).
      93              506: static unsigned getFunctionOrMethodNumArgs(const Decl *d) {
                      498: branch 1 taken
                        8: branch 2 taken
      94              506:   if (const FunctionType *FnTy = getFunctionType(d))
      95              498:     return cast<FunctionProtoType>(FnTy)->getNumArgs();
                        2: branch 1 taken
                        6: branch 2 taken
      96                8:   if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
      97                2:     return BD->getNumParams();
      98                6:   return cast<ObjCMethodDecl>(d)->param_size();
      99                 : }
     100                 : 
     101              682: static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) {
                      674: branch 1 taken
                        8: branch 2 taken
     102              682:   if (const FunctionType *FnTy = getFunctionType(d))
     103              674:     return cast<FunctionProtoType>(FnTy)->getArgType(Idx);
                        2: branch 1 taken
                        6: branch 2 taken
     104                8:   if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
     105                2:     return BD->getParamDecl(Idx)->getType();
     106                 : 
     107                6:   return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType();
     108                 : }
     109                 : 
     110               10: static QualType getFunctionOrMethodResultType(const Decl *d) {
                       10: branch 1 taken
                        0: branch 2 not taken
     111               10:   if (const FunctionType *FnTy = getFunctionType(d))
     112               10:     return cast<FunctionProtoType>(FnTy)->getResultType();
     113                0:   return cast<ObjCMethodDecl>(d)->getResultType();
     114                 : }
     115                 : 
     116               42: static bool isFunctionOrMethodVariadic(const Decl *d) {
                       36: branch 1 taken
                        6: branch 2 taken
     117               42:   if (const FunctionType *FnTy = getFunctionType(d)) {
     118               36:     const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy);
     119               36:     return proto->isVariadic();
                        1: branch 1 taken
                        5: branch 2 taken
     120                6:   } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d))
     121                1:     return BD->IsVariadic();
     122                 :   else {
     123                5:     return cast<ObjCMethodDecl>(d)->isVariadic();
     124                 :   }
     125                 : }
     126                 : 
     127               42: static inline bool isNSStringType(QualType T, ASTContext &Ctx) {
     128               42:   const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
                        7: branch 0 taken
                       35: branch 1 taken
     129               42:   if (!PT)
     130                7:     return false;
     131                 : 
     132               35:   const ObjCInterfaceType *ClsT =PT->getPointeeType()->getAs<ObjCInterfaceType>();
                        0: branch 0 not taken
                       35: branch 1 taken
     133               35:   if (!ClsT)
     134                0:     return false;
     135                 : 
     136               35:   IdentifierInfo* ClsName = ClsT->getDecl()->getIdentifier();
     137                 : 
     138                 :   // FIXME: Should we walk the chain of classes?
     139                 :   return ClsName == &Ctx.Idents.get("NSString") ||
                        0: branch 2 not taken
                       35: branch 3 taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     140               35:          ClsName == &Ctx.Idents.get("NSMutableString");
     141                 : }
     142                 : 
     143                8: static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
     144                8:   const PointerType *PT = T->getAs<PointerType>();
                        2: branch 0 taken
                        6: branch 1 taken
     145                8:   if (!PT)
     146                2:     return false;
     147                 : 
     148                6:   const RecordType *RT = PT->getPointeeType()->getAs<RecordType>();
                        5: branch 0 taken
                        1: branch 1 taken
     149                6:   if (!RT)
     150                5:     return false;
     151                 : 
     152                1:   const RecordDecl *RD = RT->getDecl();
                        0: branch 1 not taken
                        1: branch 2 taken
     153                1:   if (RD->getTagKind() != TagDecl::TK_struct)
     154                0:     return false;
     155                 : 
     156                1:   return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
     157                 : }
     158                 : 
     159                 : //===----------------------------------------------------------------------===//
     160                 : // Attribute Implementations
     161                 : //===----------------------------------------------------------------------===//
     162                 : 
     163                 : // FIXME: All this manual attribute parsing code is gross. At the
     164                 : // least add some helper functions to check most argument patterns (#
     165                 : // and types of args).
     166                 : 
     167                 : static void HandleExtVectorTypeAttr(Scope *scope, Decl *d,
     168               65:                                     const AttributeList &Attr, Sema &S) {
     169               65:   TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d);
                        0: branch 0 not taken
                       65: branch 1 taken
     170               65:   if (tDecl == 0) {
     171                0:     S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef);
     172                0:     return;
     173                 :   }
     174                 : 
     175               65:   QualType curType = tDecl->getUnderlyingType();
     176                 : 
     177                 :   Expr *sizeExpr;
     178                 : 
     179                 :   // Special case where the argument is a template id.
                        9: branch 1 taken
                       56: branch 2 taken
     180               65:   if (Attr.getParameterName()) {
     181                9:     CXXScopeSpec SS;
     182                9:     UnqualifiedId id;
     183                9:     id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
     184                9:     sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>();
     185                 :   } else {
     186                 :     // check the attribute arguments.
                        0: branch 1 not taken
                       56: branch 2 taken
     187               56:     if (Attr.getNumArgs() != 1) {
     188                0:       S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     189                0:       return;
     190                 :     }
     191               56:     sizeExpr = static_cast<Expr *>(Attr.getArg(0));
     192                 :   }
     193                 : 
     194                 :   // Instantiate/Install the vector type, and let Sema build the type for us.
     195                 :   // This will run the reguired checks.
     196               65:   QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc());
                       64: branch 1 taken
                        1: branch 2 taken
     197               65:   if (!T.isNull()) {
     198                 :     // FIXME: preserve the old source info.
     199               64:     tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T));
     200                 : 
     201                 :     // Remember this typedef decl, we will need it later for diagnostics.
     202               64:     S.ExtVectorDecls.push_back(tDecl);
     203                 :   }
     204                 : }
     205                 : 
     206               26: static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     207                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       26: branch 2 taken
     208               26:   if (Attr.getNumArgs() > 0) {
     209                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     210                0:     return;
     211                 :   }
     212                 : 
                       17: branch 1 taken
                        9: branch 2 taken
     213               26:   if (TagDecl *TD = dyn_cast<TagDecl>(d))
                       17: branch 1 taken
                        0: branch 2 not taken
     214               17:     TD->addAttr(::new (S.Context) PackedAttr);
                        9: branch 1 taken
                        0: branch 2 not taken
     215                9:   else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) {
     216                 :     // If the alignment is less than or equal to 8 bits, the packed attribute
     217                 :     // has no effect.
                        8: branch 3 taken
                        1: branch 4 taken
                        0: branch 7 not taken
                        8: branch 8 taken
                        0: branch 9 not taken
                        9: branch 10 taken
     218                9:     if (!FD->getType()->isIncompleteType() &&
     219                 :         S.Context.getTypeAlign(FD->getType()) <= 8)
     220                 :       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type)
     221                0:         << Attr.getName() << FD->getType();
     222                 :     else
                        9: branch 1 taken
                        0: branch 2 not taken
     223                9:       FD->addAttr(::new (S.Context) PackedAttr);
     224                 :   } else
     225                0:     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
     226                 : }
     227                 : 
     228                1: static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     229                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        1: branch 2 taken
     230                1:   if (Attr.getNumArgs() > 0) {
     231                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     232                0:     return;
     233                 :   }
     234                 : 
     235                 :   // The IBOutlet attribute only applies to instance variables of Objective-C
     236                 :   // classes.
                        0: branch 1 not taken
                        1: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        1: branch 6 taken
                        0: branch 7 not taken
     237                1:   if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))
                        1: branch 1 taken
                        0: branch 2 not taken
     238                1:     d->addAttr(::new (S.Context) IBOutletAttr());
     239                 :   else
     240                0:     S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet);
     241                 : }
     242                 : 
     243              409: static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     244                 :   // GCC ignores the nonnull attribute on K&R style function prototypes, so we
     245                 :   // ignore it as well
                      409: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                      409: branch 5 taken
                        0: branch 6 not taken
                      409: branch 7 taken
     246              409:   if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
     247                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     248                0:       << Attr.getName() << 0 /*function*/;
     249                0:     return;
     250                 :   }
     251                 : 
     252              409:   unsigned NumArgs = getFunctionOrMethodNumArgs(d);
     253                 : 
     254                 :   // The nonnull attribute only applies to pointers.
     255              409:   llvm::SmallVector<unsigned, 10> NonNullArgs;
     256                 : 
                      582: branch 2 taken
                        1: branch 3 taken
                        0: branch 4 not taken
                      583: branch 7 taken
                      408: branch 8 taken
     257             1983:   for (AttributeList::arg_iterator I=Attr.arg_begin(),
     258              409:                                    E=Attr.arg_end(); I!=E; ++I) {
     259                 : 
     260                 : 
     261                 :     // The argument must be an integer constant expression.
     262              583:     Expr *Ex = static_cast<Expr *>(*I);
     263              583:     llvm::APSInt ArgNum(32);
                        0: branch 1 not taken
                      583: branch 2 taken
     264              583:     if (!Ex->isIntegerConstantExpr(ArgNum, S.Context)) {
     265                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
     266                0:         << "nonnull" << Ex->getSourceRange();
     267                2:       return;
     268                 :     }
     269                 : 
     270              583:     unsigned x = (unsigned) ArgNum.getZExtValue();
     271                 : 
                      582: branch 0 taken
                        1: branch 1 taken
                        0: branch 2 not taken
                      582: branch 3 taken
     272              583:     if (x < 1 || x > NumArgs) {
     273                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
     274                1:        << "nonnull" << I.getArgNum() << Ex->getSourceRange();
     275                 :       return;
     276                 :     }
     277                 : 
     278              582:     --x;
     279                 : 
     280                 :     // Is the function argument a pointer type?
     281              582:     QualType T = getFunctionOrMethodArgType(d, x);
                        4: branch 2 taken
                      578: branch 3 taken
                        0: branch 6 not taken
                        4: branch 7 taken
                        0: branch 8 not taken
                      582: branch 9 taken
     282              582:     if (!T->isAnyPointerType() && !T->isBlockPointerType()) {
     283                 :       // FIXME: Should also highlight argument in decl.
     284                 :       S.Diag(Attr.getLoc(), diag::err_nonnull_pointers_only)
     285                0:         << "nonnull" << Ex->getSourceRange();
     286                0:       continue;
     287                 :     }
     288                 : 
     289              582:     NonNullArgs.push_back(x);
     290                 :   }
     291                 : 
     292                 :   // If no arguments were specified to __attribute__((nonnull)) then all pointer
     293                 :   // arguments have a nonnull attribute.
                       11: branch 1 taken
                      397: branch 2 taken
     294              408:   if (NonNullArgs.empty()) {
                       17: branch 1 taken
                       11: branch 2 taken
     295               28:     for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) {
     296               17:       QualType T = getFunctionOrMethodArgType(d, I);
                        8: branch 2 taken
                        9: branch 3 taken
                        2: branch 6 taken
                        6: branch 7 taken
                       11: branch 8 taken
                        6: branch 9 taken
     297               17:       if (T->isAnyPointerType() || T->isBlockPointerType())
     298               11:         NonNullArgs.push_back(I);
     299                 :     }
     300                 : 
                        1: branch 1 taken
                       10: branch 2 taken
     301               11:     if (NonNullArgs.empty()) {
     302                1:       S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers);
     303                 :       return;
     304                 :     }
     305                 :   }
     306                 : 
     307              407:   unsigned* start = &NonNullArgs[0];
     308              407:   unsigned size = NonNullArgs.size();
     309              407:   std::sort(start, start + size);
                      407: branch 1 taken
                        0: branch 2 not taken
                      407: branch 6 taken
                        2: branch 7 taken
     310              407:   d->addAttr(::new (S.Context) NonNullAttr(start, size));
     311                 : }
     312                 : 
     313               11: static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     314                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       11: branch 2 taken
     315               11:   if (Attr.getNumArgs() != 1) {
     316                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     317                0:     return;
     318                 :   }
     319                 : 
     320               11:   Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
     321               11:   Arg = Arg->IgnoreParenCasts();
     322               11:   StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
     323                 : 
                       11: branch 0 taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                       11: branch 4 taken
                        0: branch 5 not taken
                       11: branch 6 taken
     324               11:   if (Str == 0 || Str->isWide()) {
     325                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
     326                0:       << "alias" << 1;
     327                0:     return;
     328                 :   }
     329                 : 
     330                 :   // FIXME: check if target symbol exists in current file
     331                 : 
                       11: branch 2 taken
                        0: branch 3 not taken
     332               11:   d->addAttr(::new (S.Context) AliasAttr(Str->getString()));
     333                 : }
     334                 : 
     335                 : static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr,
     336             1279:                                    Sema &S) {
     337                 :   // check the attribute arguments.
                        0: branch 1 not taken
                     1279: branch 2 taken
     338             1279:   if (Attr.getNumArgs() != 0) {
     339                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     340                0:     return;
     341                 :   }
     342                 : 
                        0: branch 1 not taken
                     1279: branch 2 taken
     343             1279:   if (!isa<FunctionDecl>(d)) {
     344                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     345                0:     << Attr.getName() << 0 /*function*/;
     346                0:     return;
     347                 :   }
     348                 : 
                     1279: branch 1 taken
                        0: branch 2 not taken
     349             1279:   d->addAttr(::new (S.Context) AlwaysInlineAttr());
     350                 : }
     351                 : 
     352               46: static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     353                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       46: branch 2 taken
     354               46:   if (Attr.getNumArgs() != 0) {
     355                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     356                0:     return;
     357                 :   }
     358                 : 
                       35: branch 1 taken
                       11: branch 2 taken
     359               46:   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
     360               35:     QualType RetTy = FD->getResultType();
                        5: branch 2 taken
                       30: branch 3 taken
                        1: branch 6 taken
                        4: branch 7 taken
                       31: branch 8 taken
                        4: branch 9 taken
     361               35:     if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) {
                       31: branch 1 taken
                        0: branch 2 not taken
     362               31:       d->addAttr(::new (S.Context) MallocAttr());
     363               31:       return;
     364                 :     }
     365                 :   }
     366                 : 
     367               15:   S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only);
     368                 : }
     369                 : 
     370                 : static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
     371               14:                                      Sema &S) {
     372                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       14: branch 2 taken
     373               14:   if (Attr.getNumArgs() != 0) {
     374                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     375                0:     return false;
     376                 :   }
     377                 : 
                        3: branch 1 taken
                       11: branch 2 taken
                        0: branch 4 not taken
                        3: branch 5 taken
                        0: branch 6 not taken
                       14: branch 7 taken
     378               14:   if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) {
     379                0:     ValueDecl *VD = dyn_cast<ValueDecl>(d);
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 10 not taken
                        0: branch 11 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
     380                0:     if (VD == 0 || (!VD->getType()->isBlockPointerType()
     381                 :                     && !VD->getType()->isFunctionPointerType())) {
     382                 :       S.Diag(Attr.getLoc(),
     383                 :              Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
     384                 :                                      : diag::warn_attribute_wrong_decl_type)
                        0: branch 2 not taken
                        0: branch 3 not taken
     385                0:         << Attr.getName() << 0 /*function*/;
     386                0:       return false;
     387                 :     }
     388                 :   }
     389                 : 
     390               14:   return true;
     391                 : }
     392                 : 
     393              105: static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     394                 :   // Don't apply as a decl attribute to ValueDecl.
     395                 :   // FIXME: probably ought to diagnose this.
                       99: branch 1 taken
                        6: branch 2 taken
     396              105:   if (isa<ValueDecl>(d))
     397               99:     return;
     398                 : 
                        6: branch 1 taken
                        0: branch 2 not taken
     399                6:   if (HandleCommonNoReturnAttr(d, Attr, S))
                        6: branch 1 taken
                        0: branch 2 not taken
     400                6:     d->addAttr(::new (S.Context) NoReturnAttr());
     401                 : }
     402                 : 
     403                 : static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
     404                8:                                        Sema &S) {
                        8: branch 1 taken
                        0: branch 2 not taken
     405                8:   if (HandleCommonNoReturnAttr(d, Attr, S))
                        8: branch 1 taken
                        0: branch 2 not taken
     406                8:     d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
     407                8: }
     408                 : 
     409                0: static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     410                0:   if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
     411                 :     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
     412                0:       << Attr.getName() << 8 /*function, method, or parameter*/;
     413                0:     return;
     414                 :   }
     415                 :   // FIXME: Actually store the attribute on the declaration
     416                 : }
     417                 : 
     418               24: static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     419                 :   // check the attribute arguments.
                        1: branch 1 taken
                       23: branch 2 taken
     420               24:   if (Attr.getNumArgs() != 0) {
     421                1:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     422                1:     return;
     423                 :   }
     424                 : 
                        5: branch 1 taken
                       18: branch 2 taken
                        0: branch 4 not taken
                        5: branch 5 taken
                        0: branch 6 not taken
                       23: branch 7 taken
     425               23:   if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
     426                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     427                0:       << Attr.getName() << 2 /*variable and function*/;
     428                0:     return;
     429                 :   }
     430                 : 
                       23: branch 1 taken
                        0: branch 2 not taken
     431               23:   d->addAttr(::new (S.Context) UnusedAttr());
     432                 : }
     433                 : 
     434               16: static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     435                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       16: branch 2 taken
     436               16:   if (Attr.getNumArgs() != 0) {
     437                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     438                0:     return;
     439                 :   }
     440                 : 
                       13: branch 1 taken
                        3: branch 2 taken
     441               16:   if (const VarDecl *VD = dyn_cast<VarDecl>(d)) {
                       12: branch 1 taken
                        1: branch 2 taken
                        2: branch 4 taken
                       10: branch 5 taken
                        3: branch 6 taken
                       10: branch 7 taken
     442               13:     if (VD->hasLocalStorage() || VD->hasExternalStorage()) {
     443                3:       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";
     444                3:       return;
     445                 :     }
                        1: branch 1 taken
                        2: branch 2 taken
     446                3:   } else if (!isFunctionOrMethod(d)) {
     447                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     448                1:       << Attr.getName() << 2 /*variable and function*/;
     449                1:     return;
     450                 :   }
     451                 : 
                       12: branch 1 taken
                        0: branch 2 not taken
     452               12:   d->addAttr(::new (S.Context) UsedAttr());
     453                 : }
     454                 : 
     455                8: static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     456                 :   // check the attribute arguments.
                        3: branch 1 taken
                        5: branch 2 taken
                        1: branch 4 taken
                        2: branch 5 taken
                        1: branch 6 taken
                        7: branch 7 taken
     457                8:   if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
     458                 :     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
     459                1:       << "0 or 1";
     460                1:     return;
     461                 :   }
     462                 : 
     463                7:   int priority = 65535; // FIXME: Do not hardcode such constants.
                        2: branch 1 taken
                        5: branch 2 taken
     464                7:   if (Attr.getNumArgs() > 0) {
     465                2:     Expr *E = static_cast<Expr *>(Attr.getArg(0));
     466                2:     llvm::APSInt Idx(32);
                        1: branch 1 taken
                        1: branch 2 taken
     467                2:     if (!E->isIntegerConstantExpr(Idx, S.Context)) {
     468                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
     469                1:         << "constructor" << 1 << E->getSourceRange();
     470                1:       return;
     471                 :     }
                        1: branch 2 taken
                        1: branch 3 taken
     472                1:     priority = Idx.getZExtValue();
     473                 :   }
     474                 : 
                        1: branch 1 taken
                        5: branch 2 taken
     475                6:   if (!isa<FunctionDecl>(d)) {
     476                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     477                1:       << Attr.getName() << 0 /*function*/;
     478                1:     return;
     479                 :   }
     480                 : 
                        5: branch 1 taken
                        0: branch 2 not taken
     481                5:   d->addAttr(::new (S.Context) ConstructorAttr(priority));
     482                 : }
     483                 : 
     484                7: static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     485                 :   // check the attribute arguments.
                        3: branch 1 taken
                        4: branch 2 taken
                        1: branch 4 taken
                        2: branch 5 taken
                        1: branch 6 taken
                        6: branch 7 taken
     486                7:   if (Attr.getNumArgs() != 0 && Attr.getNumArgs() != 1) {
     487                 :     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
     488                1:        << "0 or 1";
     489                1:     return;
     490                 :   }
     491                 : 
     492                6:   int priority = 65535; // FIXME: Do not hardcode such constants.
                        2: branch 1 taken
                        4: branch 2 taken
     493                6:   if (Attr.getNumArgs() > 0) {
     494                2:     Expr *E = static_cast<Expr *>(Attr.getArg(0));
     495                2:     llvm::APSInt Idx(32);
                        1: branch 1 taken
                        1: branch 2 taken
     496                2:     if (!E->isIntegerConstantExpr(Idx, S.Context)) {
     497                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
     498                1:         << "destructor" << 1 << E->getSourceRange();
     499                1:       return;
     500                 :     }
                        1: branch 2 taken
                        1: branch 3 taken
     501                1:     priority = Idx.getZExtValue();
     502                 :   }
     503                 : 
                        1: branch 1 taken
                        4: branch 2 taken
     504                5:   if (!isa<FunctionDecl>(d)) {
     505                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     506                1:       << Attr.getName() << 0 /*function*/;
     507                1:     return;
     508                 :   }
     509                 : 
                        4: branch 1 taken
                        0: branch 2 not taken
     510                4:   d->addAttr(::new (S.Context) DestructorAttr(priority));
     511                 : }
     512                 : 
     513               46: static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     514                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       46: branch 2 taken
     515               46:   if (Attr.getNumArgs() != 0) {
     516                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     517                0:     return;
     518                 :   }
     519                 : 
                       46: branch 1 taken
                        0: branch 2 not taken
     520               46:   d->addAttr(::new (S.Context) DeprecatedAttr());
     521                 : }
     522                 : 
     523                9: static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     524                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        9: branch 2 taken
     525                9:   if (Attr.getNumArgs() != 0) {
     526                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     527                0:     return;
     528                 :   }
     529                 : 
                        9: branch 1 taken
                        0: branch 2 not taken
     530                9:   d->addAttr(::new (S.Context) UnavailableAttr());
     531                 : }
     532                 : 
     533               14: static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     534                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       14: branch 2 taken
     535               14:   if (Attr.getNumArgs() != 1) {
     536                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     537                0:     return;
     538                 :   }
     539                 : 
     540               14:   Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
     541               14:   Arg = Arg->IgnoreParenCasts();
     542               14:   StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
     543                 : 
                       14: branch 0 taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                       14: branch 4 taken
                        0: branch 5 not taken
                       14: branch 6 taken
     544               14:   if (Str == 0 || Str->isWide()) {
     545                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
     546                0:       << "visibility" << 1;
     547                0:     return;
     548                 :   }
     549                 : 
     550               14:   llvm::StringRef TypeStr = Str->getString();
     551                 :   VisibilityAttr::VisibilityTypes type;
     552                 : 
                        4: branch 2 taken
                       10: branch 3 taken
     553               14:   if (TypeStr == "default")
     554                4:     type = VisibilityAttr::DefaultVisibility;
                        9: branch 2 taken
                        1: branch 3 taken
     555               10:   else if (TypeStr == "hidden")
     556                9:     type = VisibilityAttr::HiddenVisibility;
                        0: branch 2 not taken
                        1: branch 3 taken
     557                1:   else if (TypeStr == "internal")
     558                0:     type = VisibilityAttr::HiddenVisibility; // FIXME
                        1: branch 2 taken
                        0: branch 3 not taken
     559                1:   else if (TypeStr == "protected")
     560                1:     type = VisibilityAttr::ProtectedVisibility;
     561                 :   else {
     562                0:     S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
     563                0:     return;
     564                 :   }
     565                 : 
                       14: branch 1 taken
                        0: branch 2 not taken
     566               14:   d->addAttr(::new (S.Context) VisibilityAttr(type));
     567                 : }
     568                 : 
     569                 : static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
     570                7:                                     Sema &S) {
                        0: branch 1 not taken
                        7: branch 2 taken
     571                7:   if (Attr.getNumArgs() != 0) {
     572                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     573                0:     return;
     574                 :   }
     575                 : 
     576                7:   ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
                        2: branch 0 taken
                        5: branch 1 taken
     577                7:   if (OCI == 0) {
     578                2:     S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface);
     579                2:     return;
     580                 :   }
     581                 : 
                        5: branch 1 taken
                        0: branch 2 not taken
     582                5:   D->addAttr(::new (S.Context) ObjCExceptionAttr());
     583                 : }
     584                 : 
     585                4: static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                        4: branch 2 taken
     586                4:   if (Attr.getNumArgs() != 0) {
     587                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     588                0:     return;
     589                 :   }
                        4: branch 1 taken
                        0: branch 2 not taken
     590                4:   if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
     591                4:     QualType T = TD->getUnderlyingType();
                        3: branch 2 taken
                        1: branch 3 taken
                        1: branch 9 taken
                        2: branch 10 taken
                        2: branch 11 taken
                        2: branch 12 taken
     592                4:     if (!T->isPointerType() ||
     593                 :         !T->getAs<PointerType>()->getPointeeType()->isRecordType()) {
     594                2:       S.Diag(TD->getLocation(), diag::err_nsobject_attribute);
     595                2:       return;
     596                 :     }
     597                 :   }
                        2: branch 1 taken
                        0: branch 2 not taken
     598                2:   D->addAttr(::new (S.Context) ObjCNSObjectAttr());
     599                 : }
     600                 : 
     601                 : static void
     602               35: HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                       35: branch 2 taken
     603               35:   if (Attr.getNumArgs() != 0) {
     604                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     605                0:     return;
     606                 :   }
     607                 : 
                        1: branch 1 taken
                       34: branch 2 taken
     608               35:   if (!isa<FunctionDecl>(D)) {
     609                1:     S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);
     610                1:     return;
     611                 :   }
     612                 : 
                       34: branch 1 taken
                        0: branch 2 not taken
     613               34:   D->addAttr(::new (S.Context) OverloadableAttr());
     614                 : }
     615                 : 
     616              112: static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                      112: branch 2 taken
     617              112:   if (!Attr.getParameterName()) {
     618                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
     619                0:       << "blocks" << 1;
     620                0:     return;
     621                 :   }
     622                 : 
                        0: branch 1 not taken
                      112: branch 2 taken
     623              112:   if (Attr.getNumArgs() != 0) {
     624                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     625                0:     return;
     626                 :   }
     627                 : 
     628                 :   BlocksAttr::BlocksAttrTypes type;
                      112: branch 2 taken
                        0: branch 3 not taken
     629              112:   if (Attr.getParameterName()->isStr("byref"))
     630              112:     type = BlocksAttr::ByRef;
     631                 :   else {
     632                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
     633                0:       << "blocks" << Attr.getParameterName();
     634                0:     return;
     635                 :   }
     636                 : 
                      112: branch 1 taken
                        0: branch 2 not taken
     637              224:   d->addAttr(::new (S.Context) BlocksAttr(type));
     638                 : }
     639                 : 
     640               40: static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     641                 :   // check the attribute arguments.
                        2: branch 1 taken
                       38: branch 2 taken
     642               40:   if (Attr.getNumArgs() > 2) {
     643                 :     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
     644                2:       << "0, 1 or 2";
     645                2:     return;
     646                 :   }
     647                 : 
     648               38:   int sentinel = 0;
                       22: branch 1 taken
                       16: branch 2 taken
     649               38:   if (Attr.getNumArgs() > 0) {
     650               22:     Expr *E = static_cast<Expr *>(Attr.getArg(0));
     651               22:     llvm::APSInt Idx(32);
                        2: branch 1 taken
                       20: branch 2 taken
     652               22:     if (!E->isIntegerConstantExpr(Idx, S.Context)) {
     653                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
     654                2:        << "sentinel" << 1 << E->getSourceRange();
     655                4:       return;
     656                 :     }
     657               20:     sentinel = Idx.getZExtValue();
     658                 : 
                        2: branch 0 taken
                       18: branch 1 taken
     659               20:     if (sentinel < 0) {
     660                 :       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero)
     661                2:         << E->getSourceRange();
     662                 :       return;
                       18: branch 1 taken
                        4: branch 2 taken
     663               22:     }
     664                 :   }
     665                 : 
     666               34:   int nullPos = 0;
                        5: branch 1 taken
                       29: branch 2 taken
     667               34:   if (Attr.getNumArgs() > 1) {
     668                5:     Expr *E = static_cast<Expr *>(Attr.getArg(1));
     669                5:     llvm::APSInt Idx(32);
                        0: branch 1 not taken
                        5: branch 2 taken
     670                5:     if (!E->isIntegerConstantExpr(Idx, S.Context)) {
     671                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
     672                0:         << "sentinel" << 2 << E->getSourceRange();
     673                1:       return;
     674                 :     }
     675                5:     nullPos = Idx.getZExtValue();
     676                 : 
                        4: branch 0 taken
                        1: branch 1 taken
                        0: branch 2 not taken
                        4: branch 3 taken
     677                5:     if (nullPos > 1 || nullPos < 0) {
     678                 :       // FIXME: This error message could be improved, it would be nice
     679                 :       // to say what the bounds actually are.
     680                 :       S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one)
     681                1:         << E->getSourceRange();
     682                 :       return;
                        4: branch 1 taken
                        1: branch 2 taken
     683                5:     }
     684                 :   }
     685                 : 
                       13: branch 1 taken
                       20: branch 2 taken
     686               33:   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) {
     687               13:     const FunctionType *FT = FD->getType()->getAs<FunctionType>();
                        0: branch 0 not taken
                       13: branch 1 taken
     688               13:     assert(FT && "FunctionDecl has non-function type?");
     689                 : 
                        1: branch 1 taken
                       12: branch 2 taken
     690               13:     if (isa<FunctionNoProtoType>(FT)) {
     691                1:       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments);
     692                1:       return;
     693                 :     }
     694                 : 
                        1: branch 2 taken
                       11: branch 3 taken
     695               12:     if (!cast<FunctionProtoType>(FT)->isVariadic()) {
     696                1:       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
     697                1:       return;
     698                 :     }
                        7: branch 1 taken
                       13: branch 2 taken
     699               20:   } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) {
                        1: branch 1 taken
                        6: branch 2 taken
     700                7:     if (!MD->isVariadic()) {
     701                1:       S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0;
     702                1:       return;
     703                 :     }
                       10: branch 1 taken
                        3: branch 2 taken
     704               13:   } else if (isa<BlockDecl>(d)) {
     705                 :     // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the
     706                 :     // caller.
     707                 :     ;
                       10: branch 1 taken
                        0: branch 2 not taken
     708               10:   } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) {
     709               10:     QualType Ty = V->getType();
                        5: branch 2 taken
                        5: branch 3 taken
                        4: branch 6 taken
                        1: branch 7 taken
                        9: branch 8 taken
                        1: branch 9 taken
     710               10:     if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) {
     711                 :       const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d)
                        4: branch 2 taken
                        5: branch 3 taken
     712                9:         : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>();
                        1: branch 2 taken
                        8: branch 3 taken
     713                9:       if (!cast<FunctionProtoType>(FT)->isVariadic()) {
                        0: branch 2 not taken
                        1: branch 3 taken
     714                1:         int m = Ty->isFunctionPointerType() ? 0 : 1;
     715                1:         S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m;
     716                1:         return;
     717                 :       }
     718                 :     } else {
     719                 :       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     720                1:       << Attr.getName() << 6 /*function, method or block */;
     721                1:       return;
     722                 :     }
     723                 :   } else {
     724                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     725                0:       << Attr.getName() << 6 /*function, method or block */;
     726                0:     return;
     727                 :   }
                       28: branch 1 taken
                        0: branch 2 not taken
     728               28:   d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos));
     729                 : }
     730                 : 
     731               13: static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) {
     732                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       13: branch 2 taken
     733               13:   if (Attr.getNumArgs() != 0) {
     734                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     735                0:     return;
     736                 :   }
     737                 : 
                        1: branch 1 taken
                       12: branch 2 taken
     738               13:   if (!isFunctionOrMethod(D)) {
     739                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     740                1:       << Attr.getName() << 0 /*function*/;
     741                1:     return;
     742                 :   }
     743                 : 
                        1: branch 4 taken
                       11: branch 5 taken
     744               12:   if (getFunctionType(D)->getResultType()->isVoidType()) {
     745                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_void_function)
     746                1:       << Attr.getName();
     747                1:     return;
     748                 :   }
     749                 : 
                       11: branch 1 taken
                        0: branch 2 not taken
     750               11:   D->addAttr(::new (S.Context) WarnUnusedResultAttr());
     751                 : }
     752                 : 
     753               21: static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     754                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       21: branch 2 taken
     755               21:   if (Attr.getNumArgs() != 0) {
     756                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     757                0:     return;
     758                 :   }
     759                 : 
     760                 :   /* weak only applies to non-static declarations */
     761               21:   bool isStatic = false;
                       12: branch 1 taken
                        9: branch 2 taken
     762               21:   if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
     763               12:     isStatic = VD->getStorageClass() == VarDecl::Static;
                        8: branch 1 taken
                        1: branch 2 taken
     764                9:   } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     765                8:     isStatic = FD->getStorageClass() == FunctionDecl::Static;
     766                 :   }
                        1: branch 0 taken
                       20: branch 1 taken
     767               21:   if (isStatic) {
     768                 :     S.Diag(Attr.getLoc(), diag::err_attribute_weak_static) <<
     769                1:       dyn_cast<NamedDecl>(D)->getNameAsString();
     770                1:     return;
     771                 :   }
     772                 : 
     773                 :   // TODO: could also be applied to methods?
                       12: branch 1 taken
                        8: branch 2 taken
                        1: branch 4 taken
                       11: branch 5 taken
                        1: branch 6 taken
                       19: branch 7 taken
     774               20:   if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
     775                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     776                1:       << Attr.getName() << 2 /*variable and function*/;
     777                1:     return;
     778                 :   }
     779                 : 
                       19: branch 1 taken
                        0: branch 2 not taken
     780               19:   D->addAttr(::new (S.Context) WeakAttr());
     781                 : }
     782                 : 
     783               17: static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     784                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       17: branch 2 taken
     785               17:   if (Attr.getNumArgs() != 0) {
     786                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     787                0:     return;
     788                 :   }
     789                 : 
     790                 :   // weak_import only applies to variable & function declarations.
     791               17:   bool isDef = false;
                        4: branch 1 taken
                       13: branch 2 taken
     792               17:   if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
                        3: branch 1 taken
                        1: branch 2 taken
                        0: branch 4 not taken
                        3: branch 5 taken
     793                4:     isDef = (!VD->hasExternalStorage() || VD->getInit());
                        4: branch 1 taken
                        9: branch 2 taken
     794               13:   } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     795                4:     isDef = FD->getBody();
                        8: branch 1 taken
                        1: branch 2 taken
                        2: branch 4 taken
                        6: branch 5 taken
                        3: branch 6 taken
                        6: branch 7 taken
     796                9:   } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) {
     797                 :     // We ignore weak import on properties and methods
     798                3:     return;
                        5: branch 0 taken
                        1: branch 1 taken
                        0: branch 3 not taken
                        5: branch 4 taken
                        1: branch 5 taken
                        5: branch 6 taken
     799                6:   } else if (!(S.LangOpts.ObjCNonFragileABI && isa<ObjCInterfaceDecl>(D))) {
     800                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     801                1:     << Attr.getName() << 2 /*variable and function*/;
     802                1:     return;
     803                 :   }
     804                 : 
     805                 :   // Merge should handle any subsequent violations.
                        1: branch 0 taken
                       12: branch 1 taken
     806               13:   if (isDef) {
     807                 :     S.Diag(Attr.getLoc(),
     808                 :            diag::warn_attribute_weak_import_invalid_on_definition)
     809                1:       << "weak_import" << 2 /*variable and function*/;
     810                1:     return;
     811                 :   }
     812                 : 
                       12: branch 1 taken
                        0: branch 2 not taken
     813               12:   D->addAttr(::new (S.Context) WeakImportAttr());
     814                 : }
     815                 : 
     816                7: static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     817                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        7: branch 2 taken
     818                7:   if (Attr.getNumArgs() != 0) {
     819                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     820                0:     return;
     821                 :   }
     822                 : 
     823                 :   // Attribute can be applied only to functions or variables.
                        0: branch 1 not taken
                        7: branch 2 taken
     824                7:   if (isa<VarDecl>(D)) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     825                0:     D->addAttr(::new (S.Context) DLLImportAttr());
     826                0:     return;
     827                 :   }
     828                 : 
     829                7:   FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
                        1: branch 0 taken
                        6: branch 1 taken
     830                7:   if (!FD) {
     831                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     832                1:       << Attr.getName() << 2 /*variable and function*/;
     833                1:     return;
     834                 :   }
     835                 : 
     836                 :   // Currently, the dllimport attribute is ignored for inlined functions.
     837                 :   // Warning is emitted.
                        1: branch 1 taken
                        5: branch 2 taken
     838                6:   if (FD->isInlineSpecified()) {
     839                1:     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
     840                1:     return;
     841                 :   }
     842                 : 
     843                 :   // The attribute is also overridden by a subsequent declaration as dllexport.
     844                 :   // Warning is emitted.
                        0: branch 2 not taken
                        5: branch 3 taken
     845                5:   for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
     846                 :        nextAttr = nextAttr->getNext()) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     847                0:     if (nextAttr->getKind() == AttributeList::AT_dllexport) {
     848                0:       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
     849                0:       return;
     850                 :     }
     851                 :   }
     852                 : 
                        2: branch 1 taken
                        3: branch 2 taken
     853                5:   if (D->getAttr<DLLExportAttr>()) {
     854                2:     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
     855                2:     return;
     856                 :   }
     857                 : 
                        3: branch 1 taken
                        0: branch 2 not taken
     858                3:   D->addAttr(::new (S.Context) DLLImportAttr());
     859                 : }
     860                 : 
     861                6: static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     862                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        6: branch 2 taken
     863                6:   if (Attr.getNumArgs() != 0) {
     864                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     865                0:     return;
     866                 :   }
     867                 : 
     868                 :   // Attribute can be applied only to functions or variables.
                        0: branch 1 not taken
                        6: branch 2 taken
     869                6:   if (isa<VarDecl>(D)) {
                        0: branch 1 not taken
                        0: branch 2 not taken
     870                0:     D->addAttr(::new (S.Context) DLLExportAttr());
     871                0:     return;
     872                 :   }
     873                 : 
     874                6:   FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
                        1: branch 0 taken
                        5: branch 1 taken
     875                6:   if (!FD) {
     876                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
     877                1:       << Attr.getName() << 2 /*variable and function*/;
     878                1:     return;
     879                 :   }
     880                 : 
     881                 :   // Currently, the dllexport attribute is ignored for inlined functions, unless
     882                 :   // the -fkeep-inline-functions flag has been used. Warning is emitted;
                        1: branch 1 taken
                        4: branch 2 taken
     883                5:   if (FD->isInlineSpecified()) {
     884                 :     // FIXME: ... unless the -fkeep-inline-functions flag has been used.
     885                1:     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
     886                1:     return;
     887                 :   }
     888                 : 
                        4: branch 1 taken
                        0: branch 2 not taken
     889                4:   D->addAttr(::new (S.Context) DLLExportAttr());
     890                 : }
     891                 : 
     892                 : static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
     893                0:                                     Sema &S) {
     894                 :   // Attribute has 3 arguments.
                        0: branch 1 not taken
                        0: branch 2 not taken
     895                0:   if (Attr.getNumArgs() != 3) {
     896                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     897                0:     return;
     898                 :   }
     899                 : 
     900                 :   unsigned WGSize[3];
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
     901                0:   for (unsigned i = 0; i < 3; ++i) {
     902                0:     Expr *E = static_cast<Expr *>(Attr.getArg(i));
     903                0:     llvm::APSInt ArgNum(32);
                        0: branch 1 not taken
                        0: branch 2 not taken
     904                0:     if (!E->isIntegerConstantExpr(ArgNum, S.Context)) {
     905                 :       S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
     906                0:         << "reqd_work_group_size" << E->getSourceRange();
     907                0:       return;
     908                 :     }
     909                0:     WGSize[i] = (unsigned) ArgNum.getZExtValue();
     910                 :   }
     911                 :   D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
                        0: branch 1 not taken
                        0: branch 2 not taken
     912                0:                                                      WGSize[2]));
     913                 : }
     914                 : 
     915               14: static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     916                 :   // Attribute has no arguments.
                        0: branch 1 not taken
                       14: branch 2 taken
     917               14:   if (Attr.getNumArgs() != 1) {
     918                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     919                0:     return;
     920                 :   }
     921                 : 
     922                 :   // Make sure that there is a string literal as the sections's single
     923                 :   // argument.
     924               14:   Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
     925               14:   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
                        1: branch 0 taken
                       13: branch 1 taken
     926               14:   if (!SE) {
     927                1:     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section";
     928                1:     return;
     929                 :   }
     930                 : 
     931                 :   // If the target wants to validate the section specifier, make it happen.
     932               13:   std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString());
                        1: branch 1 taken
                       12: branch 2 taken
     933               13:   if (!Error.empty()) {
     934                 :     S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target)
     935                1:     << Error;
     936                2:     return;
     937                 :   }
     938                 : 
     939                 :   // This attribute cannot be applied to local variables.
                       10: branch 1 taken
                        2: branch 2 taken
                        1: branch 5 taken
                        9: branch 6 taken
                        1: branch 7 taken
                       11: branch 8 taken
     940               12:   if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) {
     941                1:     S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable);
     942                 :     return;
     943                 :   }
     944                 :   
                       11: branch 2 taken
                        0: branch 3 not taken
                       11: branch 7 taken
                        2: branch 8 taken
     945               11:   D->addAttr(::new (S.Context) SectionAttr(SE->getString()));
     946                 : }
     947                 : 
     948                 : 
     949              457: static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     950                 :   // check the attribute arguments.
                        0: branch 1 not taken
                      457: branch 2 taken
     951              457:   if (Attr.getNumArgs() != 0) {
     952                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     953                0:     return;
     954                 :   }
     955                 : 
                      457: branch 1 taken
                        0: branch 2 not taken
     956              457:   d->addAttr(::new (S.Context) NoThrowAttr());
     957                 : }
     958                 : 
     959               48: static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     960                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       48: branch 2 taken
     961               48:   if (Attr.getNumArgs() != 0) {
     962                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     963                0:     return;
     964                 :   }
     965                 : 
                       48: branch 1 taken
                        0: branch 2 not taken
     966               48:   d->addAttr(::new (S.Context) ConstAttr());
     967                 : }
     968                 : 
     969               36: static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) {
     970                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       36: branch 2 taken
     971               36:   if (Attr.getNumArgs() != 0) {
     972                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     973                0:     return;
     974                 :   }
     975                 : 
                       36: branch 1 taken
                        0: branch 2 not taken
     976               36:   d->addAttr(::new (S.Context) PureAttr());
     977                 : }
     978                 : 
     979               18: static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        2: branch 1 taken
                       16: branch 2 taken
     980               18:   if (!Attr.getParameterName()) {
     981                2:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     982                2:     return;
     983                 :   }
     984                 : 
                        0: branch 1 not taken
                       16: branch 2 taken
     985               16:   if (Attr.getNumArgs() != 0) {
     986                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
     987                0:     return;
     988                 :   }
     989                 : 
     990               16:   VarDecl *VD = dyn_cast<VarDecl>(d);
     991                 : 
                       16: branch 0 taken
                        0: branch 1 not taken
                        4: branch 3 taken
                       12: branch 4 taken
                        4: branch 5 taken
                       12: branch 6 taken
     992               16:   if (!VD || !VD->hasLocalStorage()) {
     993                4:     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup";
     994                4:     return;
     995                 :   }
     996                 : 
     997                 :   // Look up the function
     998                 :   NamedDecl *CleanupDecl
     999                 :     = S.LookupSingleName(S.TUScope, Attr.getParameterName(),
    1000               12:                          Sema::LookupOrdinaryName);
                        1: branch 0 taken
                       11: branch 1 taken
    1001               12:   if (!CleanupDecl) {
    1002                 :     S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_found) <<
    1003                1:       Attr.getParameterName();
    1004                1:     return;
    1005                 :   }
    1006                 : 
    1007               11:   FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
                        1: branch 0 taken
                       10: branch 1 taken
    1008               11:   if (!FD) {
    1009                 :     S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_arg_not_function) <<
    1010                1:       Attr.getParameterName();
    1011                1:     return;
    1012                 :   }
    1013                 : 
                        1: branch 1 taken
                        9: branch 2 taken
    1014               10:   if (FD->getNumParams() != 1) {
    1015                 :     S.Diag(Attr.getLoc(), diag::err_attribute_cleanup_func_must_take_one_arg) <<
    1016                1:       Attr.getParameterName();
    1017                1:     return;
    1018                 :   }
    1019                 : 
    1020                 :   // We're currently more strict than GCC about what function types we accept.
    1021                 :   // If this ever proves to be a problem it should be easy to fix.
    1022                9:   QualType Ty = S.Context.getPointerType(VD->getType());
    1023                9:   QualType ParamTy = FD->getParamDecl(0)->getType();
                        1: branch 1 taken
                        8: branch 2 taken
    1024                9:   if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
    1025                 :     S.Diag(Attr.getLoc(),
    1026                 :            diag::err_attribute_cleanup_func_arg_incompatible_type) <<
    1027                1:       Attr.getParameterName() << ParamTy << Ty;
    1028                1:     return;
    1029                 :   }
    1030                 : 
                        8: branch 1 taken
                        0: branch 2 not taken
    1031                8:   d->addAttr(::new (S.Context) CleanupAttr(FD));
    1032                 : }
    1033                 : 
    1034                 : /// Handle __attribute__((format_arg((idx)))) attribute based on
    1035                 : /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
    1036               18: static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        4: branch 1 taken
                       14: branch 2 taken
    1037               18:   if (Attr.getNumArgs() != 1) {
    1038                4:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
    1039                4:     return;
    1040                 :   }
                       11: branch 1 taken
                        3: branch 2 taken
                        0: branch 4 not taken
                       11: branch 5 taken
                        3: branch 6 taken
                       11: branch 7 taken
    1041               14:   if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
    1042                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1043                3:     << Attr.getName() << 0 /*function*/;
    1044                3:     return;
    1045                 :   }
    1046                 :   // FIXME: in C++ the implicit 'this' function parameter also counts.  this is
    1047                 :   // needed in order to be compatible with GCC the index must start with 1.
    1048               11:   unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
    1049               11:   unsigned FirstIdx = 1;
    1050                 :   // checks for the 2nd argument
    1051               11:   Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
    1052               11:   llvm::APSInt Idx(32);
                        0: branch 1 not taken
                       11: branch 2 taken
    1053               11:   if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
    1054                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
    1055                0:     << "format" << 2 << IdxExpr->getSourceRange();
    1056                2:     return;
    1057                 :   }
    1058                 : 
                       11: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       11: branch 5 taken
                        0: branch 6 not taken
                       11: branch 7 taken
    1059               11:   if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
    1060                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
    1061                0:     << "format" << 2 << IdxExpr->getSourceRange();
    1062                 :     return;
    1063                 :   }
    1064                 : 
    1065               11:   unsigned ArgIdx = Idx.getZExtValue() - 1;
    1066                 : 
    1067                 :   // make sure the format string is really a string
    1068               11:   QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
    1069                 : 
    1070               11:   bool not_nsstring_type = !isNSStringType(Ty, S.Context);
                        3: branch 0 taken
                        8: branch 1 taken
                        3: branch 3 taken
                        0: branch 4 not taken
                        2: branch 7 taken
                        1: branch 8 taken
                        0: branch 14 not taken
                        2: branch 15 taken
                        1: branch 16 taken
                       10: branch 17 taken
    1071               11:   if (not_nsstring_type &&
    1072                 :       !isCFStringType(Ty, S.Context) &&
    1073                 :       (!Ty->isPointerType() ||
    1074                 :        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
    1075                 :     // FIXME: Should highlight the actual expression that has the wrong type.
    1076                 :     S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
    1077                 :     << (not_nsstring_type ? "a string type" : "an NSString")
                        1: branch 1 taken
                        0: branch 2 not taken
    1078                1:        << IdxExpr->getSourceRange();
    1079                 :     return;
    1080                 :   }
    1081               10:   Ty = getFunctionOrMethodResultType(d);
                        3: branch 1 taken
                        7: branch 2 taken
                        3: branch 4 taken
                        0: branch 5 not taken
                        2: branch 8 taken
                        1: branch 9 taken
                        0: branch 15 not taken
                        2: branch 16 taken
                        1: branch 17 taken
                        9: branch 18 taken
    1082               10:   if (!isNSStringType(Ty, S.Context) &&
    1083                 :       !isCFStringType(Ty, S.Context) &&
    1084                 :       (!Ty->isPointerType() ||
    1085                 :        !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) {
    1086                 :     // FIXME: Should highlight the actual expression that has the wrong type.
    1087                 :     S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not)
    1088                 :     << (not_nsstring_type ? "string type" : "NSString")
                        0: branch 1 not taken
                        1: branch 2 taken
    1089                1:        << IdxExpr->getSourceRange();
    1090                 :     return;
    1091                 :   }
    1092                 : 
                        9: branch 2 taken
                        0: branch 3 not taken
                        9: branch 7 taken
                        2: branch 8 taken
    1093                9:   d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));
    1094                 : }
    1095                 : 
    1096                 : enum FormatAttrKind {
    1097                 :   CFStringFormat,
    1098                 :   NSStringFormat,
    1099                 :   StrftimeFormat,
    1100                 :   SupportedFormat,
    1101                 :   InvalidFormat
    1102                 : };
    1103                 : 
    1104                 : /// getFormatAttrKind - Map from format attribute names to supported format
    1105                 : /// types.
    1106               75: static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) {
    1107                 :   // Check for formats that get handled specially.
                       21: branch 2 taken
                       54: branch 3 taken
    1108               75:   if (Format == "NSString")
    1109               21:     return NSStringFormat;
                        2: branch 2 taken
                       52: branch 3 taken
    1110               54:   if (Format == "CFString")
    1111                2:     return CFStringFormat;
                        2: branch 2 taken
                       50: branch 3 taken
    1112               52:   if (Format == "strftime")
    1113                2:     return StrftimeFormat;
    1114                 : 
    1115                 :   // Otherwise, check for supported formats.
                       38: branch 2 taken
                       12: branch 3 taken
                        6: branch 6 taken
                       32: branch 7 taken
                        0: branch 10 not taken
                        6: branch 11 taken
                        0: branch 14 not taken
                        0: branch 15 not taken
                        0: branch 18 not taken
                        0: branch 19 not taken
                        0: branch 22 not taken
                        0: branch 23 not taken
                        0: branch 26 not taken
                        0: branch 27 not taken
                        0: branch 30 not taken
                        0: branch 31 not taken
                        0: branch 34 not taken
                        0: branch 35 not taken
                        0: branch 38 not taken
                        0: branch 39 not taken
                       50: branch 40 taken
                        0: branch 41 not taken
    1116               50:   if (Format == "scanf" || Format == "printf" || Format == "printf0" ||
    1117                 :       Format == "strfmon" || Format == "cmn_err" || Format == "strftime" ||
    1118                 :       Format == "NSString" || Format == "CFString" || Format == "vcmn_err" ||
    1119                 :       Format == "zcmn_err")
    1120               50:     return SupportedFormat;
    1121                 : 
    1122                0:   return InvalidFormat;
    1123                 : }
    1124                 : 
    1125                 : /// Handle __attribute__((format(type,idx,firstarg))) attributes based on
    1126                 : /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
    1127               75: static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1128                 : 
                        0: branch 1 not taken
                       75: branch 2 taken
    1129               75:   if (!Attr.getParameterName()) {
    1130                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
    1131                0:       << "format" << 1;
    1132                0:     return;
    1133                 :   }
    1134                 : 
                        0: branch 1 not taken
                       75: branch 2 taken
    1135               75:   if (Attr.getNumArgs() != 2) {
    1136                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3;
    1137                0:     return;
    1138                 :   }
    1139                 : 
                       75: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       75: branch 5 taken
                        0: branch 6 not taken
                       75: branch 7 taken
    1140               75:   if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) {
    1141                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1142                0:       << Attr.getName() << 0 /*function*/;
    1143                0:     return;
    1144                 :   }
    1145                 : 
    1146               75:   unsigned NumArgs  = getFunctionOrMethodNumArgs(d);
    1147               75:   unsigned FirstIdx = 1;
    1148                 : 
    1149               75:   llvm::StringRef Format = Attr.getParameterName()->getName();
    1150                 : 
    1151                 :   // Normalize the argument, __foo__ becomes foo.
                       47: branch 2 taken
                       28: branch 3 taken
                       47: branch 6 taken
                        0: branch 7 not taken
                       47: branch 8 taken
                       28: branch 9 taken
    1152               75:   if (Format.startswith("__") && Format.endswith("__"))
    1153               47:     Format = Format.substr(2, Format.size() - 4);
    1154                 : 
    1155                 :   // Check for supported formats.
    1156               75:   FormatAttrKind Kind = getFormatAttrKind(Format);
                        0: branch 0 not taken
                       75: branch 1 taken
    1157               75:   if (Kind == InvalidFormat) {
    1158                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
    1159                0:       << "format" << Attr.getParameterName()->getName();
    1160                0:     return;
    1161                 :   }
    1162                 : 
    1163                 :   // checks for the 2nd argument
    1164               75:   Expr *IdxExpr = static_cast<Expr *>(Attr.getArg(0));
    1165               75:   llvm::APSInt Idx(32);
                        0: branch 1 not taken
                       75: branch 2 taken
    1166               75:   if (!IdxExpr->isIntegerConstantExpr(Idx, S.Context)) {
    1167                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
    1168                0:       << "format" << 2 << IdxExpr->getSourceRange();
    1169               16:     return;
    1170                 :   }
    1171                 : 
    1172                 :   // FIXME: We should handle the implicit 'this' parameter in a more generic
    1173                 :   // way that can be used for other arguments.
    1174               75:   bool HasImplicitThisParam = false;
                        6: branch 1 taken
                       69: branch 2 taken
    1175               75:   if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(d)) {
                        5: branch 1 taken
                        1: branch 2 taken
    1176                6:     if (MD->isInstance()) {
    1177                5:       HasImplicitThisParam = true;
    1178                5:       NumArgs++;
    1179                 :     }
    1180                 :   }
    1181                 : 
                       73: branch 1 taken
                        2: branch 2 taken
                        0: branch 4 not taken
                       73: branch 5 taken
                        2: branch 6 taken
                       73: branch 7 taken
    1182               75:   if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) {
    1183                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
    1184                2:       << "format" << 2 << IdxExpr->getSourceRange();
    1185                 :     return;
    1186                 :   }
    1187                 : 
    1188                 :   // FIXME: Do we need to bounds check?
    1189               73:   unsigned ArgIdx = Idx.getZExtValue() - 1;
    1190                 : 
                        5: branch 0 taken
                       68: branch 1 taken
    1191               73:   if (HasImplicitThisParam) {
                        1: branch 0 taken
                        4: branch 1 taken
    1192                5:     if (ArgIdx == 0) {
    1193                 :       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
    1194                1:         << "a string type" << IdxExpr->getSourceRange();
    1195                 :       return;
    1196                 :     }
    1197                4:     ArgIdx--;
    1198                 :   }
    1199                 : 
    1200                 :   // make sure the format string is really a string
    1201               72:   QualType Ty = getFunctionOrMethodArgType(d, ArgIdx);
    1202                 : 
                        2: branch 0 taken
                       70: branch 1 taken
    1203               72:   if (Kind == CFStringFormat) {
                        1: branch 1 taken
                        1: branch 2 taken
    1204                2:     if (!isCFStringType(Ty, S.Context)) {
    1205                 :       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
    1206                1:         << "a CFString" << IdxExpr->getSourceRange();
    1207                 :       return;
    1208                 :     }
                       21: branch 0 taken
                       49: branch 1 taken
    1209               70:   } else if (Kind == NSStringFormat) {
    1210                 :     // FIXME: do we need to check if the type is NSString*?  What are the
    1211                 :     // semantics?
                        1: branch 1 taken
                       20: branch 2 taken
    1212               21:     if (!isNSStringType(Ty, S.Context)) {
    1213                 :       // FIXME: Should highlight the actual expression that has the wrong type.
    1214                 :       S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
    1215                1:         << "an NSString" << IdxExpr->getSourceRange();
    1216                 :       return;
    1217                 :     }
                       43: branch 2 taken
                        6: branch 3 taken
                        0: branch 9 not taken
                       43: branch 10 taken
                        6: branch 11 taken
                       43: branch 12 taken
    1218               49:   } else if (!Ty->isPointerType() ||
    1219                 :              !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) {
    1220                 :     // FIXME: Should highlight the actual expression that has the wrong type.
    1221                 :     S.Diag(Attr.getLoc(), diag::err_format_attribute_not)
    1222                6:       << "a string type" << IdxExpr->getSourceRange();
    1223                 :     return;
    1224                 :   }
    1225                 : 
    1226                 :   // check the 3rd argument
    1227               64:   Expr *FirstArgExpr = static_cast<Expr *>(Attr.getArg(1));
    1228               64:   llvm::APSInt FirstArg(32);
                        0: branch 1 not taken
                       64: branch 2 taken
    1229               64:   if (!FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) {
    1230                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int)
    1231                0:       << "format" << 3 << FirstArgExpr->getSourceRange();
    1232                 :     return;
    1233                 :   }
    1234                 : 
    1235                 :   // check if the function is variadic if the 3rd argument non-zero
                       42: branch 1 taken
                       22: branch 2 taken
    1236               64:   if (FirstArg != 0) {
                       40: branch 1 taken
                        2: branch 2 taken
    1237               42:     if (isFunctionOrMethodVariadic(d)) {
    1238               40:       ++NumArgs; // +1 for ...
    1239                 :     } else {
    1240                2:       S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic);
    1241                 :       return;
    1242                 :     }
    1243                 :   }
    1244                 : 
    1245                 :   // strftime requires FirstArg to be 0 because it doesn't read from any
    1246                 :   // variable the input is just the current time + the format string.
                        2: branch 0 taken
                       60: branch 1 taken
    1247               62:   if (Kind == StrftimeFormat) {
                        1: branch 1 taken
                        1: branch 2 taken
    1248                2:     if (FirstArg != 0) {
    1249                 :       S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)
    1250                1:         << FirstArgExpr->getSourceRange();
    1251                 :       return;
    1252                 :     }
    1253                 :   // if 0 it disables parameter checking (to use with e.g. va_list)
                       39: branch 1 taken
                       21: branch 2 taken
                        2: branch 4 taken
                       37: branch 5 taken
                        2: branch 6 taken
                       58: branch 7 taken
    1254               60:   } else if (FirstArg != 0 && FirstArg != NumArgs) {
    1255                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds)
    1256                2:       << "format" << 3 << FirstArgExpr->getSourceRange();
    1257                 :     return;
    1258                 :   }
    1259                 : 
    1260                 :   d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(),
                       59: branch 3 taken
                        0: branch 4 not taken
                       59: branch 8 taken
                        5: branch 9 taken
                       59: branch 11 taken
                       16: branch 12 taken
    1261               59:                                           FirstArg.getZExtValue()));
    1262                 : }
    1263                 : 
    1264                 : static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr,
    1265                6:                                        Sema &S) {
    1266                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        6: branch 2 taken
    1267                6:   if (Attr.getNumArgs() != 0) {
    1268                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1269                0:     return;
    1270                 :   }
    1271                 : 
    1272                 :   // Try to find the underlying union declaration.
    1273                6:   RecordDecl *RD = 0;
    1274                6:   TypedefDecl *TD = dyn_cast<TypedefDecl>(d);
                        6: branch 0 taken
                        0: branch 1 not taken
                        6: branch 5 taken
                        0: branch 6 not taken
                        6: branch 7 taken
                        0: branch 8 not taken
    1275                6:   if (TD && TD->getUnderlyingType()->isUnionType())
    1276                6:     RD = TD->getUnderlyingType()->getAsUnionType()->getDecl();
    1277                 :   else
    1278                0:     RD = dyn_cast<RecordDecl>(d);
    1279                 : 
                        6: branch 0 taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        6: branch 4 taken
                        0: branch 5 not taken
                        6: branch 6 taken
    1280                6:   if (!RD || !RD->isUnion()) {
    1281                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1282                0:       << Attr.getName() << 1 /*union*/;
    1283                0:     return;
    1284                 :   }
    1285                 : 
                        0: branch 1 not taken
                        6: branch 2 taken
    1286                6:   if (!RD->isDefinition()) {
    1287                 :     S.Diag(Attr.getLoc(),
    1288                0:         diag::warn_transparent_union_attribute_not_definition);
    1289                0:     return;
    1290                 :   }
    1291                 : 
    1292                6:   RecordDecl::field_iterator Field = RD->field_begin(),
    1293                6:                           FieldEnd = RD->field_end();
                        1: branch 1 taken
                        5: branch 2 taken
    1294                6:   if (Field == FieldEnd) {
    1295                1:     S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields);
    1296                1:     return;
    1297                 :   }
    1298                 : 
    1299                5:   FieldDecl *FirstField = *Field;
    1300                5:   QualType FirstType = FirstField->getType();
                        4: branch 2 taken
                        1: branch 3 taken
                        0: branch 6 not taken
                        4: branch 7 taken
                        1: branch 8 taken
                        4: branch 9 taken
    1301                5:   if (FirstType->isFloatingType() || FirstType->isVectorType()) {
    1302                 :     S.Diag(FirstField->getLocation(),
    1303                1:            diag::warn_transparent_union_attribute_floating);
    1304                1:     return;
    1305                 :   }
    1306                 : 
    1307                4:   uint64_t FirstSize = S.Context.getTypeSize(FirstType);
    1308                4:   uint64_t FirstAlign = S.Context.getTypeAlign(FirstType);
                        8: branch 2 taken
                        2: branch 3 taken
    1309               10:   for (; Field != FieldEnd; ++Field) {
    1310                8:     QualType FieldType = Field->getType();
                        7: branch 1 taken
                        1: branch 2 taken
                        1: branch 4 taken
                        6: branch 5 taken
                        2: branch 6 taken
                        6: branch 7 taken
    1311                8:     if (S.Context.getTypeSize(FieldType) != FirstSize ||
    1312                 :         S.Context.getTypeAlign(FieldType) != FirstAlign) {
    1313                 :       // Warn if we drop the attribute.
    1314                2:       bool isSize = S.Context.getTypeSize(FieldType) != FirstSize;
    1315                 :       unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType)
                        1: branch 0 taken
                        1: branch 1 taken
    1316                2:                                  : S.Context.getTypeAlign(FieldType);
    1317                 :       S.Diag(Field->getLocation(),
    1318                 :           diag::warn_transparent_union_attribute_field_size_align)
    1319                2:         << isSize << Field->getDeclName() << FieldBits;
                        1: branch 0 taken
                        1: branch 1 taken
    1320                2:       unsigned FirstBits = isSize? FirstSize : FirstAlign;
    1321                 :       S.Diag(FirstField->getLocation(),
    1322                 :              diag::note_transparent_union_first_field_size_align)
    1323                2:         << isSize << FirstBits;
    1324                2:       return;
    1325                 :     }
    1326                 :   }
    1327                 : 
                        2: branch 1 taken
                        0: branch 2 not taken
    1328                2:   RD->addAttr(::new (S.Context) TransparentUnionAttr());
    1329                 : }
    1330                 : 
    1331                6: static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1332                 :   // check the attribute arguments.
                        1: branch 1 taken
                        5: branch 2 taken
    1333                6:   if (Attr.getNumArgs() != 1) {
    1334                1:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
    1335                1:     return;
    1336                 :   }
    1337                5:   Expr *ArgExpr = static_cast<Expr *>(Attr.getArg(0));
    1338                5:   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
    1339                 : 
    1340                 :   // Make sure that there is a string literal as the annotation's single
    1341                 :   // argument.
                        1: branch 0 taken
                        4: branch 1 taken
    1342                5:   if (!SE) {
    1343                1:     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate";
    1344                1:     return;
    1345                 :   }
                        4: branch 2 taken
                        0: branch 3 not taken
    1346                4:   d->addAttr(::new (S.Context) AnnotateAttr(SE->getString()));
    1347                 : }
    1348                 : 
    1349               53: static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1350                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       53: branch 2 taken
    1351               53:   if (Attr.getNumArgs() > 1) {
    1352                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
    1353                0:     return;
    1354                 :   }
    1355                 :   
    1356                 :   //FIXME: The C++0x version of this attribute has more limited applicabilty
    1357                 :   //       than GNU's, and should error out when it is used to specify a
    1358                 :   //       weaker alignment, rather than being silently ignored.
    1359                 : 
    1360               53:   unsigned Align = 0;
                        2: branch 1 taken
                       51: branch 2 taken
    1361               53:   if (Attr.getNumArgs() == 0) {
    1362                 :     // FIXME: This should be the target specific maximum alignment.
    1363                 :     // (For now we just use 128 bits which is the maximum on X86).
    1364                2:     Align = 128;
                        2: branch 1 taken
                        0: branch 2 not taken
    1365                2:     d->addAttr(::new (S.Context) AlignedAttr(Align));
    1366                2:     return;
    1367                 :   }
    1368                 : 
    1369               51:   Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0));
    1370               51:   llvm::APSInt Alignment(32);
                        1: branch 1 taken
                       50: branch 2 taken
    1371               51:   if (!alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) {
    1372                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
    1373                1:       << "aligned" << alignmentExpr->getSourceRange();
    1374                3:     return;
    1375                 :   }
                        2: branch 2 taken
                       48: branch 3 taken
    1376               50:   if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) {
    1377                 :     S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two)
    1378                2:       << alignmentExpr->getSourceRange();
    1379                 :     return;
    1380                 :   }
    1381                 : 
                       48: branch 2 taken
                        0: branch 3 not taken
                       48: branch 7 taken
                        3: branch 8 taken
    1382               48:   d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8));
    1383                 : }
    1384                 : 
    1385                 : /// HandleModeAttr - This attribute modifies the width of a decl with primitive
    1386                 : /// type.
    1387                 : ///
    1388                 : /// Despite what would be logical, the mode attribute is a decl attribute, not a
    1389                 : /// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be
    1390                 : /// HImode, not an intermediate pointer.
    1391              104: static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
    1392                 :   // This attribute isn't documented, but glibc uses it.  It changes
    1393                 :   // the width of an int or unsigned int to the specified size.
    1394                 : 
    1395                 :   // Check that there aren't any arguments
                        0: branch 1 not taken
                      104: branch 2 taken
    1396              104:   if (Attr.getNumArgs() != 0) {
    1397                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1398                0:     return;
    1399                 :   }
    1400                 : 
    1401              104:   IdentifierInfo *Name = Attr.getParameterName();
                        4: branch 0 taken
                      100: branch 1 taken
    1402              104:   if (!Name) {
    1403                4:     S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
    1404                4:     return;
    1405                 :   }
    1406                 : 
    1407              100:   llvm::StringRef Str = Attr.getParameterName()->getName();
    1408                 : 
    1409                 :   // Normalize the attribute name, __foo__ becomes foo.
                       80: branch 2 taken
                       20: branch 3 taken
                       80: branch 6 taken
                        0: branch 7 not taken
                       80: branch 8 taken
                       20: branch 9 taken
    1410              100:   if (Str.startswith("__") && Str.endswith("__"))
    1411               80:     Str = Str.substr(2, Str.size() - 4);
    1412                 : 
    1413              100:   unsigned DestWidth = 0;
    1414              100:   bool IntegerMode = true;
    1415              100:   bool ComplexMode = false;
                       94: branch 1 taken
                        6: branch 2 taken
                        0: branch 3 not taken
                        0: branch 4 not taken
    1416              100:   switch (Str.size()) {
    1417                 :   case 2:
                       18: branch 1 taken
                       24: branch 2 taken
                       26: branch 3 taken
                       20: branch 4 taken
                        2: branch 5 taken
                        2: branch 6 taken
                        2: branch 7 taken
    1418               94:     switch (Str[0]) {
    1419               18:     case 'Q': DestWidth = 8; break;
    1420               24:     case 'H': DestWidth = 16; break;
    1421               26:     case 'S': DestWidth = 32; break;
    1422               20:     case 'D': DestWidth = 64; break;
    1423                2:     case 'X': DestWidth = 96; break;
    1424                2:     case 'T': DestWidth = 128; break;
    1425                 :     }
                        2: branch 1 taken
                       92: branch 2 taken
    1426               94:     if (Str[1] == 'F') {
    1427                2:       IntegerMode = false;
                        6: branch 1 taken
                       86: branch 2 taken
    1428               92:     } else if (Str[1] == 'C') {
    1429                6:       IntegerMode = false;
    1430                6:       ComplexMode = true;
                        0: branch 1 not taken
                       86: branch 2 taken
    1431               86:     } else if (Str[1] != 'I') {
    1432                0:       DestWidth = 0;
    1433                 :     }
    1434               94:     break;
    1435                 :   case 4:
    1436                 :     // FIXME: glibc uses 'word' to define register_t; this is narrower than a
    1437                 :     // pointer on PIC16 and other embedded platforms.
                        6: branch 2 taken
                        0: branch 3 not taken
    1438                6:     if (Str == "word")
    1439                6:       DestWidth = S.Context.Target.getPointerWidth(0);
                        0: branch 2 not taken
                        0: branch 3 not taken
    1440                0:     else if (Str == "byte")
    1441                0:       DestWidth = S.Context.Target.getCharWidth();
    1442                6:     break;
    1443                 :   case 7:
                        0: branch 2 not taken
                        0: branch 3 not taken
    1444                0:     if (Str == "pointer")
    1445                0:       DestWidth = S.Context.Target.getPointerWidth(0);
    1446                 :     break;
    1447                 :   }
    1448                 : 
    1449              100:   QualType OldTy;
                       98: branch 1 taken
                        2: branch 2 taken
    1450              100:   if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
    1451               98:     OldTy = TD->getUnderlyingType();
                        2: branch 1 taken
                        0: branch 2 not taken
    1452                2:   else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
    1453                2:     OldTy = VD->getType();
    1454                 :   else {
    1455                 :     S.Diag(D->getLocation(), diag::err_attr_wrong_decl)
    1456                0:       << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc());
    1457                0:     return;
    1458                 :   }
    1459                 : 
                       10: branch 2 taken
                       90: branch 3 taken
                        4: branch 6 taken
                        6: branch 7 taken
                        4: branch 8 taken
                       96: branch 9 taken
    1460              100:   if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType())
    1461                4:     S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
                       88: branch 0 taken
                        8: branch 1 taken
    1462               96:   else if (IntegerMode) {
                        2: branch 2 taken
                       86: branch 3 taken
    1463               88:     if (!OldTy->isIntegralType())
    1464                2:       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
                        6: branch 0 taken
                        2: branch 1 taken
    1465                8:   } else if (ComplexMode) {
                        0: branch 2 not taken
                        6: branch 3 taken
    1466                6:     if (!OldTy->isComplexType())
    1467                0:       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
    1468                 :   } else {
                        0: branch 2 not taken
                        2: branch 3 taken
    1469                2:     if (!OldTy->isFloatingType())
    1470                0:       S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
    1471                 :   }
    1472                 : 
    1473                 :   // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
    1474                 :   // and friends, at least with glibc.
    1475                 :   // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong
    1476                 :   // width on unusual platforms.
    1477                 :   // FIXME: Make sure floating-point mappings are accurate
    1478                 :   // FIXME: Support XF and TF types
    1479              100:   QualType NewTy;
                        2: branch 0 taken
                        0: branch 1 not taken
                       18: branch 2 taken
                       24: branch 3 taken
                       32: branch 4 taken
                       20: branch 5 taken
                        2: branch 6 taken
                        2: branch 7 taken
    1480              100:   switch (DestWidth) {
    1481                 :   case 0:
    1482                2:     S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;
    1483                2:     return;
    1484                 :   default:
    1485                0:     S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
    1486                0:     return;
    1487                 :   case 8:
                        0: branch 0 not taken
                       18: branch 1 taken
    1488               18:     if (!IntegerMode) {
    1489                0:       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
    1490                0:       return;
    1491                 :     }
                        8: branch 2 taken
                       10: branch 3 taken
    1492               18:     if (OldTy->isSignedIntegerType())
    1493                8:       NewTy = S.Context.SignedCharTy;
    1494                 :     else
    1495               10:       NewTy = S.Context.UnsignedCharTy;
    1496               18:     break;
    1497                 :   case 16:
                        0: branch 0 not taken
                       24: branch 1 taken
    1498               24:     if (!IntegerMode) {
    1499                0:       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
    1500                0:       return;
    1501                 :     }
                       14: branch 2 taken
                       10: branch 3 taken
    1502               24:     if (OldTy->isSignedIntegerType())
    1503               14:       NewTy = S.Context.ShortTy;
    1504                 :     else
    1505               10:       NewTy = S.Context.UnsignedShortTy;
    1506               24:     break;
    1507                 :   case 32:
                        2: branch 0 taken
                       30: branch 1 taken
    1508               32:     if (!IntegerMode)
    1509                2:       NewTy = S.Context.FloatTy;
                       16: branch 2 taken
                       14: branch 3 taken
    1510               30:     else if (OldTy->isSignedIntegerType())
    1511               16:       NewTy = S.Context.IntTy;
    1512                 :     else
    1513               14:       NewTy = S.Context.UnsignedIntTy;
    1514               32:     break;
    1515                 :   case 64:
                        4: branch 0 taken
                       16: branch 1 taken
    1516               20:     if (!IntegerMode)
    1517                4:       NewTy = S.Context.DoubleTy;
                        8: branch 2 taken
                        8: branch 3 taken
    1518               16:     else if (OldTy->isSignedIntegerType())
                        1: branch 1 taken
                        7: branch 2 taken
    1519                8:       if (S.Context.Target.getLongWidth() == 64)
    1520                1:         NewTy = S.Context.LongTy;
    1521                 :       else
    1522                7:         NewTy = S.Context.LongLongTy;
    1523                 :     else
                        1: branch 1 taken
                        7: branch 2 taken
    1524                8:       if (S.Context.Target.getLongWidth() == 64)
    1525                1:         NewTy = S.Context.UnsignedLongTy;
    1526                 :       else
    1527                7:         NewTy = S.Context.UnsignedLongLongTy;
    1528               20:     break;
    1529                 :   case 96:
    1530                2:     NewTy = S.Context.LongDoubleTy;
    1531                2:     break;
    1532                 :   case 128:
                        0: branch 0 not taken
                        2: branch 1 taken
    1533                2:     if (!IntegerMode) {
    1534                0:       S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;
    1535                0:       return;
    1536                 :     }
                        1: branch 2 taken
                        1: branch 3 taken
    1537                2:     if (OldTy->isSignedIntegerType())
    1538                1:       NewTy = S.Context.Int128Ty;
    1539                 :     else
    1540                1:       NewTy = S.Context.UnsignedInt128Ty;
    1541                 :     break;
    1542                 :   }
    1543                 : 
                        6: branch 0 taken
                       92: branch 1 taken
    1544               98:   if (ComplexMode) {
    1545                6:     NewTy = S.Context.getComplexType(NewTy);
    1546                 :   }
    1547                 : 
    1548                 :   // Install the new type.
                       96: branch 1 taken
                        2: branch 2 taken
    1549               98:   if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
    1550                 :     // FIXME: preserve existing source info.
    1551               96:     TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
    1552                 :   } else
    1553                2:     cast<ValueDecl>(D)->setType(NewTy);
    1554                 : }
    1555                 : 
    1556             1247: static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1557                 :   // check the attribute arguments.
                        1: branch 1 taken
                     1246: branch 2 taken
    1558             1247:   if (Attr.getNumArgs() > 0) {
    1559                1:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1560                1:     return;
    1561                 :   }
    1562                 : 
                        1: branch 1 taken
                     1245: branch 2 taken
    1563             1246:   if (!isFunctionOrMethod(d)) {
    1564                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1565                1:       << Attr.getName() << 0 /*function*/;
    1566                1:     return;
    1567                 :   }
    1568                 : 
                     1245: branch 1 taken
                        0: branch 2 not taken
    1569             1245:   d->addAttr(::new (S.Context) NoDebugAttr());
    1570                 : }
    1571                 : 
    1572               10: static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1573                 :   // check the attribute arguments.
                        1: branch 1 taken
                        9: branch 2 taken
    1574               10:   if (Attr.getNumArgs() != 0) {
    1575                1:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1576                1:     return;
    1577                 :   }
    1578                 : 
                        1: branch 1 taken
                        8: branch 2 taken
    1579                9:   if (!isa<FunctionDecl>(d)) {
    1580                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1581                1:     << Attr.getName() << 0 /*function*/;
    1582                1:     return;
    1583                 :   }
    1584                 : 
                        8: branch 1 taken
                        0: branch 2 not taken
    1585                8:   d->addAttr(::new (S.Context) NoInlineAttr());
    1586                 : }
    1587                 : 
    1588               23: static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1589                 :   // check the attribute arguments.
                        0: branch 1 not taken
                       23: branch 2 taken
    1590               23:   if (Attr.getNumArgs() != 0) {
    1591                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1592                0:     return;
    1593                 :   }
    1594                 : 
    1595               23:   FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
                        0: branch 0 not taken
                       23: branch 1 taken
    1596               23:   if (Fn == 0) {
    1597                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1598                0:       << Attr.getName() << 0 /*function*/;
    1599                0:     return;
    1600                 :   }
    1601                 : 
                        1: branch 1 taken
                       22: branch 2 taken
    1602               23:   if (!Fn->isInlineSpecified()) {
    1603                1:     S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
    1604                1:     return;
    1605                 :   }
    1606                 : 
                       22: branch 1 taken
                        0: branch 2 not taken
    1607               22:   d->addAttr(::new (S.Context) GNUInlineAttr());
    1608                 : }
    1609                 : 
    1610                7: static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1611                 :   // check the attribute arguments.
                        1: branch 1 taken
                        6: branch 2 taken
    1612                7:   if (Attr.getNumArgs() != 1) {
    1613                1:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
    1614                1:     return;
    1615                 :   }
    1616                 : 
                        0: branch 1 not taken
                        6: branch 2 taken
    1617                6:   if (!isFunctionOrMethod(d)) {
    1618                 :     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
    1619                0:     << Attr.getName() << 0 /*function*/;
    1620                0:     return;
    1621                 :   }
    1622                 : 
    1623                6:   Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0));
    1624                6:   llvm::APSInt NumParams(32);
                        1: branch 1 taken
                        5: branch 2 taken
    1625                6:   if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) {
    1626                 :     S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
    1627                1:       << "regparm" << NumParamsExpr->getSourceRange();
    1628                3:     return;
    1629                 :   }
    1630                 : 
                        0: branch 1 not taken
                        5: branch 2 taken
    1631                5:   if (S.Context.Target.getRegParmMax() == 0) {
    1632                 :     S.Diag(Attr.getLoc(), diag::err_attribute_regparm_wrong_platform)
    1633                0:       << NumParamsExpr->getSourceRange();
    1634                 :     return;
    1635                 :   }
    1636                 : 
                        2: branch 2 taken
                        3: branch 3 taken
    1637                5:   if (NumParams.getLimitedValue(255) > S.Context.Target.getRegParmMax()) {
    1638                 :     S.Diag(Attr.getLoc(), diag::err_attribute_regparm_invalid_number)
    1639                2:       << S.Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange();
    1640                 :     return;
    1641                 :   }
    1642                 : 
                        3: branch 2 taken
                        0: branch 3 not taken
                        3: branch 7 taken
                        3: branch 8 taken
    1643                3:   d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue()));
    1644                 : }
    1645                 : 
    1646                3: static void HandleFinalAttr(Decl *d, const AttributeList &Attr, Sema &S) {
    1647                 :   // check the attribute arguments.
                        0: branch 1 not taken
                        3: branch 2 taken
    1648                3:   if (Attr.getNumArgs() != 0) {
    1649                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1650                0:     return;
    1651                 :   }
    1652                 : 
                        2: branch 1 taken
                        1: branch 2 taken
                        1: branch 4 taken
                        1: branch 5 taken
                        0: branch 8 not taken
                        1: branch 9 taken
                        1: branch 10 taken
                        2: branch 11 taken
    1653                3:   if (!isa<CXXRecordDecl>(d)
    1654                 :    && (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual())) {
    1655                 :     S.Diag(Attr.getLoc(),
    1656                 :            Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
    1657                 :                                    : diag::warn_attribute_wrong_decl_type)
                        1: branch 2 taken
                        0: branch 3 not taken
    1658                1:       << Attr.getName() << 7 /*virtual method or class*/;
    1659                1:     return;
    1660                 :   }
    1661                 :   
    1662                 :   // FIXME: Conform to C++0x redeclaration rules.
    1663                 :   
                        0: branch 1 not taken
                        2: branch 2 taken
    1664                2:   if (d->getAttr<FinalAttr>()) {
    1665                0:     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "final";
    1666                0:     return;
    1667                 :   }
    1668                 : 
                        2: branch 1 taken
                        0: branch 2 not taken
    1669                2:   d->addAttr(::new (S.Context) FinalAttr());
    1670                 : }
    1671                 : 
    1672                 : //===----------------------------------------------------------------------===//
    1673                 : // C++0x member checking attributes
    1674                 : //===----------------------------------------------------------------------===//
    1675                 : 
    1676                3: static void HandleBaseCheckAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                        3: branch 2 taken
    1677                3:   if (Attr.getNumArgs() != 0) {
    1678                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1679                0:     return;
    1680                 :   }
    1681                 :   
                        1: branch 1 taken
                        2: branch 2 taken
    1682                3:   if (!isa<CXXRecordDecl>(d)) {
    1683                 :     S.Diag(Attr.getLoc(),
    1684                 :            Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
    1685                 :                                    : diag::warn_attribute_wrong_decl_type)
                        1: branch 2 taken
                        0: branch 3 not taken
    1686                1:       << Attr.getName() << 9 /*class*/;
    1687                1:     return;
    1688                 :   }
    1689                 :   
                        1: branch 1 taken
                        1: branch 2 taken
    1690                2:   if (d->getAttr<BaseCheckAttr>()) {
    1691                1:     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "base_check";
    1692                1:     return;
    1693                 :   }
    1694                 :   
                        1: branch 1 taken
                        0: branch 2 not taken
    1695                1:   d->addAttr(::new (S.Context) BaseCheckAttr());
    1696                 : }
    1697                 : 
    1698                1: static void HandleHidingAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                        1: branch 2 taken
    1699                1:   if (Attr.getNumArgs() != 0) {
    1700                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1701                0:     return;
    1702                 :   }
    1703                 : 
                        1: branch 2 taken
                        0: branch 3 not taken
    1704                1:   if (!isa<RecordDecl>(d->getDeclContext())) {
    1705                 :     // FIXME: It's not the type that's the problem
    1706                 :     S.Diag(Attr.getLoc(),
    1707                 :            Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
    1708                 :                                    : diag::warn_attribute_wrong_decl_type)
                        1: branch 2 taken
                        0: branch 3 not taken
    1709                1:       << Attr.getName() << 11 /*member*/;
    1710                1:     return;
    1711                 :   }
    1712                 : 
    1713                 :   // FIXME: Conform to C++0x redeclaration rules.
    1714                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
    1715                0:   if (d->getAttr<HidingAttr>()) {
    1716                0:     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "hiding";
    1717                0:     return;
    1718                 :   }
    1719                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
    1720                0:   d->addAttr(::new (S.Context) HidingAttr());
    1721                 : }
    1722                 : 
    1723                1: static void HandleOverrideAttr(Decl *d, const AttributeList &Attr, Sema &S) {
                        0: branch 1 not taken
                        1: branch 2 taken
    1724                1:   if (Attr.getNumArgs() != 0) {
    1725                0:     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    1726                0:     return;
    1727                 :   }
    1728                 : 
                        0: branch 1 not taken
                        1: branch 2 taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        1: branch 7 taken
                        0: branch 8 not taken
    1729                1:   if (!isa<CXXMethodDecl>(d) || !cast<CXXMethodDecl>(d)->isVirtual()) {
    1730                 :     // FIXME: It's not the type that's the problem
    1731                 :     S.Diag(Attr.getLoc(),
    1732                 :            Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type
    1733                 :                                    : diag::warn_attribute_wrong_decl_type)
                        1: branch 2 taken
                        0: branch 3 not taken
    1734                1:       << Attr.getName() << 10 /*virtual method*/;
    1735                1:     return;
    1736                 :   }
    1737                 : 
    1738                 :   // FIXME: Conform to C++0x redeclaration rules.
    1739                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
    1740                0:   if (d->getAttr<OverrideAttr>()) {
    1741                0:     S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "override";
    1742                0:     return;
    1743                 :   }
    1744                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
    1745                0:   d->addAttr(::new (S.Context) OverrideAttr());
    1746                 : }
    1747                 : 
    1748                 : //===----------------------------------------------------------------------===//
    1749                 : // Checker-specific attribute handlers.
    1750                 : //===----------------------------------------------------------------------===//
    1751                 : 
    1752                 : static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
    1753               30:                                         Sema &S) {
    1754                 : 
    1755               30:   QualType RetTy;
    1756                 : 
                       22: branch 1 taken
                        8: branch 2 taken
    1757               30:   if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
    1758               22:     RetTy = MD->getResultType();
                        6: branch 1 taken
                        2: branch 2 taken
    1759                8:   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
    1760                6:     RetTy = FD->getResultType();
    1761                 :   else {
    1762                2:     SourceLocation L = Attr.getLoc();
    1763                 :     S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type)
    1764                2:         << SourceRange(L, L) << Attr.getName() << 3 /* function or method */;
    1765                2:     return;
    1766                 :   }
    1767                 : 
                       28: branch 1 taken
                        0: branch 2 not taken
                       20: branch 5 taken
                        8: branch 6 taken
                        2: branch 9 taken
                       18: branch 10 taken
                        2: branch 11 taken
                       26: branch 12 taken
    1768               28:   if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAs<PointerType>()
    1769                 :         || RetTy->getAs<ObjCObjectPointerType>())) {
    1770                2:     SourceLocation L = Attr.getLoc();
    1771                 :     S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
    1772                2:       << SourceRange(L, L) << Attr.getName();
    1773                2:     return;
    1774                 :   }
    1775                 : 
                        0: branch 1 not taken
                       16: branch 2 taken
                       10: branch 3 taken
    1776               26:   switch (Attr.getKind()) {
    1777                 :     default:
    1778                0:       assert(0 && "invalid ownership attribute");
    1779                 :       return;
    1780                 :     case AttributeList::AT_cf_returns_retained:
                       16: branch 1 taken
                        0: branch 2 not taken
    1781               16:       d->addAttr(::new (S.Context) CFReturnsRetainedAttr());
    1782               16:       return;
    1783                 :     case AttributeList::AT_ns_returns_retained:
                       10: branch 1 taken
                        0: branch 2 not taken
    1784               10:       d->addAttr(::new (S.Context) NSReturnsRetainedAttr());
    1785               10:       return;
    1786                 :   };
    1787                 : }
    1788                 : 
    1789                 : //===----------------------------------------------------------------------===//
    1790                 : // Top Level Sema Entry Points
    1791                 : //===----------------------------------------------------------------------===//
    1792                 : 
    1793                 : /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if
    1794                 : /// the attribute applies to decls.  If the attribute is a type attribute, just
    1795                 : /// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to
    1796                 : /// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
    1797                 : static void ProcessDeclAttribute(Scope *scope, Decl *D,
    1798             4890:                                  const AttributeList &Attr, Sema &S) {
                       23: branch 1 taken
                     4867: branch 2 taken
    1799             4890:   if (Attr.isDeclspecAttribute())
    1800                 :     // FIXME: Try to deal with __declspec attributes!
    1801               23:     return;
                        1: branch 1 taken
                      323: branch 2 taken
                       11: branch 3 taken
                       53: branch 4 taken
                     1279: branch 5 taken
                        8: branch 6 taken
                        6: branch 7 taken
                        3: branch 8 taken
                        0: branch 9 not taken
                        8: branch 10 taken
                       46: branch 11 taken
                        7: branch 12 taken
                        6: branch 13 taken
                        7: branch 14 taken
                       65: branch 15 taken
                        3: branch 16 taken
                       75: branch 17 taken
                       18: branch 18 taken
                       23: branch 19 taken
                        1: branch 20 taken
                      104: branch 21 taken
                       46: branch 22 taken
                      409: branch 23 taken
                      105: branch 24 taken
                      457: branch 25 taken
                        1: branch 26 taken
                       30: branch 27 taken
                        0: branch 28 not taken
                       26: branch 29 taken
                       14: branch 30 taken
                        9: branch 31 taken
                       24: branch 32 taken
                       16: branch 33 taken
                       14: branch 34 taken
                       13: branch 35 taken
                       21: branch 36 taken
                       17: branch 37 taken
                        6: branch 38 taken
                        7: branch 39 taken
                       35: branch 40 taken
                        4: branch 41 taken
                      112: branch 42 taken
                       40: branch 43 taken
                       48: branch 44 taken
                       36: branch 45 taken
                       18: branch 46 taken
                     1247: branch 47 taken
                       10: branch 48 taken
                        7: branch 49 taken
                       16: branch 50 taken
                       30: branch 51 taken
                        2: branch 52 taken
    1802             4867:   switch (Attr.getKind()) {
    1803                1:   case AttributeList::AT_IBOutlet:    HandleIBOutletAttr  (D, Attr, S); break;
    1804                 :   case AttributeList::AT_address_space:
    1805                 :   case AttributeList::AT_objc_gc:
    1806                 :   case AttributeList::AT_vector_size:
    1807                 :     // Ignore these, these are type attributes, handled by
    1808                 :     // ProcessTypeAttributes.
    1809              323:     break;
    1810               11:   case AttributeList::AT_alias:       HandleAliasAttr       (D, Attr, S); break;
    1811               53:   case AttributeList::AT_aligned:     HandleAlignedAttr     (D, Attr, S); break;
    1812                 :   case AttributeList::AT_always_inline:
    1813             1279:     HandleAlwaysInlineAttr  (D, Attr, S); break;
    1814                 :   case AttributeList::AT_analyzer_noreturn:
    1815                8:     HandleAnalyzerNoReturnAttr  (D, Attr, S); break;
    1816                6:   case AttributeList::AT_annotate:    HandleAnnotateAttr    (D, Attr, S); break;
    1817                3:   case AttributeList::AT_base_check:  HandleBaseCheckAttr   (D, Attr, S); break;
    1818                 :   case AttributeList::AT_carries_dependency:
    1819                0:                                       HandleDependencyAttr  (D, Attr, S); break;
    1820                8:   case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
    1821               46:   case AttributeList::AT_deprecated:  HandleDeprecatedAttr  (D, Attr, S); break;
    1822                7:   case AttributeList::AT_destructor:  HandleDestructorAttr  (D, Attr, S); break;
    1823                6:   case AttributeList::AT_dllexport:   HandleDLLExportAttr   (D, Attr, S); break;
    1824                7:   case AttributeList::AT_dllimport:   HandleDLLImportAttr   (D, Attr, S); break;
    1825                 :   case AttributeList::AT_ext_vector_type:
    1826               65:     HandleExtVectorTypeAttr(scope, D, Attr, S);
    1827               65:     break;
    1828                3:   case AttributeList::AT_final:       HandleFinalAttr       (D, Attr, S); break;
    1829               75:   case AttributeList::AT_format:      HandleFormatAttr      (D, Attr, S); break;
    1830               18:   case AttributeList::AT_format_arg:  HandleFormatArgAttr   (D, Attr, S); break;
    1831               23:   case AttributeList::AT_gnu_inline:  HandleGNUInlineAttr   (D, Attr, S); break;
    1832                1:   case AttributeList::AT_hiding:      HandleHidingAttr      (D, Attr, S); break;
    1833              104:   case AttributeList::AT_mode:        HandleModeAttr        (D, Attr, S); break;
    1834               46:   case AttributeList::AT_malloc:      HandleMallocAttr      (D, Attr, S); break;
    1835              409:   case AttributeList::AT_nonnull:     HandleNonNullAttr     (D, Attr, S); break;
    1836              105:   case AttributeList::AT_noreturn:    HandleNoReturnAttr    (D, Attr, S); break;
    1837              457:   case AttributeList::AT_nothrow:     HandleNothrowAttr     (D, Attr, S); break;
    1838                1:   case AttributeList::AT_override:    HandleOverrideAttr    (D, Attr, S); break;
    1839                 : 
    1840                 :   // Checker-specific.
    1841                 :   case AttributeList::AT_ns_returns_retained:
    1842                 :   case AttributeList::AT_cf_returns_retained:
    1843               30:     HandleNSReturnsRetainedAttr(D, Attr, S); break;
    1844                 : 
    1845                 :   case AttributeList::AT_reqd_wg_size:
    1846                0:     HandleReqdWorkGroupSize(D, Attr, S); break;
    1847                 : 
    1848               26:   case AttributeList::AT_packed:      HandlePackedAttr      (D, Attr, S); break;
    1849               14:   case AttributeList::AT_section:     HandleSectionAttr     (D, Attr, S); break;
    1850                9:   case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break;
    1851               24:   case AttributeList::AT_unused:      HandleUnusedAttr      (D, Attr, S); break;
    1852               16:   case AttributeList::AT_used:        HandleUsedAttr        (D, Attr, S); break;
    1853               14:   case AttributeList::AT_visibility:  HandleVisibilityAttr  (D, Attr, S); break;
    1854               13:   case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
    1855               13:     break;
    1856               21:   case AttributeList::AT_weak:        HandleWeakAttr        (D, Attr, S); break;
    1857               17:   case AttributeList::AT_weak_import: HandleWeakImportAttr  (D, Attr, S); break;
    1858                 :   case AttributeList::AT_transparent_union:
    1859                6:     HandleTransparentUnionAttr(D, Attr, S);
    1860                6:     break;
    1861                 :   case AttributeList::AT_objc_exception:
    1862                7:     HandleObjCExceptionAttr(D, Attr, S);
    1863                7:     break;
    1864               35:   case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break;
    1865                4:   case AttributeList::AT_nsobject:    HandleObjCNSObject    (D, Attr, S); break;
    1866              112:   case AttributeList::AT_blocks:      HandleBlocksAttr      (D, Attr, S); break;
    1867               40:   case AttributeList::AT_sentinel:    HandleSentinelAttr    (D, Attr, S); break;
    1868               48:   case AttributeList::AT_const:       HandleConstAttr       (D, Attr, S); break;
    1869               36:   case AttributeList::AT_pure:        HandlePureAttr        (D, Attr, S); break;
    1870               18:   case AttributeList::AT_cleanup:     HandleCleanupAttr     (D, Attr, S); break;
    1871             1247:   case AttributeList::AT_nodebug:     HandleNoDebugAttr     (D, Attr, S); break;
    1872               10:   case AttributeList::AT_noinline:    HandleNoInlineAttr    (D, Attr, S); break;
    1873                7:   case AttributeList::AT_regparm:     HandleRegparmAttr     (D, Attr, S); break;
    1874                 :   case AttributeList::IgnoredAttribute:
    1875                 :   case AttributeList::AT_no_instrument_function:  // Interacts with -pg.
    1876                 :     // Just ignore
    1877               16:     break;
    1878                 :   case AttributeList::AT_stdcall:
    1879                 :   case AttributeList::AT_cdecl:
    1880                 :   case AttributeList::AT_fastcall:
    1881                 :     // These are all treated as type attributes.
    1882               30:     break;
    1883                 :   default:
    1884                 :     // Ask target about the attribute.
    1885                2:     const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema();
                        2: branch 1 taken
                        0: branch 2 not taken
    1886                2:     if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S))
    1887                2:       S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
    1888                 :     break;
    1889                 :   }
    1890                 : }
    1891                 : 
    1892                 : /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
    1893                 : /// attribute list to the specified decl, ignoring any type attributes.
    1894             5715: void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
                     4890: branch 0 taken
                     5715: branch 1 taken
    1895            16320:   while (AttrList) {
    1896             4890:     ProcessDeclAttribute(S, D, *AttrList, *this);
    1897             4890:     AttrList = AttrList->getNext();
    1898                 :   }
    1899             5715: }
    1900                 : 
    1901                 : /// DeclClonePragmaWeak - clone existing decl (maybe definition),
    1902                 : /// #pragma weak needs a non-definition decl and source may not have one
    1903               15: NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {
                        1: branch 1 taken
                       14: branch 2 taken
                        0: branch 4 not taken
                        1: branch 5 taken
    1904               15:   assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND));
    1905               15:   NamedDecl *NewD = 0;
                       14: branch 1 taken
                        1: branch 2 taken
    1906               15:   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
    1907                 :     NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),
    1908                 :                                 FD->getLocation(), DeclarationName(II),
    1909               14:                                 FD->getType(), FD->getTypeSourceInfo());
                        1: branch 1 taken
                        0: branch 2 not taken
    1910                1:   } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {
    1911                 :     NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),
    1912                 :                            VD->getLocation(), II,
    1913                 :                            VD->getType(), VD->getTypeSourceInfo(),
    1914                1:                            VD->getStorageClass());
    1915                 :   }
    1916               15:   return NewD;
    1917                 : }
    1918                 : 
    1919                 : /// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak
    1920                 : /// applied to it, possibly with an alias.
    1921               21: void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) {
                       19: branch 1 taken
                        2: branch 2 taken
    1922               21:   if (W.getUsed()) return; // only do this once
    1923               19:   W.setUsed(true);
                       15: branch 1 taken
                        4: branch 2 taken
    1924               19:   if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...))
    1925               15:     IdentifierInfo *NDId = ND->getIdentifier();
    1926               15:     NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias());
                       15: branch 2 taken
                        0: branch 3 not taken
    1927               15:     NewD->addAttr(::new (Context) AliasAttr(NDId->getName()));
                       15: branch 1 taken
                        0: branch 2 not taken
    1928               15:     NewD->addAttr(::new (Context) WeakAttr());
    1929               15:     WeakTopLevelDecl.push_back(NewD);
    1930                 :     // FIXME: "hideous" code from Sema::LazilyCreateBuiltin
    1931                 :     // to insert Decl at TU scope, sorry.
    1932               15:     DeclContext *SavedContext = CurContext;
                       15: branch 1 taken
                        0: branch 2 not taken
    1933               15:     CurContext = Context.getTranslationUnitDecl();
    1934               15:     PushOnScopeChains(NewD, S);
    1935               15:     CurContext = SavedContext;
    1936                 :   } else { // just add weak to existing
                        4: branch 1 taken
                        0: branch 2 not taken
    1937                4:     ND->addAttr(::new (Context) WeakAttr());
    1938                 :   }
    1939                 : }
    1940                 : 
    1941                 : /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
    1942                 : /// it, apply them to D.  This is a bit tricky because PD can have attributes
    1943                 : /// specified in many different places, and we need to find and apply them all.
    1944            49447: void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
    1945                 :   // Handle #pragma weak
                    49184: branch 1 taken
                      263: branch 2 taken
    1946            49447:   if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
                    30680: branch 1 taken
                    18504: branch 2 taken
    1947            49184:     if (ND->hasLinkage()) {
    1948            30680:       WeakInfo W = WeakUndeclaredIdentifiers.lookup(ND->getIdentifier());
                       12: branch 2 taken
                    30668: branch 3 taken
    1949            30680:       if (W != WeakInfo()) {
    1950                 :         // Identifier referenced by #pragma weak before it was declared
    1951               12:         DeclApplyPragmaWeak(S, ND, W);
    1952               12:         WeakUndeclaredIdentifiers[ND->getIdentifier()] = W;
    1953                 :       }
    1954                 :     }
    1955                 :   }
    1956                 : 
    1957                 :   // Apply decl attributes from the DeclSpec if present.
                     1744: branch 2 taken
                    47703: branch 3 taken
    1958            49447:   if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
    1959             1744:     ProcessDeclAttributeList(S, D, Attrs);
    1960                 : 
    1961                 :   // Walk the declarator structure, applying decl attributes that were in a type
    1962                 :   // position to the decl itself.  This handles cases like:
    1963                 :   //   int *__attr__(x)** D;
    1964                 :   // when X is a decl attribute.
                    30208: branch 1 taken
                    49447: branch 2 taken
    1965            79655:   for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)
                       31: branch 2 taken
                    30177: branch 3 taken
    1966            30208:     if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs())
    1967               31:       ProcessDeclAttributeList(S, D, Attrs);
    1968                 : 
    1969                 :   // Finally, apply any attributes on the decl itself.
                     1386: branch 1 taken
                    48061: branch 2 taken
    1970            49447:   if (const AttributeList *Attrs = PD.getAttributes())
    1971             1386:     ProcessDeclAttributeList(S, D, Attrs);
    1972            49447: }
    1973                 : 
    1974                 : /// PushParsingDeclaration - Enter a new "scope" of deprecation
    1975                 : /// warnings.
    1976                 : ///
    1977                 : /// The state token we use is the start index of this scope
    1978                 : /// on the warning stack.
    1979            74476: Action::ParsingDeclStackState Sema::PushParsingDeclaration() {
    1980            74476:   ParsingDeclDepth++;
    1981            74476:   return (ParsingDeclStackState) DelayedDiagnostics.size();
    1982                 : }
    1983                 : 
    1984            74476: void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) {
                        0: branch 0 not taken
                    74476: branch 1 taken
    1985            74476:   assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack");
    1986            74476:   ParsingDeclDepth--;
    1987                 : 
                    74434: branch 1 taken
                       42: branch 2 taken
    1988            74476:   if (DelayedDiagnostics.empty())
    1989            74434:     return;
    1990                 : 
    1991               42:   unsigned SavedIndex = (unsigned) S;
    1992                 :   assert(SavedIndex <= DelayedDiagnostics.size() &&
                       42: branch 1 taken
                        0: branch 2 not taken
    1993               42:          "saved index is out of bounds");
    1994                 : 
    1995                 :   // We only want to actually emit delayed diagnostics when we
    1996                 :   // successfully parsed a decl.
                       30: branch 1 taken
                       12: branch 2 taken
    1997               72:   Decl *D = Ctx ? Ctx.getAs<Decl>() : 0;
                       30: branch 0 taken
                       12: branch 1 taken
    1998               42:   if (D) {
    1999                 :     // We really do want to start with 0 here.  We get one push for a
    2000                 :     // decl spec and another for each declarator;  in a decl group like:
    2001                 :     //   deprecated_typedef foo, *bar, baz();
    2002                 :     // only the declarator pops will be passed decls.  This is correct;
    2003                 :     // we really do need to consider delayed diagnostics from the decl spec
    2004                 :     // for each of the different declarations.
                       33: branch 1 taken
                       30: branch 2 taken
    2005               63:     for (unsigned I = 0, E = DelayedDiagnostics.size(); I != E; ++I) {
                        2: branch 1 taken
                       31: branch 2 taken
    2006               33:       if (DelayedDiagnostics[I].Triggered)
    2007                2:         continue;
    2008                 : 
                       25: branch 1 taken
                        6: branch 2 taken
                        0: branch 3 not taken
    2009               31:       switch (DelayedDiagnostics[I].Kind) {
    2010                 :       case DelayedDiagnostic::Deprecation:
    2011               25:         HandleDelayedDeprecationCheck(DelayedDiagnostics[I], D);
    2012               25:         break;
    2013                 : 
    2014                 :       case DelayedDiagnostic::Access:
    2015                6:         HandleDelayedAccessCheck(DelayedDiagnostics[I], D);
    2016                 :         break;
    2017                 :       }
    2018                 :     }
    2019                 :   }
    2020                 : 
    2021               42:   DelayedDiagnostics.set_size(SavedIndex);
    2022                 : }
    2023                 : 
    2024              133: static bool isDeclDeprecated(Decl *D) {
                       60: branch 2 taken
                       51: branch 3 taken
    2025              111:   do {
                       22: branch 1 taken
                      111: branch 2 taken
    2026              133:     if (D->hasAttr<DeprecatedAttr>())
    2027               22:       return true;
    2028                 :   } while ((D = cast_or_null<Decl>(D->getDeclContext())));
    2029               51:   return false;
    2030                 : }
    2031                 : 
    2032                 : void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD,
    2033               25:                                          Decl *Ctx) {
                       11: branch 1 taken
                       14: branch 2 taken
    2034               25:   if (isDeclDeprecated(Ctx))
    2035               11:     return;
    2036                 : 
    2037               14:   DD.Triggered = true;
    2038                 :   Diag(DD.Loc, diag::warn_deprecated)
    2039               14:     << DD.DeprecationData.Decl->getDeclName();
    2040                 : }
    2041                 : 
    2042               73: void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) {
    2043                 :   // Delay if we're currently parsing a declaration.
                       25: branch 0 taken
                       48: branch 1 taken
    2044               73:   if (ParsingDeclDepth) {
    2045               25:     DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D));
    2046               25:     return;
    2047                 :   }
    2048                 : 
    2049                 :   // Otherwise, don't warn if our current context is deprecated.
                       11: branch 2 taken
                       37: branch 3 taken
    2050               48:   if (isDeclDeprecated(cast<Decl>(CurContext)))
    2051               11:     return;
    2052                 : 
    2053               37:   Diag(Loc, diag::warn_deprecated) << D->getDeclName();
    2054                 : }

Generated: 2010-02-10 01:31 by zcov