diff options
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
| -rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 1965 | 
1 files changed, 943 insertions, 1022 deletions
| diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 7b3345a332179..3e583862092c5 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -23,6 +23,7 @@  #include "clang/Basic/CharInfo.h"  #include "clang/Basic/SourceManager.h"  #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h"  #include "clang/Sema/DeclSpec.h"  #include "clang/Sema/DelayedDiagnostic.h"  #include "clang/Sema/Lookup.h" @@ -52,7 +53,11 @@ enum AttributeDeclKind {    ExpectedTLSVar,    ExpectedVariableOrField,    ExpectedVariableFieldOrTag, -  ExpectedTypeOrNamespace +  ExpectedTypeOrNamespace, +  ExpectedObjectiveCInterface, +  ExpectedMethodOrProperty, +  ExpectedStructOrUnion, +  ExpectedStructOrUnionOrClass  };  //===----------------------------------------------------------------------===// @@ -204,12 +209,18 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {    return RD->getIdentifier() == &Ctx.Idents.get("__CFString");  } +static unsigned getNumAttributeArgs(const AttributeList &Attr) { +  // FIXME: Include the type in the argument list. +  return Attr.getNumArgs() + Attr.hasParsedType(); +} +  /// \brief Check if the attribute has exactly as many args as Num. May  /// output an error.  static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, -                                  unsigned int Num) { -  if (Attr.getNumArgs() != Num) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; +                                  unsigned Num) { +  if (getNumAttributeArgs(Attr) != Num) { +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +      << Attr.getName() << Num;      return false;    } @@ -220,8 +231,8 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr,  /// \brief Check if the attribute has at least as many args as Num. May  /// output an error.  static bool checkAttributeAtLeastNumArgs(Sema &S, const AttributeList &Attr, -                                  unsigned int Num) { -  if (Attr.getNumArgs() < Num) { +                                         unsigned Num) { +  if (getNumAttributeArgs(Attr) < Num) {      S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num;      return false;    } @@ -240,24 +251,27 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,                                                 const Expr *IdxExpr,                                                 uint64_t &Idx)  { -  assert(isFunctionOrMethod(D) && hasFunctionProto(D)); +  assert(isFunctionOrMethod(D));    // In C++ the implicit 'this' function parameter also counts.    // Parameters are counted from one. -  const bool HasImplicitThisParam = isInstanceMethod(D); -  const unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; -  const unsigned FirstIdx = 1; +  bool HP = hasFunctionProto(D); +  bool HasImplicitThisParam = isInstanceMethod(D); +  bool IV = HP && isFunctionOrMethodVariadic(D); +  unsigned NumArgs = (HP ? getFunctionOrMethodNumArgs(D) : 0) + +                     HasImplicitThisParam;    llvm::APSInt IdxInt;    if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||        !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { -    S.Diag(AttrLoc, diag::err_attribute_argument_n_not_int) -      << AttrName << AttrArgNum << IdxExpr->getSourceRange(); +    std::string Name = std::string("'") + AttrName.str() + std::string("'"); +    S.Diag(AttrLoc, diag::err_attribute_argument_n_type) << Name.c_str() +      << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange();      return false;    }    Idx = IdxInt.getLimitedValue(); -  if (Idx < FirstIdx || (!isFunctionOrMethodVariadic(D) && Idx > NumArgs)) { +  if (Idx < 1 || (!IV && Idx > NumArgs)) {      S.Diag(AttrLoc, diag::err_attribute_argument_out_of_bounds)        << AttrName << AttrArgNum << IdxExpr->getSourceRange();      return false; @@ -276,6 +290,42 @@ static bool checkFunctionOrMethodArgumentIndex(Sema &S, const Decl *D,    return true;  } +/// \brief Check if the argument \p ArgNum of \p Attr is a ASCII string literal. +/// If not emit an error and return false. If the argument is an identifier it +/// will emit an error with a fixit hint and treat it as if it was a string +/// literal. +bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr, +                                          unsigned ArgNum, StringRef &Str, +                                          SourceLocation *ArgLocation) { +  // Look for identifiers. If we have one emit a hint to fix it to a literal. +  if (Attr.isArgIdent(ArgNum)) { +    IdentifierLoc *Loc = Attr.getArgAsIdent(ArgNum); +    Diag(Loc->Loc, diag::err_attribute_argument_type) +        << Attr.getName() << AANT_ArgumentString +        << FixItHint::CreateInsertion(Loc->Loc, "\"") +        << FixItHint::CreateInsertion(PP.getLocForEndOfToken(Loc->Loc), "\""); +    Str = Loc->Ident->getName(); +    if (ArgLocation) +      *ArgLocation = Loc->Loc; +    return true; +  } + +  // Now check for an actual string literal. +  Expr *ArgExpr = Attr.getArgAsExpr(ArgNum); +  StringLiteral *Literal = dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); +  if (ArgLocation) +    *ArgLocation = ArgExpr->getLocStart(); + +  if (!Literal || !Literal->isAscii()) { +    Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) +        << Attr.getName() << AANT_ArgumentString; +    return false; +  } + +  Str = Literal->getString(); +  return true; +} +  ///  /// \brief Check if passed in Decl is a field or potentially shared global var  /// \return true if the Decl is a field or potentially shared global variable @@ -414,7 +464,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,                                           int Sidx = 0,                                           bool ParamIdxOk = false) {    for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) { -    Expr *ArgExp = Attr.getArg(Idx); +    Expr *ArgExp = Attr.getArgAsExpr(Idx);      if (ArgExp->isTypeDependent()) {        // FIXME -- need to check this again on template instantiation @@ -424,7 +474,7 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D,      if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) {        if (StrLit->getLength() == 0 || -          StrLit->getString() == StringRef("*")) { +          (StrLit->isAscii() && StrLit->getString() == StringRef("*"))) {          // Pass empty strings to the analyzer without warnings.          // Treat "*" as the universal lock.          Args.push_back(ArgExp); @@ -492,11 +542,6 @@ enum ThreadAttributeDeclKind {  static bool checkGuardedVarAttrCommon(Sema &S, Decl *D,                                        const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return false; -    // D must be either a member field or global (potentially shared) variable.    if (!mayBeSharedVariable(D)) {      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) @@ -532,11 +577,6 @@ static void handlePtGuardedVarAttr(Sema &S, Decl *D,  static bool checkGuardedByAttrCommon(Sema &S, Decl *D,                                       const AttributeList &Attr,                                       Expr* &Arg) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 1)) -    return false; -    // D must be either a member field or global (potentially shared) variable.    if (!mayBeSharedVariable(D)) {      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) @@ -579,13 +619,8 @@ static void handlePtGuardedByAttr(Sema &S, Decl *D,  static bool checkLockableAttrCommon(Sema &S, Decl *D,                                      const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return false; -    // FIXME: Lockable structs for C code. -  if (!isa<CXXRecordDecl>(D)) { +  if (!isa<RecordDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)        << Attr.getName() << ThreadExpectedClassOrStruct;      return false; @@ -613,11 +648,6 @@ static void handleScopedLockableAttr(Sema &S, Decl *D,  static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,                                           const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)        << Attr.getName() << ThreadExpectedFunctionOrMethod; @@ -630,11 +660,6 @@ static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,  static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,                                        const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunctionOrMethod; @@ -648,11 +673,6 @@ static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,  static void handleNoSanitizeMemory(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunctionOrMethod; @@ -665,11 +685,6 @@ static void handleNoSanitizeMemory(Sema &S, Decl *D,  static void handleNoSanitizeThread(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunctionOrMethod; @@ -682,9 +697,7 @@ static void handleNoSanitizeThread(Sema &S, Decl *D,  static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D,                                          const AttributeList &Attr, -                                        SmallVector<Expr*, 1> &Args) { -  assert(!Attr.isInvalid()); - +                                        SmallVectorImpl<Expr *> &Args) {    if (!checkAttributeAtLeastNumArgs(S, Attr, 1))      return false; @@ -743,9 +756,7 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D,  static bool checkLockFunAttrCommon(Sema &S, Decl *D,                                     const AttributeList &Attr, -                                   SmallVector<Expr*, 1> &Args) { -  assert(!Attr.isInvalid()); - +                                   SmallVectorImpl<Expr *> &Args) {    // zero or more arguments ok    // check that the attribute is applied to a function @@ -788,11 +799,37 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D,                                         Attr.getAttributeSpellingListIndex()));  } +static void handleAssertSharedLockAttr(Sema &S, Decl *D, +                                       const AttributeList &Attr) { +  SmallVector<Expr*, 1> Args; +  if (!checkLockFunAttrCommon(S, D, Attr, Args)) +    return; + +  unsigned Size = Args.size(); +  Expr **StartArg = Size == 0 ? 0 : &Args[0]; +  D->addAttr(::new (S.Context) +             AssertSharedLockAttr(Attr.getRange(), S.Context, StartArg, Size, +                                  Attr.getAttributeSpellingListIndex())); +} + +static void handleAssertExclusiveLockAttr(Sema &S, Decl *D, +                                          const AttributeList &Attr) { +  SmallVector<Expr*, 1> Args; +  if (!checkLockFunAttrCommon(S, D, Attr, Args)) +    return; + +  unsigned Size = Args.size(); +  Expr **StartArg = Size == 0 ? 0 : &Args[0]; +  D->addAttr(::new (S.Context) +             AssertExclusiveLockAttr(Attr.getRange(), S.Context, +                                     StartArg, Size, +                                     Attr.getAttributeSpellingListIndex())); +} + +  static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,                                        const AttributeList &Attr, -                                      SmallVector<Expr*, 2> &Args) { -  assert(!Attr.isInvalid()); - +                                      SmallVectorImpl<Expr *> &Args) {    if (!checkAttributeAtLeastNumArgs(S, Attr, 1))      return false; @@ -802,9 +839,9 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,      return false;    } -  if (!isIntOrBool(Attr.getArg(0))) { -    S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool) -      << Attr.getName(); +  if (!isIntOrBool(Attr.getArgAsExpr(0))) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 1 << AANT_ArgumentIntOrBool;      return false;    } @@ -820,11 +857,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D,    if (!checkTryLockFunAttrCommon(S, D, Attr, Args))      return; -  unsigned Size = Args.size(); -  Expr **StartArg = Size == 0 ? 0 : &Args[0];    D->addAttr(::new (S.Context)               SharedTrylockFunctionAttr(Attr.getRange(), S.Context, -                                       Attr.getArg(0), StartArg, Size, +                                       Attr.getArgAsExpr(0), +                                       Args.data(), Args.size(),                                         Attr.getAttributeSpellingListIndex()));  } @@ -834,19 +870,16 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D,    if (!checkTryLockFunAttrCommon(S, D, Attr, Args))      return; -  unsigned Size = Args.size(); -  Expr **StartArg = Size == 0 ? 0 : &Args[0];    D->addAttr(::new (S.Context)               ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, -                                          Attr.getArg(0), StartArg, Size, +                                          Attr.getArgAsExpr(0), +                                          Args.data(), Args.size(),                                            Attr.getAttributeSpellingListIndex()));  }  static bool checkLocksRequiredCommon(Sema &S, Decl *D,                                       const AttributeList &Attr, -                                     SmallVector<Expr*, 1> &Args) { -  assert(!Attr.isInvalid()); - +                                     SmallVectorImpl<Expr *> &Args) {    if (!checkAttributeAtLeastNumArgs(S, Attr, 1))      return false; @@ -892,8 +925,6 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,  static void handleUnlockFunAttr(Sema &S, Decl *D,                                  const AttributeList &Attr) { -  assert(!Attr.isInvalid()); -    // zero or more arguments ok    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { @@ -915,11 +946,6 @@ static void handleUnlockFunAttr(Sema &S, Decl *D,  static void handleLockReturnedAttr(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  assert(!Attr.isInvalid()); - -  if (!checkAttributeNumArgs(S, Attr, 1)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type)        << Attr.getName() << ThreadExpectedFunctionOrMethod; @@ -940,8 +966,6 @@ static void handleLockReturnedAttr(Sema &S, Decl *D,  static void handleLocksExcludedAttr(Sema &S, Decl *D,                                      const AttributeList &Attr) { -  assert(!Attr.isInvalid()); -    if (!checkAttributeAtLeastNumArgs(S, Attr, 1))      return; @@ -964,6 +988,260 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,                                 Attr.getAttributeSpellingListIndex()));  } +static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) { +  ConsumableAttr::ConsumedState DefaultState; + +  if (Attr.isArgIdent(0)) { +    IdentifierLoc *IL = Attr.getArgAsIdent(0); +    if (!ConsumableAttr::ConvertStrToConsumedState(IL->Ident->getName(), +                                                   DefaultState)) { +      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << IL->Ident; +      return; +    } +  } else { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) +        << Attr.getName() << AANT_ArgumentIdentifier; +    return; +  } + +  if (!isa<CXXRecordDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedClass; +    return; +  } +   +  D->addAttr(::new (S.Context) +             ConsumableAttr(Attr.getRange(), S.Context, DefaultState, +                            Attr.getAttributeSpellingListIndex())); +} + +static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, +                                        const AttributeList &Attr) { +  ASTContext &CurrContext = S.getASTContext(); +  QualType ThisType = MD->getThisType(CurrContext)->getPointeeType(); +   +  if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) { +    if (!RD->hasAttr<ConsumableAttr>()) { +      S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) << +        RD->getNameAsString(); +       +      return false; +    } +  } +   +  return true; +} + + +static void handleCallableWhenAttr(Sema &S, Decl *D, +                                   const AttributeList &Attr) { +  if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) +    return; + +  if (!isa<CXXMethodDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedMethod; +    return; +  } +   +  if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) +    return; +   +  SmallVector<CallableWhenAttr::ConsumedState, 3> States; +  for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) { +    CallableWhenAttr::ConsumedState CallableState; +     +    StringRef StateString; +    SourceLocation Loc; +    if (!S.checkStringLiteralArgumentAttr(Attr, ArgIndex, StateString, &Loc)) +      return; + +    if (!CallableWhenAttr::ConvertStrToConsumedState(StateString, +                                                     CallableState)) { +      S.Diag(Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << StateString; +      return; +    } +       +    States.push_back(CallableState); +  } +   +  D->addAttr(::new (S.Context) +             CallableWhenAttr(Attr.getRange(), S.Context, States.data(), +               States.size(), Attr.getAttributeSpellingListIndex())); +} + + +static void handleParamTypestateAttr(Sema &S, Decl *D, +                                    const AttributeList &Attr) { +  if (!checkAttributeNumArgs(S, Attr, 1)) return; +   +  if (!isa<ParmVarDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedParameter; +    return; +  } +   +  ParamTypestateAttr::ConsumedState ParamState; +   +  if (Attr.isArgIdent(0)) { +    IdentifierLoc *Ident = Attr.getArgAsIdent(0); +    StringRef StateString = Ident->Ident->getName(); + +    if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString, +                                                       ParamState)) { +      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << StateString; +      return; +    } +  } else { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << +      Attr.getName() << AANT_ArgumentIdentifier; +    return; +  } +   +  // FIXME: This check is currently being done in the analysis.  It can be +  //        enabled here only after the parser propagates attributes at +  //        template specialization definition, not declaration. +  //QualType ReturnType = cast<ParmVarDecl>(D)->getType(); +  //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); +  // +  //if (!RD || !RD->hasAttr<ConsumableAttr>()) { +  //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << +  //      ReturnType.getAsString(); +  //    return; +  //} +   +  D->addAttr(::new (S.Context) +             ParamTypestateAttr(Attr.getRange(), S.Context, ParamState, +                                Attr.getAttributeSpellingListIndex())); +} + + +static void handleReturnTypestateAttr(Sema &S, Decl *D, +                                      const AttributeList &Attr) { +  if (!checkAttributeNumArgs(S, Attr, 1)) return; +   +  if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedFunctionMethodOrParameter; +    return; +  } + +  ReturnTypestateAttr::ConsumedState ReturnState; +   +  if (Attr.isArgIdent(0)) { +    IdentifierLoc *IL = Attr.getArgAsIdent(0); +    if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(), +                                                        ReturnState)) { +      S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << IL->Ident; +      return; +    } +  } else { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << +      Attr.getName() << AANT_ArgumentIdentifier; +    return; +  } +   +  // FIXME: This check is currently being done in the analysis.  It can be +  //        enabled here only after the parser propagates attributes at +  //        template specialization definition, not declaration. +  //QualType ReturnType; +  // +  //if (const ParmVarDecl *Param = dyn_cast<ParmVarDecl>(D)) { +  //  ReturnType = Param->getType(); +  // +  //} else if (const CXXConstructorDecl *Constructor = +  //             dyn_cast<CXXConstructorDecl>(D)) { +  //  ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType(); +  //   +  //} else { +  //   +  //  ReturnType = cast<FunctionDecl>(D)->getCallResultType(); +  //} +  // +  //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl(); +  // +  //if (!RD || !RD->hasAttr<ConsumableAttr>()) { +  //    S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) << +  //      ReturnType.getAsString(); +  //    return; +  //} +   +  D->addAttr(::new (S.Context) +             ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState, +                                 Attr.getAttributeSpellingListIndex())); +} + + +static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) { +  if (!checkAttributeNumArgs(S, Attr, 1)) +    return; + +  if (!isa<CXXMethodDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedMethod; +    return; +  } +   +  if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) +    return; +   +  SetTypestateAttr::ConsumedState NewState; +  if (Attr.isArgIdent(0)) { +    IdentifierLoc *Ident = Attr.getArgAsIdent(0); +    StringRef Param = Ident->Ident->getName(); +    if (!SetTypestateAttr::ConvertStrToConsumedState(Param, NewState)) { +      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << Param; +      return; +    } +  } else { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << +      Attr.getName() << AANT_ArgumentIdentifier; +    return; +  } +   +  D->addAttr(::new (S.Context) +             SetTypestateAttr(Attr.getRange(), S.Context, NewState, +                              Attr.getAttributeSpellingListIndex())); +} + +static void handleTestTypestateAttr(Sema &S, Decl *D, +                                    const AttributeList &Attr) { +  if (!checkAttributeNumArgs(S, Attr, 1)) +    return; +   +  if (!isa<CXXMethodDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << +      Attr.getName() << ExpectedMethod; +    return; +  } +   +  if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr)) +    return; +   +  TestTypestateAttr::ConsumedState TestState;   +  if (Attr.isArgIdent(0)) { +    IdentifierLoc *Ident = Attr.getArgAsIdent(0); +    StringRef Param = Ident->Ident->getName(); +    if (!TestTypestateAttr::ConvertStrToConsumedState(Param, TestState)) { +      S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported) +        << Attr.getName() << Param; +      return; +    } +  } else { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << +      Attr.getName() << AANT_ArgumentIdentifier; +    return; +  } +   +  D->addAttr(::new (S.Context) +             TestTypestateAttr(Attr.getRange(), S.Context, TestState, +                                Attr.getAttributeSpellingListIndex())); +}  static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,                                      const AttributeList &Attr) { @@ -980,10 +1258,6 @@ static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,  }  static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (TagDecl *TD = dyn_cast<TagDecl>(D))      TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context));    else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { @@ -1012,10 +1286,6 @@ static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    // The IBAction attributes only apply to instance methods.    if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))      if (MD->isInstanceMethod()) { @@ -1055,10 +1325,6 @@ static bool checkIBOutletCommon(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -      if (!checkIBOutletCommon(S, D, Attr))      return; @@ -1071,36 +1337,46 @@ static void handleIBOutletCollection(Sema &S, Decl *D,                                       const AttributeList &Attr) {    // The iboutletcollection attribute can have zero or one arguments. -  if (Attr.getParameterName() && Attr.getNumArgs() > 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +  if (Attr.getNumArgs() > 1) { +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +      << Attr.getName() << 1;      return;    }    if (!checkIBOutletCommon(S, D, Attr))      return; -  IdentifierInfo *II = Attr.getParameterName(); -  if (!II) -    II = &S.Context.Idents.get("NSObject"); -   -  ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(),  -                        S.getScopeForContext(D->getDeclContext()->getParent())); -  if (!TypeRep) { -    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; -    return; +  ParsedType PT; + +  if (Attr.hasParsedType()) +    PT = Attr.getTypeArg(); +  else { +    PT = S.getTypeName(S.Context.Idents.get("NSObject"), Attr.getLoc(), +                       S.getScopeForContext(D->getDeclContext()->getParent())); +    if (!PT) { +      S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << "NSObject"; +      return; +    }    } -  QualType QT = TypeRep.get(); + +  TypeSourceInfo *QTLoc = 0; +  QualType QT = S.GetTypeFromParser(PT, &QTLoc); +  if (!QTLoc) +    QTLoc = S.Context.getTrivialTypeSourceInfo(QT, Attr.getLoc()); +    // Diagnose use of non-object type in iboutletcollection attribute.    // FIXME. Gnu attribute extension ignores use of builtin types in    // attributes. So, __attribute__((iboutletcollection(char))) will be    // treated as __attribute__((iboutletcollection())).    if (!QT->isObjCIdType() && !QT->isObjCObjectType()) { -    S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; +    S.Diag(Attr.getLoc(), +           QT->isBuiltinType() ? diag::err_iboutletcollection_builtintype +                               : diag::err_iboutletcollection_type) << QT;      return;    } +    D->addAttr(::new (S.Context) -             IBOutletCollectionAttr(Attr.getRange(),S.Context, -                                    QT, Attr.getParameterLoc(), +             IBOutletCollectionAttr(Attr.getRange(), S.Context, QTLoc,                                      Attr.getAttributeSpellingListIndex()));  } @@ -1122,70 +1398,36 @@ static void possibleTransparentUnionPointerType(QualType &T) {  static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (!isFunctionOrMethod(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) -    << "alloc_size" << ExpectedFunctionOrMethod; +    << Attr.getName() << ExpectedFunctionOrMethod;      return;    }    if (!checkAttributeAtLeastNumArgs(S, Attr, 1))      return; -  // In C++ the implicit 'this' function parameter also counts, and they are -  // counted from one. -  bool HasImplicitThisParam = isInstanceMethod(D); -  unsigned NumArgs; -  if (hasFunctionProto(D)) -    NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; -  else -    NumArgs = 0; -    SmallVector<unsigned, 8> SizeArgs; - -  for (AttributeList::arg_iterator I = Attr.arg_begin(), -       E = Attr.arg_end(); I!=E; ++I) { -    // The argument must be an integer constant expression. -    Expr *Ex = *I; -    llvm::APSInt ArgNum; -    if (Ex->isTypeDependent() || Ex->isValueDependent() || -        !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -      << "alloc_size" << Ex->getSourceRange(); -      return; -    } - -    uint64_t x = ArgNum.getZExtValue(); - -    if (x < 1 || x > NumArgs) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) -      << "alloc_size" << I.getArgNum() << Ex->getSourceRange(); +  for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { +    Expr *Ex = Attr.getArgAsExpr(i); +    uint64_t Idx; +    if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), +                                            Attr.getLoc(), i + 1, Ex, Idx))        return; -    } - -    --x; -    if (HasImplicitThisParam) { -      if (x == 0) { -        S.Diag(Attr.getLoc(), -               diag::err_attribute_invalid_implicit_this_argument) -        << "alloc_size" << Ex->getSourceRange(); -        return; -      } -      --x; -    }      // check if the function argument is of an integer type -    QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); +    QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();      if (!T->isIntegerType()) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -      << "alloc_size" << Ex->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) +        << Attr.getName() << AANT_ArgumentIntegerConstant +        << Ex->getSourceRange();        return;      } - -    SizeArgs.push_back(x); +    SizeArgs.push_back(Idx);    }    // check if the function returns a pointer    if (!getFunctionType(D)->getResultType()->isAnyPointerType()) {      S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type) -    << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); +    << Attr.getName() << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange();    }    D->addAttr(::new (S.Context) @@ -1203,47 +1445,16 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {      return;    } -  // In C++ the implicit 'this' function parameter also counts, and they are -  // counted from one. -  bool HasImplicitThisParam = isInstanceMethod(D); -  unsigned NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - -  // The nonnull attribute only applies to pointers. -  SmallVector<unsigned, 10> NonNullArgs; - -  for (AttributeList::arg_iterator I = Attr.arg_begin(), -                                   E = Attr.arg_end(); I != E; ++I) { -    // The argument must be an integer constant expression. -    Expr *Ex = *I; -    llvm::APSInt ArgNum(32); -    if (Ex->isTypeDependent() || Ex->isValueDependent() || -        !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -        << "nonnull" << Ex->getSourceRange(); +  SmallVector<unsigned, 8> NonNullArgs; +  for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { +    Expr *Ex = Attr.getArgAsExpr(i); +    uint64_t Idx; +    if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), +                                            Attr.getLoc(), i + 1, Ex, Idx))        return; -    } - -    unsigned x = (unsigned) ArgNum.getZExtValue(); - -    if (x < 1 || x > NumArgs) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) -       << "nonnull" << I.getArgNum() << Ex->getSourceRange(); -      return; -    } - -    --x; -    if (HasImplicitThisParam) { -      if (x == 0) { -        S.Diag(Attr.getLoc(), -               diag::err_attribute_invalid_implicit_this_argument) -          << "nonnull" << Ex->getSourceRange(); -        return; -      } -      --x; -    }      // Is the function argument a pointer type? -    QualType T = getFunctionOrMethodArgType(D, x).getNonReferenceType(); +    QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType();      possibleTransparentUnionPointerType(T);      if (!T->isAnyPointerType() && !T->isBlockPointerType()) { @@ -1253,7 +1464,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {        continue;      } -    NonNullArgs.push_back(x); +    NonNullArgs.push_back(Idx);    }    // If no arguments were specified to __attribute__((nonnull)) then all pointer @@ -1284,43 +1495,52 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) {                           Attr.getAttributeSpellingListIndex()));  } +static const char *ownershipKindToDiagName(OwnershipAttr::OwnershipKind K) { +  switch (K) { +    case OwnershipAttr::Holds:    return "'ownership_holds'"; +    case OwnershipAttr::Takes:    return "'ownership_takes'"; +    case OwnershipAttr::Returns:  return "'ownership_returns'"; +  } +  llvm_unreachable("unknown ownership"); +} +  static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { -  // This attribute must be applied to a function declaration. -  // The first argument to the attribute must be a string, -  // the name of the resource, for example "malloc". -  // The following arguments must be argument indexes, the arguments must be -  // of integer type for Returns, otherwise of pointer type. +  // This attribute must be applied to a function declaration. The first +  // argument to the attribute must be an identifier, the name of the resource, +  // for example: malloc. The following arguments must be argument indexes, the +  // arguments must be of integer type for Returns, otherwise of pointer type.    // The difference between Holds and Takes is that a pointer may still be used -  // after being held.  free() should be __attribute((ownership_takes)), whereas +  // after being held. free() should be __attribute((ownership_takes)), whereas    // a list append function may well be __attribute((ownership_holds)). -  if (!AL.getParameterName()) { -    S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) -        << AL.getName()->getName() << 1; +  if (!AL.isArgIdent(0)) { +    S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) +      << AL.getName() << 1 << AANT_ArgumentIdentifier;      return;    } +    // Figure out our Kind, and check arguments while we're at it.    OwnershipAttr::OwnershipKind K;    switch (AL.getKind()) {    case AttributeList::AT_ownership_takes:      K = OwnershipAttr::Takes; -    if (AL.getNumArgs() < 1) { -      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; +    if (AL.getNumArgs() < 2) { +      S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;        return;      }      break;    case AttributeList::AT_ownership_holds:      K = OwnershipAttr::Holds; -    if (AL.getNumArgs() < 1) { -      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; +    if (AL.getNumArgs() < 2) { +      S.Diag(AL.getLoc(), diag::err_attribute_too_few_arguments) << 2;        return;      }      break;    case AttributeList::AT_ownership_returns:      K = OwnershipAttr::Returns; -    if (AL.getNumArgs() > 1) { -      S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) -          << AL.getNumArgs() + 1; + +    if (AL.getNumArgs() > 2) { +      S.Diag(AL.getLoc(), diag::err_attribute_too_many_arguments) << 1;        return;      }      break; @@ -1335,107 +1555,58 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {      return;    } -  // In C++ the implicit 'this' function parameter also counts, and they are -  // counted from one. -  bool HasImplicitThisParam = isInstanceMethod(D); -  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; - -  StringRef Module = AL.getParameterName()->getName(); +  StringRef Module = AL.getArgAsIdent(0)->Ident->getName();    // Normalize the argument, __foo__ becomes foo.    if (Module.startswith("__") && Module.endswith("__"))      Module = Module.substr(2, Module.size() - 4); -  SmallVector<unsigned, 10> OwnershipArgs; - -  for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; -       ++I) { - -    Expr *IdxExpr = *I; -    llvm::APSInt ArgNum(32); -    if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() -        || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { -      S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int) -          << AL.getName()->getName() << IdxExpr->getSourceRange(); -      continue; -    } - -    unsigned x = (unsigned) ArgNum.getZExtValue(); - -    if (x > NumArgs || x < 1) { -      S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) -          << AL.getName()->getName() << x << IdxExpr->getSourceRange(); -      continue; -    } -    --x; -    if (HasImplicitThisParam) { -      if (x == 0) { -        S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument) -          << "ownership" << IdxExpr->getSourceRange(); -        return; -      } -      --x; -    } +  SmallVector<unsigned, 8> OwnershipArgs; +  for (unsigned i = 1; i < AL.getNumArgs(); ++i) { +    Expr *Ex = AL.getArgAsExpr(i); +    uint64_t Idx; +    if (!checkFunctionOrMethodArgumentIndex(S, D, AL.getName()->getName(), +                                            AL.getLoc(), i, Ex, Idx)) +      return; +    // Is the function argument a pointer type? +    QualType T = getFunctionOrMethodArgType(D, Idx); +    int Err = -1;  // No error      switch (K) { -    case OwnershipAttr::Takes: -    case OwnershipAttr::Holds: { -      // Is the function argument a pointer type? -      QualType T = getFunctionOrMethodArgType(D, x); -      if (!T->isAnyPointerType() && !T->isBlockPointerType()) { -        // FIXME: Should also highlight argument in decl. -        S.Diag(AL.getLoc(), diag::err_ownership_type) -            << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") -            << "pointer" -            << IdxExpr->getSourceRange(); -        continue; -      } -      break; +      case OwnershipAttr::Takes: +      case OwnershipAttr::Holds: +        if (!T->isAnyPointerType() && !T->isBlockPointerType()) +          Err = 0; +        break; +      case OwnershipAttr::Returns: +        if (!T->isIntegerType()) +          Err = 1; +        break;      } -    case OwnershipAttr::Returns: { -      if (AL.getNumArgs() > 1) { -          // Is the function argument an integer type? -          Expr *IdxExpr = AL.getArg(0); -          llvm::APSInt ArgNum(32); -          if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() -              || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { -            S.Diag(AL.getLoc(), diag::err_ownership_type) -                << "ownership_returns" << "integer" -                << IdxExpr->getSourceRange(); -            return; -          } -      } -      break; +    if (-1 != Err) { +      S.Diag(AL.getLoc(), diag::err_ownership_type) << AL.getName() << Err +        << Ex->getSourceRange(); +      return;      } -    } // switch      // Check we don't have a conflict with another ownership attribute.      for (specific_attr_iterator<OwnershipAttr> -          i = D->specific_attr_begin<OwnershipAttr>(), -          e = D->specific_attr_end<OwnershipAttr>(); -        i != e; ++i) { -      if ((*i)->getOwnKind() != K) { -        for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); -             I!=E; ++I) { -          if (x == *I) { -            S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) -                << AL.getName()->getName() << "ownership_*"; -          } -        } +         i = D->specific_attr_begin<OwnershipAttr>(), +         e = D->specific_attr_end<OwnershipAttr>(); i != e; ++i) { +      if ((*i)->getOwnKind() != K && (*i)->args_end() != +          std::find((*i)->args_begin(), (*i)->args_end(), Idx)) { +        S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) +          << AL.getName() << ownershipKindToDiagName((*i)->getOwnKind()); +        return;        }      } -    OwnershipArgs.push_back(x); +    OwnershipArgs.push_back(Idx);    }    unsigned* start = OwnershipArgs.data();    unsigned size = OwnershipArgs.size();    llvm::array_pod_sort(start, start + size); -  if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) { -    S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; -    return; -  } -    D->addAttr(::new (S.Context)               OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size,                             AL.getAttributeSpellingListIndex())); @@ -1444,7 +1615,8 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) {  static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // Check the attribute arguments.    if (Attr.getNumArgs() > 1) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +      << Attr.getName() << 1;      return;    } @@ -1495,21 +1667,15 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // static ((alias ("y"), weakref)).    // Should we? How to check that weakref is before or after alias? -  if (Attr.getNumArgs() == 1) { -    Expr *Arg = Attr.getArg(0); -    Arg = Arg->IgnoreParenCasts(); -    StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - -    if (!Str || !Str->isAscii()) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -          << "weakref" << 1; -      return; -    } +  // FIXME: it would be good for us to keep the WeakRefAttr as-written instead +  // of transforming it into an AliasAttr.  The WeakRefAttr never uses the +  // StringRef parameter it was given anyway. +  StringRef Str; +  if (Attr.getNumArgs() && S.checkStringLiteralArgumentAttr(Attr, 0, Str))      // GCC will accept anything as the argument of weakref. Should we      // check for an existing decl? -    D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, -                                           Str->getString())); -  } +    D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str, +                                        Attr.getAttributeSpellingListIndex()));    D->addAttr(::new (S.Context)               WeakRefAttr(Attr.getRange(), S.Context, @@ -1517,21 +1683,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.getNumArgs() != 1) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  } - -  Expr *Arg = Attr.getArg(0); -  Arg = Arg->IgnoreParenCasts(); -  StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - -  if (!Str || !Str->isAscii()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -      << "alias" << 1; +  StringRef Str; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))      return; -  }    if (S.Context.getTargetInfo().getTriple().isOSDarwin()) {      S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); @@ -1540,16 +1694,11 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // FIXME: check if target symbol exists in current file -  D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, -                                         Str->getString(), +  D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, Str,                                           Attr.getAttributeSpellingListIndex()));  }  static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunctionOrMethod; @@ -1562,10 +1711,6 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -1583,10 +1728,6 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -1604,10 +1745,6 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -1621,12 +1758,6 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleAlwaysInlineAttr(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  // Check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -1640,21 +1771,11 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D,  static void handleTLSModelAttr(Sema &S, Decl *D,                                 const AttributeList &Attr) { -  // Check the attribute arguments. -  if (Attr.getNumArgs() != 1) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  } - -  Expr *Arg = Attr.getArg(0); -  Arg = Arg->IgnoreParenCasts(); -  StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - +  StringRef Model; +  SourceLocation LiteralLoc;    // Check that it is a string. -  if (!Str) { -    S.Diag(Attr.getLoc(), diag::err_attribute_not_string) << "tls_model"; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))      return; -  }    if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) @@ -1663,10 +1784,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D,    }    // Check that the value. -  StringRef Model = Str->getString();    if (Model != "global-dynamic" && Model != "local-dynamic"        && Model != "initial-exec" && Model != "local-exec") { -    S.Diag(Attr.getLoc(), diag::err_attr_tlsmodel_arg); +    S.Diag(LiteralLoc, diag::err_attr_tlsmodel_arg);      return;    } @@ -1676,12 +1796,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D,  }  static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {      QualType RetTy = FD->getResultType();      if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { @@ -1696,17 +1810,12 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    D->addAttr(::new (S.Context)               MayAliasAttr(Attr.getRange(), S.Context,                            Attr.getAttributeSpellingListIndex()));  }  static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  assert(!Attr.isInvalid());    if (isa<VarDecl>(D))      D->addAttr(::new (S.Context)                 NoCommonAttr(Attr.getRange(), S.Context, @@ -1717,7 +1826,11 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  assert(!Attr.isInvalid()); +  if (S.LangOpts.CPlusPlus) { +    S.Diag(Attr.getLoc(), diag::err_common_not_supported_cplusplus); +    return; +  } +    if (isa<VarDecl>(D))      D->addAttr(::new (S.Context)                 CommonAttr(Attr.getRange(), S.Context, @@ -1744,8 +1857,7 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {  }  bool Sema::CheckNoReturnAttr(const AttributeList &attr) { -  if (attr.hasParameterOrArguments()) { -    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; +  if (!checkAttributeNumArgs(*this, attr, 0)) {      attr.setInvalid();      return true;    } @@ -1758,10 +1870,6 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,    // The checking path for 'noreturn' and 'analyzer_noreturn' are different    // because 'analyzer_noreturn' does not impact the type. -   -  if(!checkAttributeNumArgs(S, Attr, 0)) -      return; -      if (!isFunctionOrMethod(D) && !isa<BlockDecl>(D)) {      ValueDecl *VD = dyn_cast<ValueDecl>(D);      if (VD == 0 || (!VD->getType()->isBlockPointerType() @@ -1881,12 +1989,6 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,  }  static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&        !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -1901,12 +2003,6 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleReturnsTwiceAttr(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -1919,14 +2015,8 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D,  }  static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { -    if (VD->hasLocalStorage() || VD->hasExternalStorage()) { +    if (VD->hasLocalStorage()) {        S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used";        return;      } @@ -1950,12 +2040,13 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {    int priority = 65535; // FIXME: Do not hardcode such constants.    if (Attr.getNumArgs() > 0) { -    Expr *E = Attr.getArg(0); +    Expr *E = Attr.getArgAsExpr(0);      llvm::APSInt Idx(32);      if (E->isTypeDependent() || E->isValueDependent() ||          !E->isIntegerConstantExpr(Idx, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -        << "constructor" << 1 << E->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +        << Attr.getName() << 1 << AANT_ArgumentIntegerConstant +        << E->getSourceRange();        return;      }      priority = Idx.getZExtValue(); @@ -1981,12 +2072,13 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {    int priority = 65535; // FIXME: Do not hardcode such constants.    if (Attr.getNumArgs() > 0) { -    Expr *E = Attr.getArg(0); +    Expr *E = Attr.getArgAsExpr(0);      llvm::APSInt Idx(32);      if (E->isTypeDependent() || E->isValueDependent() ||          !E->isIntegerConstantExpr(Idx, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -        << "destructor" << 1 << E->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +        << Attr.getName() << 1 << AANT_ArgumentIntegerConstant +        << E->getSourceRange();        return;      }      priority = Idx.getZExtValue(); @@ -2004,8 +2096,8 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  template <typename AttrTy> -static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, -                                  const char *Name) { +static void handleAttrWithMessage(Sema &S, Decl *D, +                                  const AttributeList &Attr) {    unsigned NumArgs = Attr.getNumArgs();    if (NumArgs > 1) {      S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; @@ -2014,15 +2106,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,    // Handle the case where the attribute has a text message.    StringRef Str; -  if (NumArgs == 1) { -    StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); -    if (!SE) { -      S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) -        << Name; -      return; -    } -    Str = SE->getString(); -  } +  if (NumArgs == 1 && !S.checkStringLiteralArgumentAttr(Attr, 0, Str)) +    return;    D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str,                                        Attr.getAttributeSpellingListIndex())); @@ -2030,12 +2115,6 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr,  static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,                                               const AttributeList &Attr) { -  unsigned NumArgs = Attr.getNumArgs(); -  if (NumArgs > 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; -    return; -  } -      D->addAttr(::new (S.Context)               ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,                                         Attr.getAttributeSpellingListIndex())); @@ -2044,13 +2123,8 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,  static void handleObjCRootClassAttr(Sema &S, Decl *D,                                       const AttributeList &Attr) {    if (!isa<ObjCInterfaceDecl>(D)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); -    return; -  } -   -  unsigned NumArgs = Attr.getNumArgs(); -  if (NumArgs > 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) +      << Attr.getName() << ExpectedObjectiveCInterface;      return;    } @@ -2066,12 +2140,6 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,      return;    } -  unsigned NumArgs = Attr.getNumArgs(); -  if (NumArgs > 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 0; -    return; -  } -      D->addAttr(::new (S.Context)               ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,                                            Attr.getAttributeSpellingListIndex())); @@ -2261,13 +2329,15 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range,  static void handleAvailabilityAttr(Sema &S, Decl *D,                                     const AttributeList &Attr) { -  IdentifierInfo *Platform = Attr.getParameterName(); -  SourceLocation PlatformLoc = Attr.getParameterLoc(); +  if (!checkAttributeNumArgs(S, Attr, 1)) +    return; +  IdentifierLoc *Platform = Attr.getArgAsIdent(0);    unsigned Index = Attr.getAttributeSpellingListIndex(); -  if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) -    S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) -      << Platform; +  IdentifierInfo *II = Platform->Ident; +  if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty()) +    S.Diag(Platform->Loc, diag::warn_availability_unknown_platform) +      << Platform->Ident;    NamedDecl *ND = dyn_cast<NamedDecl>(D);    if (!ND) { @@ -2280,13 +2350,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,    AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted();    bool IsUnavailable = Attr.getUnavailableLoc().isValid();    StringRef Str; -  const StringLiteral *SE =  -    dyn_cast_or_null<const StringLiteral>(Attr.getMessageExpr()); -  if (SE) +  if (const StringLiteral *SE = +          dyn_cast_or_null<StringLiteral>(Attr.getMessageExpr()))      Str = SE->getString(); -  AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), -                                                      Platform, +  AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), II,                                                        Introduced.Version,                                                        Deprecated.Version,                                                        Obsoleted.Version, @@ -2346,41 +2414,25 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,      return;    } -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 1)) +  // Check that the argument is a string literal. +  StringRef TypeStr; +  SourceLocation LiteralLoc; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, TypeStr, &LiteralLoc))      return; -  Expr *Arg = Attr.getArg(0); -  Arg = Arg->IgnoreParenCasts(); -  StringLiteral *Str = dyn_cast<StringLiteral>(Arg); - -  if (!Str || !Str->isAscii()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -      << (isTypeVisibility ? "type_visibility" : "visibility") << 1; +  VisibilityAttr::VisibilityType type; +  if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) { +    S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported) +      << Attr.getName() << TypeStr;      return;    } - -  StringRef TypeStr = Str->getString(); -  VisibilityAttr::VisibilityType type; -  if (TypeStr == "default") +  // Complain about attempts to use protected visibility on targets +  // (like Darwin) that don't support it. +  if (type == VisibilityAttr::Protected && +      !S.Context.getTargetInfo().hasProtectedVisibility()) { +    S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);      type = VisibilityAttr::Default; -  else if (TypeStr == "hidden") -    type = VisibilityAttr::Hidden; -  else if (TypeStr == "internal") -    type = VisibilityAttr::Hidden; // FIXME -  else if (TypeStr == "protected") { -    // Complain about attempts to use protected visibility on targets -    // (like Darwin) that don't support it. -    if (!S.Context.getTargetInfo().hasProtectedVisibility()) { -      S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility); -      type = VisibilityAttr::Default; -    } else { -      type = VisibilityAttr::Protected; -    } -  } else { -    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; -    return;    }    unsigned Index = Attr.getAttributeSpellingListIndex(); @@ -2405,39 +2457,21 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,      return;    } -  if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) { -    if (!Attr.getParameterName() && Attr.getNumArgs() == 1) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -        << "objc_method_family" << 1; -    } else { -      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    } -    Attr.setInvalid(); +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 1 << AANT_ArgumentIdentifier;      return;    } -  StringRef param = Attr.getParameterName()->getName(); -  ObjCMethodFamilyAttr::FamilyKind family; -  if (param == "none") -    family = ObjCMethodFamilyAttr::OMF_None; -  else if (param == "alloc") -    family = ObjCMethodFamilyAttr::OMF_alloc; -  else if (param == "copy") -    family = ObjCMethodFamilyAttr::OMF_copy; -  else if (param == "init") -    family = ObjCMethodFamilyAttr::OMF_init; -  else if (param == "mutableCopy") -    family = ObjCMethodFamilyAttr::OMF_mutableCopy; -  else if (param == "new") -    family = ObjCMethodFamilyAttr::OMF_new; -  else { -    // Just warn and ignore it.  This is future-proof against new -    // families being used in system headers. -    S.Diag(Attr.getParameterLoc(), diag::warn_unknown_method_family); +  IdentifierLoc *IL = Attr.getArgAsIdent(0); +  ObjCMethodFamilyAttr::FamilyKind F; +  if (!ObjCMethodFamilyAttr::ConvertStrToFamilyKind(IL->Ident->getName(), F)) { +    S.Diag(IL->Loc, diag::warn_attribute_type_not_supported) << Attr.getName() +      << IL->Ident;      return;    } -  if (family == ObjCMethodFamilyAttr::OMF_init &&  +  if (F == ObjCMethodFamilyAttr::OMF_init &&         !method->getResultType()->isObjCObjectPointerType()) {      S.Diag(method->getLocation(), diag::err_init_method_bad_return_type)        << method->getResultType(); @@ -2446,17 +2480,15 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,    }    method->addAttr(new (S.Context) ObjCMethodFamilyAttr(Attr.getRange(), -                                                       S.Context, family)); +                                                       S.Context, F));  }  static void handleObjCExceptionAttr(Sema &S, Decl *D,                                      const AttributeList &Attr) { -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);    if (OCI == 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) +      << Attr.getName() << ExpectedObjectiveCInterface;      return;    } @@ -2466,10 +2498,6 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D,  }  static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { -  if (Attr.getNumArgs() != 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  }    if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {      QualType T = TD->getUnderlyingType();      if (!T->isCARCBridgableType()) { @@ -2500,11 +2528,6 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {  static void  handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (Attr.getNumArgs() != 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  } -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function);      return; @@ -2516,23 +2539,17 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (!Attr.getParameterName()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -      << "blocks" << 1; -    return; -  } - -  if (Attr.getNumArgs() != 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 1 << AANT_ArgumentIdentifier;      return;    } +  IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;    BlocksAttr::BlockType type; -  if (Attr.getParameterName()->isStr("byref")) -    type = BlocksAttr::ByRef; -  else { +  if (!BlocksAttr::ConvertStrToBlockType(II->getName(), type)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) -      << "blocks" << Attr.getParameterName(); +      << Attr.getName() << II;      return;    } @@ -2550,12 +2567,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {    unsigned sentinel = 0;    if (Attr.getNumArgs() > 0) { -    Expr *E = Attr.getArg(0); +    Expr *E = Attr.getArgAsExpr(0);      llvm::APSInt Idx(32);      if (E->isTypeDependent() || E->isValueDependent() ||          !E->isIntegerConstantExpr(Idx, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -       << "sentinel" << 1 << E->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +        << Attr.getName() << 1 << AANT_ArgumentIntegerConstant +        << E->getSourceRange();        return;      } @@ -2570,12 +2588,13 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {    unsigned nullPos = 0;    if (Attr.getNumArgs() > 1) { -    Expr *E = Attr.getArg(1); +    Expr *E = Attr.getArgAsExpr(1);      llvm::APSInt Idx(32);      if (E->isTypeDependent() || E->isValueDependent() ||          !E->isIntegerConstantExpr(Idx, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -        << "sentinel" << 2 << E->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +        << Attr.getName() << 2 << AANT_ArgumentIntegerConstant +        << E->getSourceRange();        return;      }      nullPos = Idx.getZExtValue(); @@ -2635,11 +2654,14 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) {                            Attr.getAttributeSpellingListIndex()));  } -static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; +static void handleWarnUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { +  if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) +    RD->addAttr(::new (S.Context) WarnUnusedAttr(Attr.getRange(), S.Context)); +  else +    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} +static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) {    if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunctionMethodOrClass; @@ -2664,12 +2686,6 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)  }  static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {      if (isa<CXXRecordDecl>(D)) {        D->addAttr(::new (S.Context) WeakAttr(Attr.getRange(), S.Context)); @@ -2688,18 +2704,12 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; - -    // weak_import only applies to variable & function declarations.    bool isDef = false;    if (!D->canBeWeakImported(isDef)) {      if (isDef) -      S.Diag(Attr.getLoc(), -             diag::warn_attribute_weak_import_invalid_on_definition) -        << "weak_import" << 2 /*variable and function*/; +      S.Diag(Attr.getLoc(), diag::warn_attribute_invalid_on_definition) +        << "weak_import";      else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) ||               (S.Context.getTargetInfo().getTriple().isOSDarwin() &&                (isa<ObjCInterfaceDecl>(D) || isa<EnumDecl>(D)))) { @@ -2719,20 +2729,15 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) {  // Handles reqd_work_group_size and work_group_size_hint.  static void handleWorkGroupSize(Sema &S, Decl *D,                                  const AttributeList &Attr) { -  assert(Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize  -      || Attr.getKind() == AttributeList::AT_WorkGroupSizeHint); - -  // Attribute has 3 arguments. -  if (!checkAttributeNumArgs(S, Attr, 3)) return; -    unsigned WGSize[3];    for (unsigned i = 0; i < 3; ++i) { -    Expr *E = Attr.getArg(i); +    Expr *E = Attr.getArgAsExpr(i);      llvm::APSInt ArgNum(32);      if (E->isTypeDependent() || E->isValueDependent() ||          !E->isIntegerConstantExpr(ArgNum, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -        << Attr.getName()->getName() << E->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) +        << Attr.getName() << AANT_ArgumentIntegerConstant +        << E->getSourceRange();        return;      }      WGSize[i] = (unsigned) ArgNum.getZExtValue(); @@ -2775,11 +2780,15 @@ static void handleWorkGroupSize(Sema &S, Decl *D,  static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {    assert(Attr.getKind() == AttributeList::AT_VecTypeHint); -  // Attribute has 1 argument. -  if (!checkAttributeNumArgs(S, Attr, 1)) +  if (!Attr.hasParsedType()) { +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +      << Attr.getName() << 1;      return; +  } -  QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); +  TypeSourceInfo *ParmTSI = 0; +  QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg(), &ParmTSI); +  assert(ParmTSI && "no type source info for attribute argument");    if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&        (ParmType->isBooleanType() || @@ -2792,23 +2801,14 @@ static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) {    if (Attr.getKind() == AttributeList::AT_VecTypeHint &&        D->hasAttr<VecTypeHintAttr>()) {      VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); -    if (A->getTypeHint() != ParmType) { +    if (!S.Context.hasSameType(A->getTypeHint(), ParmType)) {        S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName();        return;      }    }    D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, -                                               ParmType, Attr.getLoc())); -} - -static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (!dyn_cast<VarDecl>(D)) -    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" -                                                                << 9; -  StringRef EndianType = Attr.getParameterName()->getName(); -  if (EndianType != "host" && EndianType != "device") -    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; +                                               ParmTSI));  }  SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, @@ -2826,48 +2826,35 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range,  }  static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // Attribute has no arguments. -  if (!checkAttributeNumArgs(S, Attr, 1)) -    return; -    // Make sure that there is a string literal as the sections's single    // argument. -  Expr *ArgExpr = Attr.getArg(0); -  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); -  if (!SE) { -    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; +  StringRef Str; +  SourceLocation LiteralLoc; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str, &LiteralLoc))      return; -  }    // If the target wants to validate the section specifier, make it happen. -  std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(SE->getString()); +  std::string Error = S.Context.getTargetInfo().isValidSectionSpecifier(Str);    if (!Error.empty()) { -    S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) +    S.Diag(LiteralLoc, diag::err_attribute_section_invalid_for_target)      << Error;      return;    }    // This attribute cannot be applied to local variables.    if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { -    S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); +    S.Diag(LiteralLoc, diag::err_attribute_section_local_variable);      return;    }    unsigned Index = Attr.getAttributeSpellingListIndex(); -  SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), -                                            SE->getString(), Index); +  SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), Str, Index);    if (NewAttr)      D->addAttr(NewAttr);  }  static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -      if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {      if (Existing->getLocation().isInvalid())        Existing->setRange(Attr.getRange()); @@ -2879,12 +2866,6 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (Attr.hasParameterOrArguments()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -    return; -  } -    if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {     if (Existing->getLocation().isInvalid())       Existing->setRange(Attr.getRange()); @@ -2896,56 +2877,55 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    D->addAttr(::new (S.Context)               PureAttr(Attr.getRange(), S.Context,                        Attr.getAttributeSpellingListIndex()));  }  static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (!Attr.getParameterName()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  } - -  if (Attr.getNumArgs() != 0) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    return; -  } -    VarDecl *VD = dyn_cast<VarDecl>(D); -    if (!VD || !VD->hasLocalStorage()) { -    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; +    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();      return;    } -  // Look up the function -  // FIXME: Lookup probably isn't looking in the right place -  NamedDecl *CleanupDecl -    = S.LookupSingleName(S.TUScope, Attr.getParameterName(), -                         Attr.getParameterLoc(), Sema::LookupOrdinaryName); -  if (!CleanupDecl) { -    S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << -      Attr.getParameterName(); -    return; -  } +  Expr *E = Attr.getArgAsExpr(0); +  SourceLocation Loc = E->getExprLoc(); +  FunctionDecl *FD = 0; +  DeclarationNameInfo NI; -  FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); -  if (!FD) { -    S.Diag(Attr.getParameterLoc(), -           diag::err_attribute_cleanup_arg_not_function) -      << Attr.getParameterName(); +  // gcc only allows for simple identifiers. Since we support more than gcc, we +  // will warn the user. +  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { +    if (DRE->hasQualifier()) +      S.Diag(Loc, diag::warn_cleanup_ext); +    FD = dyn_cast<FunctionDecl>(DRE->getDecl()); +    NI = DRE->getNameInfo(); +    if (!FD) { +      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 1 +        << NI.getName(); +      return; +    } +  } else if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { +    if (ULE->hasExplicitTemplateArgs()) +      S.Diag(Loc, diag::warn_cleanup_ext); +    FD = S.ResolveSingleFunctionTemplateSpecialization(ULE, true); +    NI = ULE->getNameInfo(); +    if (!FD) { +      S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 2 +        << NI.getName(); +      if (ULE->getType() == S.Context.OverloadTy) +        S.NoteAllOverloadCandidates(ULE); +      return; +    } +  } else { +    S.Diag(Loc, diag::err_attribute_cleanup_arg_not_function) << 0;      return;    }    if (FD->getNumParams() != 1) { -    S.Diag(Attr.getParameterLoc(), -           diag::err_attribute_cleanup_func_must_take_one_arg) -      << Attr.getParameterName(); +    S.Diag(Loc, diag::err_attribute_cleanup_func_must_take_one_arg) +      << NI.getName();      return;    } @@ -2955,63 +2935,30 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {    QualType ParamTy = FD->getParamDecl(0)->getType();    if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(),                                     ParamTy, Ty) != Sema::Compatible) { -    S.Diag(Attr.getParameterLoc(), -           diag::err_attribute_cleanup_func_arg_incompatible_type) << -      Attr.getParameterName() << ParamTy << Ty; +    S.Diag(Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) +      << NI.getName() << ParamTy << Ty;      return;    }    D->addAttr(::new (S.Context)               CleanupAttr(Attr.getRange(), S.Context, FD,                           Attr.getAttributeSpellingListIndex())); -  S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); -  S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc());  }  /// Handle __attribute__((format_arg((idx)))) attribute based on  /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html  static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (!checkAttributeNumArgs(S, Attr, 1)) -    return; -    if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction;      return;    } -  // In C++ the implicit 'this' function parameter also counts, and they are -  // counted from one. -  bool HasImplicitThisParam = isInstanceMethod(D); -  unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; -  unsigned FirstIdx = 1; - -  // checks for the 2nd argument -  Expr *IdxExpr = Attr.getArg(0); -  llvm::APSInt Idx(32); -  if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || -      !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -    << "format" << 2 << IdxExpr->getSourceRange(); -    return; -  } - -  if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) -    << "format" << 2 << IdxExpr->getSourceRange(); +  Expr *IdxExpr = Attr.getArgAsExpr(0); +  uint64_t ArgIdx; +  if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(), +                                          Attr.getLoc(), 1, IdxExpr, ArgIdx))      return; -  } - -  unsigned ArgIdx = Idx.getZExtValue() - 1; - -  if (HasImplicitThisParam) { -    if (ArgIdx == 0) { -      S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument) -        << "format_arg" << IdxExpr->getSourceRange(); -      return; -    } -    ArgIdx--; -  }    // make sure the format string is really a string    QualType Ty = getFunctionOrMethodArgType(D, ArgIdx); @@ -3039,8 +2986,14 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) {      return;    } +  // We cannot use the ArgIdx returned from checkFunctionOrMethodArgumentIndex +  // because that has corrected for the implicit this parameter, and is zero- +  // based.  The attribute expects what the user wrote explicitly. +  llvm::APSInt Val; +  IdxExpr->EvaluateAsInt(Val, S.Context); +    D->addAttr(::new (S.Context) -             FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(), +             FormatArgAttr(Attr.getRange(), S.Context, Val.getZExtValue(),                             Attr.getAttributeSpellingListIndex()));  } @@ -3094,18 +3047,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,      return;    } -  if (Attr.getNumArgs() != 1) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; -    Attr.setInvalid(); -    return; -  } -  Expr *priorityExpr = Attr.getArg(0); +  Expr *priorityExpr = Attr.getArgAsExpr(0);    llvm::APSInt priority(32);    if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||        !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -    << "init_priority" << priorityExpr->getSourceRange(); +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) +      << Attr.getName() << AANT_ArgumentIntegerConstant +      << priorityExpr->getSourceRange();      Attr.setInvalid();      return;    } @@ -3121,8 +3070,9 @@ static void handleInitPriorityAttr(Sema &S, Decl *D,                                Attr.getAttributeSpellingListIndex()));  } -FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, -                                  int FormatIdx, int FirstArg, +FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, +                                  IdentifierInfo *Format, int FormatIdx, +                                  int FirstArg,                                    unsigned AttrSpellingListIndex) {    // Check whether we already have an equivalent format attribute.    for (specific_attr_iterator<FormatAttr> @@ -3141,22 +3091,16 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format,      }    } -  return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg, -                                    AttrSpellingListIndex); +  return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, +                                    FirstArg, AttrSpellingListIndex);  }  /// Handle __attribute__((format(type,idx,firstarg))) attributes based on  /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html  static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { - -  if (!Attr.getParameterName()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -      << "format" << 1; -    return; -  } - -  if (Attr.getNumArgs() != 2) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 1 << AANT_ArgumentIdentifier;      return;    } @@ -3172,11 +3116,15 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {    unsigned NumArgs  = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam;    unsigned FirstIdx = 1; -  StringRef Format = Attr.getParameterName()->getName(); +  IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident; +  StringRef Format = II->getName();    // Normalize the argument, __foo__ becomes foo. -  if (Format.startswith("__") && Format.endswith("__")) +  if (Format.startswith("__") && Format.endswith("__")) {      Format = Format.substr(2, Format.size() - 4); +    // If we've modified the string name, we need a new identifier for it. +    II = &S.Context.Idents.get(Format); +  }    // Check for supported formats.    FormatAttrKind Kind = getFormatAttrKind(Format); @@ -3186,17 +3134,18 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (Kind == InvalidFormat) {      S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) -      << "format" << Attr.getParameterName()->getName(); +      << "format" << II->getName();      return;    }    // checks for the 2nd argument -  Expr *IdxExpr = Attr.getArg(0); +  Expr *IdxExpr = Attr.getArgAsExpr(1);    llvm::APSInt Idx(32);    if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() ||        !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -      << "format" << 2 << IdxExpr->getSourceRange(); +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 2 << AANT_ArgumentIntegerConstant +      << IdxExpr->getSourceRange();      return;    } @@ -3246,12 +3195,13 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {    }    // check the 3rd argument -  Expr *FirstArgExpr = Attr.getArg(1); +  Expr *FirstArgExpr = Attr.getArgAsExpr(2);    llvm::APSInt FirstArg(32);    if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() ||        !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -      << "format" << 3 << FirstArgExpr->getSourceRange(); +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 3 << AANT_ArgumentIntegerConstant +      << FirstArgExpr->getSourceRange();      return;    } @@ -3280,7 +3230,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {      return;    } -  FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format, +  FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), II,                                            Idx.getZExtValue(),                                            FirstArg.getZExtValue(),                                            Attr.getAttributeSpellingListIndex()); @@ -3290,11 +3240,6 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleTransparentUnionAttr(Sema &S, Decl *D,                                         const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; - -    // Try to find the underlying union declaration.    RecordDecl *RD = 0;    TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); @@ -3358,37 +3303,30 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D,  }  static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 1)) -    return; - -  Expr *ArgExpr = Attr.getArg(0); -  StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); -    // Make sure that there is a string literal as the annotation's single    // argument. -  if (!SE) { -    S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; +  StringRef Str; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, Str))      return; -  }    // Don't duplicate annotations that are already set.    for (specific_attr_iterator<AnnotateAttr>         i = D->specific_attr_begin<AnnotateAttr>(),         e = D->specific_attr_end<AnnotateAttr>(); i != e; ++i) { -      if ((*i)->getAnnotation() == SE->getString()) -          return; +    if ((*i)->getAnnotation() == Str) +      return;    }    D->addAttr(::new (S.Context) -             AnnotateAttr(Attr.getRange(), S.Context, SE->getString(), +             AnnotateAttr(Attr.getRange(), S.Context, Str,                            Attr.getAttributeSpellingListIndex()));  }  static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // check the attribute arguments.    if (Attr.getNumArgs() > 1) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +      << Attr.getName() << 1;      return;    } @@ -3398,7 +3336,7 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) {      return;    } -  Expr *E = Attr.getArg(0); +  Expr *E = Attr.getArgAsExpr(0);    if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) {      S.Diag(Attr.getEllipsisLoc(),             diag::err_pack_expansion_without_parameter_packs); @@ -3555,19 +3493,14 @@ void Sema::CheckAlignasUnderalignment(Decl *D) {  static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // This attribute isn't documented, but glibc uses it.  It changes    // the width of an int or unsigned int to the specified size. - -  // Check that there aren't any arguments -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; - - -  IdentifierInfo *Name = Attr.getParameterName(); -  if (!Name) { -    S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() +      << AANT_ArgumentIdentifier;      return;    } - -  StringRef Str = Attr.getParameterName()->getName(); +   +  IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; +  StringRef Str = Name->getName();    // Normalize the attribute name, __foo__ becomes foo.    if (Str.startswith("__") && Str.endswith("__")) @@ -3639,73 +3572,24 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {    // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t    // and friends, at least with glibc. -  // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong -  // width on unusual platforms.    // FIXME: Make sure floating-point mappings are accurate    // FIXME: Support XF and TF types -  QualType NewTy; -  switch (DestWidth) { -  case 0: +  if (!DestWidth) {      S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name;      return; -  default: +  } + +  QualType NewTy; + +  if (IntegerMode) +    NewTy = S.Context.getIntTypeForBitwidth(DestWidth, +                                            OldTy->isSignedIntegerType()); +  else +    NewTy = S.Context.getRealTypeForBitwidth(DestWidth); + +  if (NewTy.isNull()) {      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name;      return; -  case 8: -    if (!IntegerMode) { -      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; -      return; -    } -    if (OldTy->isSignedIntegerType()) -      NewTy = S.Context.SignedCharTy; -    else -      NewTy = S.Context.UnsignedCharTy; -    break; -  case 16: -    if (!IntegerMode) { -      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; -      return; -    } -    if (OldTy->isSignedIntegerType()) -      NewTy = S.Context.ShortTy; -    else -      NewTy = S.Context.UnsignedShortTy; -    break; -  case 32: -    if (!IntegerMode) -      NewTy = S.Context.FloatTy; -    else if (OldTy->isSignedIntegerType()) -      NewTy = S.Context.IntTy; -    else -      NewTy = S.Context.UnsignedIntTy; -    break; -  case 64: -    if (!IntegerMode) -      NewTy = S.Context.DoubleTy; -    else if (OldTy->isSignedIntegerType()) -      if (S.Context.getTargetInfo().getLongWidth() == 64) -        NewTy = S.Context.LongTy; -      else -        NewTy = S.Context.LongLongTy; -    else -      if (S.Context.getTargetInfo().getLongWidth() == 64) -        NewTy = S.Context.UnsignedLongTy; -      else -        NewTy = S.Context.UnsignedLongLongTy; -    break; -  case 96: -    NewTy = S.Context.LongDoubleTy; -    break; -  case 128: -    if (!IntegerMode) { -      S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; -      return; -    } -    if (OldTy->isSignedIntegerType()) -      NewTy = S.Context.Int128Ty; -    else -      NewTy = S.Context.UnsignedInt128Ty; -    break;    }    if (ComplexMode) { @@ -3713,18 +3597,17 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {    }    // Install the new type. -  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { -    // FIXME: preserve existing source info. -    TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); -  } else +  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) +    TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy); +  else      cast<ValueDecl>(D)->setType(NewTy); + +  D->addAttr(::new (S.Context) +             ModeAttr(Attr.getRange(), S.Context, Name, +                      Attr.getAttributeSpellingListIndex()));  }  static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {      if (!VD->hasGlobalStorage())        S.Diag(Attr.getLoc(), @@ -3743,11 +3626,6 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; - -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -3761,11 +3639,6 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,                                             const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; - -    if (!isa<FunctionDecl>(D)) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)        << Attr.getName() << ExpectedFunction; @@ -3779,12 +3652,6 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,  static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (S.LangOpts.CUDA) { -    // check the attribute arguments. -    if (Attr.hasParameterOrArguments()) { -      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; -      return; -    } -      if (!isa<VarDecl>(D)) {        S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)          << Attr.getName() << ExpectedVariable; @@ -3803,7 +3670,8 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (S.LangOpts.CUDA) {      // check the attribute arguments.      if (Attr.getNumArgs() != 0) { -      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; +      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) +        << Attr.getName() << 0;        return;      } @@ -3823,10 +3691,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (S.LangOpts.CUDA) { -    // check the attribute arguments. -    if (!checkAttributeNumArgs(S, Attr, 0)) -      return; -      if (!isa<FunctionDecl>(D)) {        S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)          << Attr.getName() << ExpectedFunction; @@ -3858,11 +3722,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (S.LangOpts.CUDA) { -    // check the attribute arguments. -    if (!checkAttributeNumArgs(S, Attr, 0)) -      return; - -      if (!isa<FunctionDecl>(D)) {        S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)          << Attr.getName() << ExpectedFunction; @@ -3879,10 +3738,6 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {  static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {    if (S.LangOpts.CUDA) { -    // check the attribute arguments. -    if (!checkAttributeNumArgs(S, Attr, 0)) -      return; -      if (!isa<VarDecl>(D)) {        S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)          << Attr.getName() << ExpectedVariable; @@ -3898,10 +3753,6 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  // check the attribute arguments. -  if (!checkAttributeNumArgs(S, Attr, 0)) -    return; -    FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);    if (Fn == 0) {      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) @@ -3961,6 +3812,16 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {                 PascalAttr(Attr.getRange(), S.Context,                            Attr.getAttributeSpellingListIndex()));      return; +  case AttributeList::AT_MSABI: +    D->addAttr(::new (S.Context) +               MSABIAttr(Attr.getRange(), S.Context, +                         Attr.getAttributeSpellingListIndex())); +    return; +  case AttributeList::AT_SysVABI: +    D->addAttr(::new (S.Context) +               SysVABIAttr(Attr.getRange(), S.Context, +                           Attr.getAttributeSpellingListIndex())); +    return;    case AttributeList::AT_Pcs: {      PcsAttr::PCSType PCS;      switch (CC) { @@ -3996,19 +3857,17 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ -  assert(!Attr.isInvalid());    D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context));  }  static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ -  assert(!Attr.isInvalid()); - -  Expr *E = Attr.getArg(0); +  Expr *E = Attr.getArgAsExpr(0);    llvm::APSInt ArgNum(32);    if (E->isTypeDependent() || E->isValueDependent() ||        !E->isIntegerConstantExpr(ArgNum, S.Context)) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -      << Attr.getName()->getName() << E->getSourceRange(); +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) +      << Attr.getName() << AANT_ArgumentIntegerConstant +      << E->getSourceRange();      return;    } @@ -4022,8 +3881,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,      return true;    unsigned ReqArgs = attr.getKind() == AttributeList::AT_Pcs ? 1 : 0; -  if (attr.getNumArgs() != ReqArgs || attr.getParameterName()) { -    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << ReqArgs; +  if (!checkAttributeNumArgs(*this, attr, ReqArgs)) {      attr.setInvalid();      return true;    } @@ -4036,17 +3894,20 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,    case AttributeList::AT_StdCall: CC = CC_X86StdCall; break;    case AttributeList::AT_ThisCall: CC = CC_X86ThisCall; break;    case AttributeList::AT_Pascal: CC = CC_X86Pascal; break; +  case AttributeList::AT_MSABI: +    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_C : +                                                             CC_X86_64Win64; +    break; +  case AttributeList::AT_SysVABI: +    CC = Context.getTargetInfo().getTriple().isOSWindows() ? CC_X86_64SysV : +                                                             CC_C; +    break;    case AttributeList::AT_Pcs: { -    Expr *Arg = attr.getArg(0); -    StringLiteral *Str = dyn_cast<StringLiteral>(Arg); -    if (!Str || !Str->isAscii()) { -      Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) -        << "pcs" << 1; +    StringRef StrRef; +    if (!checkStringLiteralArgumentAttr(attr, 0, StrRef)) {        attr.setInvalid();        return true;      } - -    StringRef StrRef = Str->getString();      if (StrRef == "aapcs") {        CC = CC_AAPCS;        break; @@ -4103,18 +3964,18 @@ bool Sema::CheckRegparmAttr(const AttributeList &Attr, unsigned &numParams) {    if (Attr.isInvalid())      return true; -  if (Attr.getNumArgs() != 1) { -    Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; +  if (!checkAttributeNumArgs(*this, Attr, 1)) {      Attr.setInvalid();      return true;    } -  Expr *NumParamsExpr = Attr.getArg(0); +  Expr *NumParamsExpr = Attr.getArgAsExpr(0);    llvm::APSInt NumParams(32);    if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() ||        !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { -    Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) -      << "regparm" << NumParamsExpr->getSourceRange(); +    Diag(Attr.getLoc(), diag::err_attribute_argument_type) +      << Attr.getName() << AANT_ArgumentIntegerConstant +      << NumParamsExpr->getSourceRange();      Attr.setInvalid();      return true;    } @@ -4152,24 +4013,26 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){        return;      } -    Expr *MaxThreadsExpr = Attr.getArg(0); +    Expr *MaxThreadsExpr = Attr.getArgAsExpr(0);      llvm::APSInt MaxThreads(32);      if (MaxThreadsExpr->isTypeDependent() ||          MaxThreadsExpr->isValueDependent() ||          !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -        << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange(); +      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +        << Attr.getName() << 1 << AANT_ArgumentIntegerConstant +        << MaxThreadsExpr->getSourceRange();        return;      }      llvm::APSInt MinBlocks(32);      if (Attr.getNumArgs() > 1) { -      Expr *MinBlocksExpr = Attr.getArg(1); +      Expr *MinBlocksExpr = Attr.getArgAsExpr(1);        if (MinBlocksExpr->isTypeDependent() ||            MinBlocksExpr->isValueDependent() ||            !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { -        S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) -          << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange(); +        S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +          << Attr.getName() << 2 << AANT_ArgumentIntegerConstant +          << MinBlocksExpr->getSourceRange();          return;        }      } @@ -4186,20 +4049,17 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){  static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,                                            const AttributeList &Attr) { -  StringRef AttrName = Attr.getName()->getName(); -  if (!Attr.getParameterName()) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) -      << Attr.getName() << /* arg num = */ 1; +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;      return;    } - -  if (Attr.getNumArgs() != 2) { -    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) -      << /* required args = */ 3; +   +  if (!checkAttributeNumArgs(S, Attr, 3))      return; -  } -  IdentifierInfo *ArgumentKind = Attr.getParameterName(); +  StringRef AttrName = Attr.getName()->getName(); +  IdentifierInfo *ArgumentKind = Attr.getArgAsIdent(0)->Ident;    if (!isFunctionOrMethod(D) || !hasFunctionProto(D)) {      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) @@ -4210,13 +4070,13 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,    uint64_t ArgumentIdx;    if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,                                            Attr.getLoc(), 2, -                                          Attr.getArg(0), ArgumentIdx)) +                                          Attr.getArgAsExpr(1), ArgumentIdx))      return;    uint64_t TypeTagIdx;    if (!checkFunctionOrMethodArgumentIndex(S, D, AttrName,                                            Attr.getLoc(), 3, -                                          Attr.getArg(1), TypeTagIdx)) +                                          Attr.getArgAsExpr(2), TypeTagIdx))      return;    bool IsPointer = (AttrName == "pointer_with_type_tag"); @@ -4225,7 +4085,7 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,      QualType BufferTy = getFunctionOrMethodArgType(D, ArgumentIdx);      if (!BufferTy->isPointerType()) {        S.Diag(Attr.getLoc(), diag::err_attribute_pointers_only) -        << AttrName; +        << Attr.getName();      }    } @@ -4237,18 +4097,23 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,  static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,                                           const AttributeList &Attr) { -  IdentifierInfo *PointerKind = Attr.getParameterName(); -  if (!PointerKind) { -    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_identifier) -      << "type_tag_for_datatype" << 1; +  if (!Attr.isArgIdent(0)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type) +      << Attr.getName() << 1 << AANT_ArgumentIdentifier;      return;    } +   +  if (!checkAttributeNumArgs(S, Attr, 1)) +    return; -  QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); +  IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident; +  TypeSourceInfo *MatchingCTypeLoc = 0; +  S.GetTypeFromParser(Attr.getMatchingCType(), &MatchingCTypeLoc); +  assert(MatchingCTypeLoc && "no type source info for attribute argument");    D->addAttr(::new (S.Context)               TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, -                                    MatchingCType, +                                    MatchingCTypeLoc,                                      Attr.getLayoutCompatible(),                                      Attr.getMustBeNull(),                                      Attr.getAttributeSpellingListIndex())); @@ -4393,30 +4258,39 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D,  static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,                                                const AttributeList &attr) { +  const int EP_ObjCMethod = 1; +  const int EP_ObjCProperty = 2; +      SourceLocation loc = attr.getLoc(); - +  QualType resultType; +      ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);    if (!method) { -    S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) -      << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; -    return; +    ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D); +    if (!property) { +      S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) +        << SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty; +      return; +    } +    resultType = property->getType();    } +  else +    // Check that the method returns a normal pointer. +    resultType = method->getResultType(); -  // Check that the method returns a normal pointer. -  QualType resultType = method->getResultType(); -        if (!resultType->isReferenceType() &&        (!resultType->isPointerType() || resultType->isObjCRetainableType())) { -    S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type) +    S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)        << SourceRange(loc) -      << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2; +    << attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty) +    << /*non-retainable pointer*/ 2;      // Drop the attribute.      return;    } -  method->addAttr(::new (S.Context) +  D->addAttr(::new (S.Context)                    ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context,                                                attr.getAttributeSpellingListIndex()));  } @@ -4494,14 +4368,14 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,        << Attr.getRange() << Attr.getName() << ExpectedStruct;    } -  IdentifierInfo *ParmName = Attr.getParameterName(); +  IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;    // In Objective-C, verify that the type names an Objective-C type.    // We don't want to check this outside of ObjC because people sometimes    // do crazy C declarations of Objective-C types. -  if (ParmName && S.getLangOpts().ObjC1) { +  if (Parm && S.getLangOpts().ObjC1) {      // Check for an existing type with this name. -    LookupResult R(S, DeclarationName(ParmName), Attr.getParameterLoc(), +    LookupResult R(S, DeclarationName(Parm->Ident), Parm->Loc,                     Sema::LookupOrdinaryName);      if (S.LookupName(R, Sc)) {        NamedDecl *Target = R.getFoundDecl(); @@ -4513,7 +4387,32 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,    }    D->addAttr(::new (S.Context) -             NSBridgedAttr(Attr.getRange(), S.Context, ParmName, +             NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0, +                           Attr.getAttributeSpellingListIndex())); +} + +static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D, +                                const AttributeList &Attr) { +  if (!isa<RecordDecl>(D)) { +    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) +    << Attr.getName() +    << (S.getLangOpts().CPlusPlus ? ExpectedStructOrUnionOrClass +                                  : ExpectedStructOrUnion); +    return; +  } +   +  if (Attr.getNumArgs() != 1) { +    S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); +    return; +  } +  IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0; +  if (!Parm) { +    S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id); +    return; +  } +   +  D->addAttr(::new (S.Context) +             ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,                             Attr.getAttributeSpellingListIndex()));  } @@ -4576,66 +4475,55 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,  // Microsoft specific attribute handlers.  //===----------------------------------------------------------------------===// -static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (S.LangOpts.MicrosoftExt || S.LangOpts.Borland) { -    // check the attribute arguments. -    if (!checkAttributeNumArgs(S, Attr, 1)) -      return; - -    Expr *Arg = Attr.getArg(0); -    StringLiteral *Str = dyn_cast<StringLiteral>(Arg); -    if (!Str || !Str->isAscii()) { -      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) -        << "uuid" << 1; -      return; -    } +// Check if MS extensions or some other language extensions are enabled.  If +// not, issue a diagnostic that the given attribute is unused. +static bool checkMicrosoftExt(Sema &S, const AttributeList &Attr, +                              bool OtherExtension = false) { +  if (S.LangOpts.MicrosoftExt || OtherExtension) +    return true; +  S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +  return false; +} -    StringRef StrRef = Str->getString(); +static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { +  if (!checkMicrosoftExt(S, Attr, S.LangOpts.Borland)) +    return; -    bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && -                   StrRef.back() == '}'; +  StringRef StrRef; +  SourceLocation LiteralLoc; +  if (!S.checkStringLiteralArgumentAttr(Attr, 0, StrRef, &LiteralLoc)) +    return; -    // Validate GUID length. -    if (IsCurly && StrRef.size() != 38) { -      S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); -      return; -    } -    if (!IsCurly && StrRef.size() != 36) { -      S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); -      return; -    } +  // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or +  // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}", normalize to the former. +  if (StrRef.size() == 38 && StrRef.front() == '{' && StrRef.back() == '}') +    StrRef = StrRef.drop_front().drop_back(); -    // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or -    // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" -    StringRef::iterator I = StrRef.begin(); -    if (IsCurly) // Skip the optional '{' -       ++I; +  // Validate GUID length. +  if (StrRef.size() != 36) { +    S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); +    return; +  } -    for (int i = 0; i < 36; ++i) { -      if (i == 8 || i == 13 || i == 18 || i == 23) { -        if (*I != '-') { -          S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); -          return; -        } -      } else if (!isHexDigit(*I)) { -        S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); +  for (unsigned i = 0; i < 36; ++i) { +    if (i == 8 || i == 13 || i == 18 || i == 23) { +      if (StrRef[i] != '-') { +        S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid);          return;        } -      I++; +    } else if (!isHexDigit(StrRef[i])) { +      S.Diag(LiteralLoc, diag::err_attribute_uuid_malformed_guid); +      return;      } +  } -    D->addAttr(::new (S.Context) -               UuidAttr(Attr.getRange(), S.Context, Str->getString(), -                        Attr.getAttributeSpellingListIndex())); -  } else -    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; +  D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, StrRef, +                                        Attr.getAttributeSpellingListIndex()));  }  static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (!S.LangOpts.MicrosoftExt) { -    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +  if (!checkMicrosoftExt(S, Attr))      return; -  }    AttributeList::Kind Kind = Attr.getKind();    if (Kind == AttributeList::AT_SingleInheritance) @@ -4656,50 +4544,78 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) {  }  static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (S.LangOpts.MicrosoftExt) { -    AttributeList::Kind Kind = Attr.getKind(); -    if (Kind == AttributeList::AT_Ptr32) -      D->addAttr( -          ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context, -                                      Attr.getAttributeSpellingListIndex())); -    else if (Kind == AttributeList::AT_Ptr64) -      D->addAttr( -          ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context, -                                      Attr.getAttributeSpellingListIndex())); -    else if (Kind == AttributeList::AT_Win64) -      D->addAttr( -          ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, -                                      Attr.getAttributeSpellingListIndex())); -  } else -    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +  if (!checkMicrosoftExt(S, Attr)) +    return; + +  AttributeList::Kind Kind = Attr.getKind(); +    if (Kind == AttributeList::AT_Win64) +    D->addAttr( +        ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, +                                    Attr.getAttributeSpellingListIndex()));  }  static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { -  if (S.LangOpts.MicrosoftExt) -    D->addAttr(::new (S.Context) -               ForceInlineAttr(Attr.getRange(), S.Context, -                               Attr.getAttributeSpellingListIndex())); -  else -    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +  if (!checkMicrosoftExt(S, Attr)) +    return; +  D->addAttr(::new (S.Context) +             ForceInlineAttr(Attr.getRange(), S.Context, +                             Attr.getAttributeSpellingListIndex())); +} + +static void handleSelectAnyAttr(Sema &S, Decl *D, const AttributeList &Attr) { +  if (!checkMicrosoftExt(S, Attr)) +    return; +  // Check linkage after possibly merging declaratinos.  See +  // checkAttributesAfterMerging(). +  D->addAttr(::new (S.Context) +             SelectAnyAttr(Attr.getRange(), S.Context, +                           Attr.getAttributeSpellingListIndex())); +} + +/// Handles semantic checking for features that are common to all attributes, +/// such as checking whether a parameter was properly specified, or the correct +/// number of arguments were passed, etc. +static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D, +                                          const AttributeList &Attr) { +  // Several attributes carry different semantics than the parsing requires, so +  // those are opted out of the common handling. +  // +  // We also bail on unknown and ignored attributes because those are handled +  // as part of the target-specific handling logic. +  if (Attr.hasCustomParsing() || +      Attr.getKind() == AttributeList::UnknownAttribute || +      Attr.getKind() == AttributeList::IgnoredAttribute) +    return false; + +  // If there are no optional arguments, then checking for the argument count +  // is trivial. +  if (Attr.getMinArgs() == Attr.getMaxArgs() && +      !checkAttributeNumArgs(S, Attr, Attr.getMinArgs())) +    return true; +  return false;  }  //===----------------------------------------------------------------------===//  // Top Level Sema Entry Points  //===----------------------------------------------------------------------===// -static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, -                                          const AttributeList &Attr) { -  switch (Attr.getKind()) { -  case AttributeList::AT_CUDADevice:  handleDeviceAttr      (S, D, Attr); break; -  case AttributeList::AT_CUDAHost:    handleHostAttr        (S, D, Attr); break; -  case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break; -  default: -    break; -  } -} +/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if +/// the attribute applies to decls.  If the attribute is a type attribute, just +/// silently ignore it if a GNU attribute. +static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, +                                 const AttributeList &Attr, +                                 bool IncludeCXX11Attributes) { +  if (Attr.isInvalid()) +    return; + +  // Ignore C++11 attributes on declarator chunks: they appertain to the type +  // instead. +  if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) +    return; + +  if (handleCommonAttributeFeatures(S, scope, D, Attr)) +    return; -static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, -                                       const AttributeList &Attr) {    switch (Attr.getKind()) {    case AttributeList::AT_IBAction:    handleIBAction(S, D, Attr); break;    case AttributeList::AT_IBOutlet:    handleIBOutlet(S, D, Attr); break; @@ -4710,15 +4626,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_VectorSize:    case AttributeList::AT_NeonVectorType:    case AttributeList::AT_NeonPolyVectorType: +  case AttributeList::AT_Ptr32: +  case AttributeList::AT_Ptr64: +  case AttributeList::AT_SPtr: +  case AttributeList::AT_UPtr:      // Ignore these, these are type attributes, handled by      // ProcessTypeAttributes.      break; -  case AttributeList::AT_CUDADevice: -  case AttributeList::AT_CUDAHost: -  case AttributeList::AT_Overloadable: -    // Ignore, this is a non-inheritable attribute, handled -    // by ProcessNonInheritableDeclAttr. -    break;    case AttributeList::AT_Alias:       handleAliasAttr       (S, D, Attr); break;    case AttributeList::AT_Aligned:     handleAlignedAttr     (S, D, Attr); break;    case AttributeList::AT_AllocSize:   handleAllocSizeAttr   (S, D, Attr); break; @@ -4739,7 +4653,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,      handleCXX11NoReturnAttr(S, D, Attr);      break;    case AttributeList::AT_Deprecated: -    handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated"); +    handleAttrWithMessage<DeprecatedAttr>(S, D, Attr);      break;    case AttributeList::AT_Destructor:  handleDestructorAttr  (S, D, Attr); break;    case AttributeList::AT_ExtVectorType: @@ -4751,15 +4665,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_Format:      handleFormatAttr      (S, D, Attr); break;    case AttributeList::AT_FormatArg:   handleFormatArgAttr   (S, D, Attr); break;    case AttributeList::AT_CUDAGlobal:  handleGlobalAttr      (S, D, Attr); break; +  case AttributeList::AT_CUDADevice:  handleDeviceAttr      (S, D, Attr); break; +  case AttributeList::AT_CUDAHost:    handleHostAttr        (S, D, Attr); break;    case AttributeList::AT_GNUInline:   handleGNUInlineAttr   (S, D, Attr); break;    case AttributeList::AT_CUDALaunchBounds:      handleLaunchBoundsAttr(S, D, Attr);      break; -  case AttributeList::AT_Mode:        handleModeAttr        (S, D, Attr); break;    case AttributeList::AT_Malloc:      handleMallocAttr      (S, D, Attr); break;    case AttributeList::AT_MayAlias:    handleMayAliasAttr    (S, D, Attr); break; +  case AttributeList::AT_Mode:        handleModeAttr        (S, D, Attr); break;    case AttributeList::AT_NoCommon:    handleNoCommonAttr    (S, D, Attr); break;    case AttributeList::AT_NonNull:     handleNonNullAttr     (S, D, Attr); break; +  case AttributeList::AT_Overloadable:handleOverloadableAttr(S, D, Attr); break;    case AttributeList::AT_ownership_returns:    case AttributeList::AT_ownership_takes:    case AttributeList::AT_ownership_holds: @@ -4785,6 +4702,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_NSBridged:      handleNSBridgedAttr(S, scope, D, Attr); break; +       +  case AttributeList::AT_ObjCBridge: +    handleObjCBridgeAttr(S, scope, D, Attr); break;    case AttributeList::AT_CFAuditedTransfer:    case AttributeList::AT_CFUnknownTransfer: @@ -4810,17 +4730,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_VecTypeHint:      handleVecTypeHint(S, D, Attr); break; -  case AttributeList::AT_Endian: -    handleEndianAttr(S, D, Attr); -    break; -    case AttributeList::AT_InitPriority:         handleInitPriorityAttr(S, D, Attr); break;    case AttributeList::AT_Packed:      handlePackedAttr      (S, D, Attr); break;    case AttributeList::AT_Section:     handleSectionAttr     (S, D, Attr); break;    case AttributeList::AT_Unavailable: -    handleAttrWithMessage<UnavailableAttr>(S, D, Attr, "unavailable"); +    handleAttrWithMessage<UnavailableAttr>(S, D, Attr);      break;    case AttributeList::AT_ArcWeakrefUnavailable:       handleArcWeakrefUnavailableAttr (S, D, Attr);  @@ -4842,6 +4758,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_TypeVisibility:      handleVisibilityAttr(S, D, Attr, true);      break; +  case AttributeList::AT_WarnUnused: +    handleWarnUnusedAttr(S, D, Attr); +    break;    case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr);      break;    case AttributeList::AT_Weak:        handleWeakAttr        (S, D, Attr); break; @@ -4876,6 +4795,8 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    case AttributeList::AT_FastCall:    case AttributeList::AT_ThisCall:    case AttributeList::AT_Pascal: +  case AttributeList::AT_MSABI: +  case AttributeList::AT_SysVABI:    case AttributeList::AT_Pcs:    case AttributeList::AT_PnaclCall:    case AttributeList::AT_IntelOclBicc: @@ -4889,7 +4810,6 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,      break;    // Microsoft attributes: -  case AttributeList::AT_MsProperty: break;    case AttributeList::AT_MsStruct:      handleMsStructAttr(S, D, Attr);      break; @@ -4902,15 +4822,22 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,      handleInheritanceAttr(S, D, Attr);      break;    case AttributeList::AT_Win64: -  case AttributeList::AT_Ptr32: -  case AttributeList::AT_Ptr64:      handlePortabilityAttr(S, D, Attr);      break;    case AttributeList::AT_ForceInline:      handleForceInlineAttr(S, D, Attr);      break; +  case AttributeList::AT_SelectAny: +    handleSelectAnyAttr(S, D, Attr); +    break;    // Thread safety attributes: +  case AttributeList::AT_AssertExclusiveLock: +    handleAssertExclusiveLockAttr(S, D, Attr); +    break; +  case AttributeList::AT_AssertSharedLock: +    handleAssertSharedLockAttr(S, D, Attr); +    break;    case AttributeList::AT_GuardedVar:      handleGuardedVarAttr(S, D, Attr);      break; @@ -4975,6 +4902,26 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,      handleAcquiredAfterAttr(S, D, Attr);      break; +  // Consumed analysis attributes. +  case AttributeList::AT_Consumable: +    handleConsumableAttr(S, D, Attr); +    break; +  case AttributeList::AT_CallableWhen: +    handleCallableWhenAttr(S, D, Attr); +    break; +  case AttributeList::AT_ParamTypestate: +    handleParamTypestateAttr(S, D, Attr); +    break; +  case AttributeList::AT_ReturnTypestate: +    handleReturnTypestateAttr(S, D, Attr); +    break; +  case AttributeList::AT_SetTypestate: +    handleSetTypestateAttr(S, D, Attr); +    break; +  case AttributeList::AT_TestTypestate: +    handleTestTypestateAttr(S, D, Attr); +    break; +    // Type safety attributes.    case AttributeList::AT_ArgumentWithTypeTag:      handleArgumentWithTypeTagAttr(S, D, Attr); @@ -4994,42 +4941,18 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D,    }  } -/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if -/// the attribute applies to decls.  If the attribute is a type attribute, just -/// silently ignore it if a GNU attribute. -static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, -                                 const AttributeList &Attr, -                                 bool NonInheritable, bool Inheritable, -                                 bool IncludeCXX11Attributes) { -  if (Attr.isInvalid()) -    return; - -  // Ignore C++11 attributes on declarator chunks: they appertain to the type -  // instead. -  if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) -    return; - -  if (NonInheritable) -    ProcessNonInheritableDeclAttr(S, scope, D, Attr); - -  if (Inheritable) -    ProcessInheritableDeclAttr(S, scope, D, Attr); -} -  /// ProcessDeclAttributeList - Apply all the decl attributes in the specified  /// attribute list to the specified decl, ignoring any type attributes.  void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,                                      const AttributeList *AttrList, -                                    bool NonInheritable, bool Inheritable,                                      bool IncludeCXX11Attributes) {    for (const AttributeList* l = AttrList; l; l = l->getNext()) -    ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable, -                         IncludeCXX11Attributes); +    ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes);    // GCC accepts    // static int a9 __attribute__((weakref));    // but that looks really pointless. We reject it. -  if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { +  if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {      Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<      cast<NamedDecl>(D)->getNameAsString();      D->dropAttr<WeakRefAttr>(); @@ -5182,11 +5105,10 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {  /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in  /// it, apply them to D.  This is a bit tricky because PD can have attributes  /// specified in many different places, and we need to find and apply them all. -void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, -                                 bool NonInheritable, bool Inheritable) { +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {    // Apply decl attributes from the DeclSpec if present.    if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) -    ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); +    ProcessDeclAttributeList(S, D, Attrs);    // Walk the declarator structure, applying decl attributes that were in a type    // position to the decl itself.  This handles cases like: @@ -5194,12 +5116,11 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD,    // when X is a decl attribute.    for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i)      if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) -      ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable, -                               /*IncludeCXX11Attributes=*/false); +      ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false);    // Finally, apply any attributes on the decl itself.    if (const AttributeList *Attrs = PD.getAttributes()) -    ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); +    ProcessDeclAttributeList(S, D, Attrs);  }  /// Is the given declaration allowed to use a forbidden type? | 
