Consolidating the notion of a GNU attribute parameter with the attribute argument list.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189711 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index b9e4ef0..00f8af9 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -419,7 +419,7 @@
                                          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
@@ -815,7 +815,7 @@
     return false;
   }
 
-  if (!isIntOrBool(Attr.getArg(0))) {
+  if (!isIntOrBool(Attr.getArgAsExpr(0))) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
       << Attr.getName() << 1 << AANT_ArgumentIntOrBool;
     return false;
@@ -833,11 +833,10 @@
   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()));
 }
 
@@ -847,11 +846,10 @@
   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()));
 }
 
@@ -1177,7 +1175,7 @@
                                      const AttributeList &Attr) {
 
   // The iboutletcollection attribute can have zero or one arguments.
-  if (Attr.getParameterName() && Attr.getNumArgs() > 0) {
+  if (Attr.getNumArgs() > 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
       << Attr.getName() << 1;
     return;
@@ -1186,9 +1184,15 @@
   if (!checkIBOutletCommon(S, D, Attr))
     return;
 
-  IdentifierInfo *II = Attr.getParameterName();
-  if (!II)
+  IdentifierLoc *IL = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
+  IdentifierInfo *II;
+  SourceLocation ILS;
+  if (IL) {
+    II = IL->Ident;
+    ILS = IL->Loc;
+  } else {
     II = &S.Context.Idents.get("NSObject");
+  }
   
   ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), 
                         S.getScopeForContext(D->getDeclContext()->getParent()));
@@ -1206,8 +1210,7 @@
     return;
   }
   D->addAttr(::new (S.Context)
-             IBOutletCollectionAttr(Attr.getRange(),S.Context,
-                                    QT, Attr.getParameterLoc(),
+             IBOutletCollectionAttr(Attr.getRange(), S.Context, QT, ILS,
                                     Attr.getAttributeSpellingListIndex()));
 }
 
@@ -1238,7 +1241,7 @@
 
   SmallVector<unsigned, 8> SizeArgs;
   for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
-    Expr *Ex = Attr.getArg(i);
+    Expr *Ex = Attr.getArgAsExpr(i);
     uint64_t Idx;
     if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
                                             Attr.getLoc(), i + 1, Ex, Idx))
@@ -1278,7 +1281,7 @@
 
   SmallVector<unsigned, 8> NonNullArgs;
   for (unsigned i = 0; i < Attr.getNumArgs(); ++i) {
-    Expr *Ex = Attr.getArg(i);
+    Expr *Ex = Attr.getArgAsExpr(i);
     uint64_t Idx;
     if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
                                             Attr.getLoc(), i + 1, Ex, Idx))
@@ -1336,7 +1339,7 @@
   // after being held.  free() should be __attribute((ownership_takes)), whereas
   // a list append function may well be __attribute((ownership_holds)).
 
-  if (!AL.getParameterName()) {
+  if (!AL.isArgIdent(0)) {
     S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
       << AL.getName()->getName() << 1 << AANT_ArgumentString;
     return;
@@ -1346,7 +1349,7 @@
   switch (AL.getKind()) {
   case AttributeList::AT_ownership_takes:
     K = OwnershipAttr::Takes;
-    if (AL.getNumArgs() < 1) {
+    if (AL.getNumArgs() < 2) {
       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
         << AL.getName() << 2;
       return;
@@ -1354,7 +1357,7 @@
     break;
   case AttributeList::AT_ownership_holds:
     K = OwnershipAttr::Holds;
-    if (AL.getNumArgs() < 1) {
+    if (AL.getNumArgs() < 2) {
       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
         << AL.getName() << 2;
       return;
@@ -1362,9 +1365,9 @@
     break;
   case AttributeList::AT_ownership_returns:
     K = OwnershipAttr::Returns;
-    if (AL.getNumArgs() > 1) {
+    if (AL.getNumArgs() > 2) {
       S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
-        << AL.getName() << AL.getNumArgs() + 1;
+        << AL.getName() << AL.getNumArgs() + 2;
       return;
     }
     break;
@@ -1379,7 +1382,7 @@
     return;
   }
 
-  StringRef Module = AL.getParameterName()->getName();
+  StringRef Module = AL.getArgAsIdent(0)->Ident->getName();
 
   // Normalize the argument, __foo__ becomes foo.
   if (Module.startswith("__") && Module.endswith("__"))
@@ -1387,11 +1390,11 @@
 
 
   SmallVector<unsigned, 8> OwnershipArgs;
-  for (unsigned i = 0; i < AL.getNumArgs(); ++i) {
-    Expr *Ex = AL.getArg(i);
+  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 + 1, Ex, Idx))
+                                            AL.getLoc(), i, Ex, Idx))
       return;
 
     switch (K) {
@@ -1410,9 +1413,9 @@
       break;
     }
     case OwnershipAttr::Returns: {
-      if (AL.getNumArgs() > 1) {
+      if (AL.getNumArgs() > 2) {
           // Is the function argument an integer type?
-          Expr *IdxExpr = AL.getArg(0);
+          Expr *IdxExpr = AL.getArgAsExpr(1);
           llvm::APSInt ArgNum(32);
           if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent()
               || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) {
@@ -1514,8 +1517,8 @@
   // 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);
+  if (Attr.isArgExpr(0)) {
+    Expr *Arg = Attr.getArgAsExpr(0);
     Arg = Arg->IgnoreParenCasts();
     StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
 
@@ -1540,9 +1543,9 @@
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  Expr *Arg = Attr.getArg(0);
-  Arg = Arg->IgnoreParenCasts();
-  StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+  StringLiteral *Str = 0;
+  if (Attr.isArgExpr(0))
+    Str = dyn_cast<StringLiteral>(Attr.getArgAsExpr(0)->IgnoreParenCasts());
 
   if (!Str || !Str->isAscii()) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
@@ -1639,11 +1642,8 @@
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (!isa<FunctionDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -1662,7 +1662,7 @@
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  Expr *Arg = Attr.getArg(0);
+  Expr *Arg = Attr.getArgAsExpr(0);
   Arg = Arg->IgnoreParenCasts();
   StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
 
@@ -1694,11 +1694,8 @@
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     QualType RetTy = FD->getResultType();
@@ -1765,9 +1762,7 @@
 }
 
 bool Sema::CheckNoReturnAttr(const AttributeList &attr) {
-  if (attr.hasParameterOrArguments()) {
-    Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-      << attr.getName() << 0;
+  if (!checkAttributeNumArgs(*this, attr, 0)) {
     attr.setInvalid();
     return true;
   }
@@ -1904,11 +1899,8 @@
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (!isa<VarDecl>(D) && !isa<ObjCIvarDecl>(D) && !isFunctionOrMethod(D) &&
       !isa<TypeDecl>(D) && !isa<LabelDecl>(D) && !isa<FieldDecl>(D)) {
@@ -1925,11 +1917,8 @@
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (!isa<FunctionDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -1944,11 +1933,8 @@
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     if (VD->hasLocalStorage()) {
@@ -1975,7 +1961,7 @@
 
   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)) {
@@ -2007,7 +1993,7 @@
 
   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)) {
@@ -2041,11 +2027,12 @@
 
   // Handle the case where the attribute has a text message.
   StringRef Str;
-  if (NumArgs == 1) {
-    StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0));
+  if (Attr.isArgExpr(0)) {
+    StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArgAsExpr(0));
     if (!SE) {
-      S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_argument_type)
-        << Attr.getName() << AANT_ArgumentString;
+      S.Diag(Attr.getArgAsExpr(0)->getLocStart(),
+             diag::err_attribute_argument_type) << Attr.getName()
+        << AANT_ArgumentString;
       return;
     }
     Str = SE->getString();
@@ -2280,13 +2267,15 @@
 
 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) {
@@ -2304,8 +2293,7 @@
   if (SE)
     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,
@@ -2369,7 +2357,7 @@
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  Expr *Arg = Attr.getArg(0);
+  Expr *Arg = Attr.getArgAsExpr(0);
   Arg = Arg->IgnoreParenCasts();
   StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
 
@@ -2424,19 +2412,18 @@
     return;
   }
 
-  if (Attr.getNumArgs() != 0 || !Attr.getParameterName()) {
-    if (!Attr.getParameterName() && Attr.getNumArgs() == 1) {
-      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
-        << Attr.getName() << 1 << AANT_ArgumentString;
-    } else {
-      S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-        << Attr.getName() << 0;
-    }
-    Attr.setInvalid();
+  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;
 
-  StringRef param = Attr.getParameterName()->getName();
+  IdentifierLoc *IL = Attr.getArgAsIdent(0);
+
+  StringRef param = IL->Ident->getName();
   ObjCMethodFamilyAttr::FamilyKind family;
   if (param == "none")
     family = ObjCMethodFamilyAttr::OMF_None;
@@ -2453,7 +2440,7 @@
   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);
+    S.Diag(IL->Loc, diag::warn_unknown_method_family);
     return;
   }
 
@@ -2533,24 +2520,22 @@
 }
 
 static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-  if (!Attr.getParameterName()) {
+  if (!Attr.isArgIdent(0)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
-      << Attr.getName() << 1 << AANT_ArgumentString;
+      << Attr.getName() << 1 << AANT_ArgumentIdentifier;
     return;
   }
-
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-      << Attr.getName() << 1;
+  
+  if (!checkAttributeNumArgs(S, Attr, 1))
     return;
-  }
 
+  IdentifierInfo *II = Attr.getArgAsIdent(0)->Ident;
   BlocksAttr::BlockType type;
-  if (Attr.getParameterName()->isStr("byref"))
+  if (II->isStr("byref"))
     type = BlocksAttr::ByRef;
   else {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
-      << "blocks" << Attr.getParameterName();
+    S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) << "blocks"
+      << II;
     return;
   }
 
@@ -2568,7 +2553,7 @@
 
   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)) {
@@ -2589,7 +2574,7 @@
 
   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)) {
@@ -2696,11 +2681,8 @@
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
     if (isa<CXXRecordDecl>(D)) {
@@ -2758,7 +2740,7 @@
 
   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)) {
@@ -2807,10 +2789,15 @@
 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 (!checkAttributeNumArgs(S, Attr, 0))
     return;
 
+  if (!Attr.hasParsedType()) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+      << Attr.getName() << 1;
+    return;
+  }
+
   QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg());
 
   if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() &&
@@ -2835,10 +2822,19 @@
 }
 
 static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) {
+  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;
+
   if (!dyn_cast<VarDecl>(D))
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian"
-                                                                << 9;
-  StringRef EndianType = Attr.getParameterName()->getName();
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedVariable;
+  StringRef EndianType = Attr.getArgAsIdent(0)->Ident->getName();
   if (EndianType != "host" && EndianType != "device")
     S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType;
 }
@@ -2864,7 +2860,7 @@
 
   // Make sure that there is a string literal as the sections's single
   // argument.
-  Expr *ArgExpr = Attr.getArg(0);
+  Expr *ArgExpr = Attr.getArgAsExpr(0);
   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
   if (!SE) {
     S.Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type)
@@ -2895,12 +2891,8 @@
 
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
   
   if (NoThrowAttr *Existing = D->getAttr<NoThrowAttr>()) {
     if (Existing->getLocation().isInvalid())
@@ -2913,12 +2905,8 @@
 }
 
 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)
-      << Attr.getName() << 0;
+  if (!checkAttributeNumArgs(S, Attr, 0))
     return;
-  }
 
   if (ConstAttr *Existing = D->getAttr<ConstAttr>()) {
    if (Existing->getLocation().isInvalid())
@@ -2941,17 +2929,14 @@
 }
 
 static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
-  if (!Attr.getParameterName()) {
+  if (!Attr.isArgIdent(0)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
       << Attr.getName() << 1;
     return;
   }
-
-  if (Attr.getNumArgs() != 0) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-      << Attr.getName() << 1;
+  
+  if (!checkAttributeNumArgs(S, Attr, 1))
     return;
-  }
 
   VarDecl *VD = dyn_cast<VarDecl>(D);
 
@@ -2960,29 +2945,27 @@
     return;
   }
 
+  IdentifierLoc *IL = Attr.getArgAsIdent(0);
+
   // 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);
+    = S.LookupSingleName(S.TUScope, IL->Ident, IL->Loc,
+                         Sema::LookupOrdinaryName);
   if (!CleanupDecl) {
-    S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) <<
-      Attr.getParameterName();
+    S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_found) << IL->Ident;
     return;
   }
 
   FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl);
   if (!FD) {
-    S.Diag(Attr.getParameterLoc(),
-           diag::err_attribute_cleanup_arg_not_function)
-      << Attr.getParameterName();
+    S.Diag(IL->Loc, diag::err_attribute_cleanup_arg_not_function) << IL->Ident;
     return;
   }
 
   if (FD->getNumParams() != 1) {
-    S.Diag(Attr.getParameterLoc(),
-           diag::err_attribute_cleanup_func_must_take_one_arg)
-      << Attr.getParameterName();
+    S.Diag(IL->Loc, diag::err_attribute_cleanup_func_must_take_one_arg)
+      << IL->Ident;
     return;
   }
 
@@ -2992,17 +2975,16 @@
   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(IL->Loc, diag::err_attribute_cleanup_func_arg_incompatible_type) <<
+      IL->Ident << 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());
+  S.MarkFunctionReferenced(IL->Loc, FD);
+  S.DiagnoseUseOfDecl(FD, IL->Loc);
 }
 
 /// Handle __attribute__((format_arg((idx)))) attribute based on
@@ -3017,7 +2999,7 @@
     return;
   }
 
-  Expr *IdxExpr = Attr.getArg(0);
+  Expr *IdxExpr = Attr.getArgAsExpr(0);
   uint64_t ArgIdx;
   if (!checkFunctionOrMethodArgumentIndex(S, D, Attr.getName()->getName(),
                                           Attr.getLoc(), 1, IdxExpr, ArgIdx))
@@ -3114,7 +3096,7 @@
     Attr.setInvalid();
     return;
   }
-  Expr *priorityExpr = Attr.getArg(0);
+  Expr *priorityExpr = Attr.getArgAsExpr(0);
   
   llvm::APSInt priority(32);
   if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() ||
@@ -3164,18 +3146,14 @@
 /// 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()) {
+  if (!Attr.isArgIdent(0)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
-      << Attr.getName() << 1 << AANT_ArgumentString;
+      << Attr.getName() << 1 << AANT_ArgumentIdentifier;
     return;
   }
-
-  if (Attr.getNumArgs() != 2) {
-    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
-      << Attr.getName() << 3;
+  
+  if (!checkAttributeNumArgs(S, Attr, 3))
     return;
-  }
 
   if (!isFunctionOrMethodOrBlock(D) || !hasFunctionProto(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -3189,7 +3167,8 @@
   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("__"))
@@ -3203,12 +3182,12 @@
   
   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)) {
@@ -3264,7 +3243,7 @@
   }
 
   // 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)) {
@@ -3381,7 +3360,7 @@
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  Expr *ArgExpr = Attr.getArg(0);
+  Expr *ArgExpr = Attr.getArgAsExpr(0);
   StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr);
 
   // Make sure that there is a string literal as the annotation's single
@@ -3419,7 +3398,7 @@
     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);
@@ -3576,20 +3555,17 @@
 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) {
+  if (!Attr.isArgIdent(0)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
       << AANT_ArgumentIdentifier;
     return;
   }
+  
+  if (!checkAttributeNumArgs(S, Attr, 1))
+    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("__"))
@@ -3808,12 +3784,8 @@
 
 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)
-        << Attr.getName() << 0;
+    if (!checkAttributeNumArgs(S, Attr, 0))
       return;
-    }
 
     if (!isa<VarDecl>(D)) {
       S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
@@ -4041,7 +4013,7 @@
 }
 
 static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){
-  Expr *E = Attr.getArg(0);
+  Expr *E = Attr.getArgAsExpr(0);
   llvm::APSInt ArgNum(32);
   if (E->isTypeDependent() || E->isValueDependent() ||
       !E->isIntegerConstantExpr(ArgNum, S.Context)) {
@@ -4061,9 +4033,7 @@
     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)
-      << attr.getName() << ReqArgs;
+  if (!checkAttributeNumArgs(*this, attr, ReqArgs)) {
     attr.setInvalid();
     return true;
   }
@@ -4085,8 +4055,10 @@
                                                              CC_C;
     break;
   case AttributeList::AT_Pcs: {
-    Expr *Arg = attr.getArg(0);
-    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+    StringLiteral *Str = 0;
+    if (attr.isArgExpr(0))
+      Str = dyn_cast<StringLiteral>(attr.getArgAsExpr(0));
+    
     if (!Str || !Str->isAscii()) {
       Diag(attr.getLoc(), diag::err_attribute_argument_type) << attr.getName()
         << AANT_ArgumentString;
@@ -4156,7 +4128,7 @@
     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)) {
@@ -4200,7 +4172,7 @@
       return;
     }
 
-    Expr *MaxThreadsExpr = Attr.getArg(0);
+    Expr *MaxThreadsExpr = Attr.getArgAsExpr(0);
     llvm::APSInt MaxThreads(32);
     if (MaxThreadsExpr->isTypeDependent() ||
         MaxThreadsExpr->isValueDependent() ||
@@ -4213,7 +4185,7 @@
 
     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)) {
@@ -4236,20 +4208,17 @@
 
 static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D,
                                           const AttributeList &Attr) {
-  StringRef AttrName = Attr.getName()->getName();
-  if (!Attr.getParameterName()) {
+  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)
-      << Attr.getName() << /* 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)
@@ -4260,13 +4229,13 @@
   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");
@@ -4287,13 +4256,16 @@
 
 static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D,
                                          const AttributeList &Attr) {
-  IdentifierInfo *PointerKind = Attr.getParameterName();
-  if (!PointerKind) {
+  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;
 
+  IdentifierInfo *PointerKind = Attr.getArgAsIdent(0)->Ident;
   QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL);
 
   D->addAttr(::new (S.Context)
@@ -4544,14 +4516,14 @@
       << 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();
@@ -4563,7 +4535,7 @@
   }
 
   D->addAttr(::new (S.Context)
-             NSBridgedAttr(Attr.getRange(), S.Context, ParmName,
+             NSBridgedAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
                            Attr.getAttributeSpellingListIndex()));
 }
 
@@ -4644,7 +4616,7 @@
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
-  Expr *Arg = Attr.getArg(0);
+  Expr *Arg = Attr.getArgAsExpr(0);
   StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
   if (!Str || !Str->isAscii()) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)