Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td	(revision 207643)
+++ include/clang/Basic/Attr.td	(working copy)
@@ -830,9 +830,8 @@
   let Args = [VariadicUnsignedArgument<"Args">];
   let AdditionalMembers =
 [{bool isNonNull(unsigned idx) const {
-    for (args_iterator i = args_begin(), e = args_end();
-         i != e; ++i)
-      if (*i == idx)
+    for (const auto &V : args())
+      if (V == idx)
         return true;
     return false;
   } }];
Index: lib/Analysis/Consumed.cpp
===================================================================
--- lib/Analysis/Consumed.cpp	(revision 207643)
+++ lib/Analysis/Consumed.cpp	(working copy)
@@ -113,14 +113,10 @@
 static bool isCallableInState(const CallableWhenAttr *CWAttr,
                               ConsumedState State) {
   
-  CallableWhenAttr::callableState_iterator I = CWAttr->callableState_begin(),
-                                           E = CWAttr->callableState_end();
-  
-  for (; I != E; ++I) {
-    
+  for (const auto &State : CWAttr->callableStates()) {    
     ConsumedState MappedAttrState = CS_None;
     
-    switch (*I) {
+    switch (State) {
     case CallableWhenAttr::Unknown:
       MappedAttrState = CS_Unknown;
       break;
Index: lib/Analysis/ThreadSafety.cpp
===================================================================
--- lib/Analysis/ThreadSafety.cpp	(revision 207643)
+++ lib/Analysis/ThreadSafety.cpp	(working copy)
@@ -1478,12 +1478,12 @@
 }
 
 template <typename Ty>
-class has_arg_iterator {
+class has_arg_iterator_range {
   typedef char yes[1];
   typedef char no[2];
 
   template <typename Inner>
-  static yes& test(Inner *I, decltype(I->args_begin()) * = nullptr);
+  static yes& test(Inner *I, decltype(I->args()) * = nullptr);
 
   template <typename>
   static no& test(...);
@@ -1522,7 +1522,7 @@
 }
 
 template <typename AttrTy>
-static typename std::enable_if<!has_arg_iterator<AttrTy>::value,
+static typename std::enable_if<!has_arg_iterator_range<AttrTy>::value,
                                StringRef>::type
 ClassifyDiagnostic(const AttrTy *A) {
   if (const ValueDecl *VD = getValueDecl(A->getArg()))
@@ -1531,11 +1531,11 @@
 }
 
 template <typename AttrTy>
-static typename std::enable_if<has_arg_iterator<AttrTy>::value,
+static typename std::enable_if<has_arg_iterator_range<AttrTy>::value,
                                StringRef>::type
 ClassifyDiagnostic(const AttrTy *A) {
-  for (auto I = A->args_begin(), E = A->args_end(); I != E; ++I) {
-    if (const ValueDecl *VD = getValueDecl(*I))
+  for (const auto *Arg : A->args()) {
+    if (const ValueDecl *VD = getValueDecl(Arg))
       return ClassifyDiagnostic(VD);
   }
   return "mutex";
@@ -1624,10 +1624,10 @@
     return;
   }
 
-  for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
-    SExpr Mu(*I, Exp, D, SelfDecl);
+  for (const auto *Arg : Attr->args()) {
+    SExpr Mu(Arg, Exp, D, SelfDecl);
     if (!Mu.isValid())
-      SExpr::warnInvalidLock(Handler, *I, Exp, D, ClassifyDiagnostic(Attr));
+      SExpr::warnInvalidLock(Handler, Arg, Exp, D, ClassifyDiagnostic(Attr));
     else
       Mtxs.push_back_nodup(Mu);
   }
@@ -2058,10 +2058,8 @@
 
       case attr::RequiresCapability: {
         RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
-
-        for (RequiresCapabilityAttr::args_iterator I = A->args_begin(),
-             E = A->args_end(); I != E; ++I)
-          warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, *I,
+        for (auto *Arg : A->args())
+          warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
                              POK_FunctionCall, ClassifyDiagnostic(A));
         break;
       }
@@ -2068,11 +2066,8 @@
 
       case attr::LocksExcluded: {
         LocksExcludedAttr *A = cast<LocksExcludedAttr>(At);
-
-        for (LocksExcludedAttr::args_iterator I = A->args_begin(),
-            E = A->args_end(); I != E; ++I) {
-          warnIfMutexHeld(D, Exp, *I, ClassifyDiagnostic(A));
-        }
+        for (auto *Arg : A->args())
+          warnIfMutexHeld(D, Exp, Arg, ClassifyDiagnostic(A));
         break;
       }
 
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp	(revision 207643)
+++ lib/Sema/SemaChecking.cpp	(working copy)
@@ -717,11 +717,8 @@
                                   SourceLocation CallSiteLoc) {
   // Check the attributes attached to the method/function itself.
   for (const auto *NonNull : FDecl->specific_attrs<NonNullAttr>()) {
-    for (NonNullAttr::args_iterator i = NonNull->args_begin(),
-         e = NonNull->args_end();
-         i != e; ++i) {
-      CheckNonNullArgument(S, ExprArgs[*i], CallSiteLoc);
-    }
+    for (const auto &Val : NonNull->args())
+      CheckNonNullArgument(S, ExprArgs[Val], CallSiteLoc);
   }
 
   // Check the attributes on the parameters.
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp	(revision 207643)
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp	(working copy)
@@ -921,9 +921,8 @@
   ProgramStateRef State = C.getState();
   bool ReleasedAllocated = false;
 
-  for (OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
-       I != E; ++I) {
-    ProgramStateRef StateI = FreeMemAux(C, CE, State, *I,
+  for (const auto &Arg : Att->args()) {
+    ProgramStateRef StateI = FreeMemAux(C, CE, State, Arg,
                                Att->getOwnKind() == OwnershipAttr::Holds,
                                ReleasedAllocated);
     if (StateI)
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp	(revision 207643)
+++ utils/TableGen/ClangAttrEmitter.cpp	(working copy)
@@ -504,32 +504,56 @@
   };
 
   class VariadicArgument : public Argument {
-    std::string type;
+    std::string Type;
+    std::string ArgName, ArgSizeName;
 
+    /// \brief Cheaply pluralize the given string.
+    /// Eg) arg --> args, copy --> copies
+    /// This is not meant for general-purpose use, but since the strings passed
+    /// in come solely from Attr.td, and are only for use with variadic
+    /// arguments, we can special case situations as needed. Note that any input
+    /// ending with "s" is assumed to already be plural.
+    static std::string pluralize(const StringRef Str) {
+      // Any input that ends with "s" is assumed to already be in plural form.
+      if (Str.endswith("s"))
+        return Str.str();
+      
+      // If it ends with a "y", assume it can be transformed into "ies" form.
+      if (Str.endswith("y"))
+        return Str.drop_back().str() + "ies";
+
+      // Otherwise, assume we can simply tack on an "s" to pluralize.
+      return Str.str() + "s";
+    }
+
   public:
     VariadicArgument(Record &Arg, StringRef Attr, std::string T)
-      : Argument(Arg, Attr), type(T)
-    {}
+        : Argument(Arg, Attr), Type(T), ArgName(getLowerName().str() + "_"),
+          ArgSizeName(ArgName + "Size") {}
 
-    std::string getType() const { return type; }
+    std::string getType() const { return Type; }
 
     void writeAccessors(raw_ostream &OS) const override {
-      OS << "  typedef " << type << "* " << getLowerName() << "_iterator;\n";
-      OS << "  " << getLowerName() << "_iterator " << getLowerName()
-         << "_begin() const {\n";
-      OS << "    return " << getLowerName() << ";\n";
+      std::string IteratorType = getLowerName().str() + "_iterator";
+      std::string BeginFn = getLowerName().str() + "_begin()";
+      std::string EndFn = getLowerName().str() + "_end()";
+      
+      OS << "  typedef " << Type << "* " << IteratorType << ";\n";
+      OS << "  " << IteratorType << " " << BeginFn << " const {";
+      OS << "    return " << ArgName << ";";
       OS << "  }\n";
-      OS << "  " << getLowerName() << "_iterator " << getLowerName()
-         << "_end() const {\n";
-      OS << "    return " << getLowerName() << " + " << getLowerName()
-         << "Size;\n";
+      OS << "  " << IteratorType << " " << EndFn << " const {";
+      OS << "    return " << ArgName << " + " << ArgSizeName << ";";
       OS << "  }\n";
       OS << "  unsigned " << getLowerName() << "_size() const {\n"
-         << "    return " << getLowerName() << "Size;\n";
-      OS << "  }";
+         << "    return " << ArgSizeName << ";\n";
+      OS << "  }\n";
+      OS << "  llvm::iterator_range<" << IteratorType << "> "
+         << pluralize(getLowerName()) << "() const { return llvm::make_range("
+         << BeginFn << ", " << EndFn << "); }\n";
     }
     void writeCloneArgs(raw_ostream &OS) const override {
-      OS << getLowerName() << ", " << getLowerName() << "Size";
+      OS << ArgName << ", " << ArgSizeName;
     }
     void writeTemplateInstantiationArgs(raw_ostream &OS) const override {
       // This isn't elegant, but we have to go through public methods...
@@ -538,16 +562,16 @@
     }
     void writeCtorBody(raw_ostream &OS) const override {
       // FIXME: memcpy is not safe on non-trivial types.
-      OS << "    std::memcpy(" << getLowerName() << ", " << getUpperName()
-         << ", " << getLowerName() << "Size * sizeof(" << getType() << "));\n";
+      OS << "    std::memcpy(" << ArgName << ", " << getUpperName()
+         << ", " << ArgSizeName << " * sizeof(" << getType() << "));\n";
     }
     void writeCtorInitializers(raw_ostream &OS) const override {
-      OS << getLowerName() << "Size(" << getUpperName() << "Size), "
-         << getLowerName() << "(new (Ctx, 16) " << getType() << "["
-         << getLowerName() << "Size])";
+      OS << ArgSizeName << "(" << getUpperName() << "Size), "
+         << ArgName << "(new (Ctx, 16) " << getType() << "["
+         << ArgSizeName << "])";
     }
     void writeCtorDefaultInitializers(raw_ostream &OS) const override {
-      OS << getLowerName() << "Size(0), " << getLowerName() << "(0)";
+      OS << ArgSizeName << "(0), " << ArgName << "(nullptr)";
     }
     void writeCtorParameters(raw_ostream &OS) const override {
       OS << getType() << " *" << getUpperName() << ", unsigned "
@@ -557,18 +581,18 @@
       OS << getUpperName() << ", " << getUpperName() << "Size";
     }
     void writeDeclarations(raw_ostream &OS) const override {
-      OS << "  unsigned " << getLowerName() << "Size;\n";
-      OS << "  " << getType() << " *" << getLowerName() << ";";
+      OS << "  unsigned " << ArgSizeName << ";\n";
+      OS << "  " << getType() << " *" << ArgName << ";";
     }
     void writePCHReadDecls(raw_ostream &OS) const override {
       OS << "  unsigned " << getLowerName() << "Size = Record[Idx++];\n";
-      OS << "  SmallVector<" << type << ", 4> " << getLowerName()
+      OS << "  SmallVector<" << Type << ", 4> " << getLowerName()
          << ";\n";
       OS << "  " << getLowerName() << ".reserve(" << getLowerName()
          << "Size);\n";
       OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
       
-      std::string read = ReadPCHRecord(type);
+      std::string read = ReadPCHRecord(Type);
       OS << "    " << getLowerName() << ".push_back(" << read << ");\n";
     }
     void writePCHReadArgs(raw_ostream &OS) const override {
@@ -576,28 +600,23 @@
     }
     void writePCHWrite(raw_ostream &OS) const override {
       OS << "    Record.push_back(SA->" << getLowerName() << "_size());\n";
-      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
-         << "_iterator i = SA->" << getLowerName() << "_begin(), e = SA->"
-         << getLowerName() << "_end(); i != e; ++i)\n";
-      OS << "      " << WritePCHRecord(type, "(*i)");
+      OS << "    for (auto &Val : SA->" << pluralize(getLowerName()) << "())\n";
+      OS << "      " << WritePCHRecord(Type, "Val");
     }
     void writeValue(raw_ostream &OS) const override {
       OS << "\";\n";
       OS << "  bool isFirst = true;\n"
-         << "  for (" << getAttrName() << "Attr::" << getLowerName()
-         << "_iterator i = " << getLowerName() << "_begin(), e = "
-         << getLowerName() << "_end(); i != e; ++i) {\n"
+         << "  for (const auto &Val : " << pluralize(getLowerName()) << "()) {\n"
          << "    if (isFirst) isFirst = false;\n"
          << "    else OS << \", \";\n"
-         << "    OS << *i;\n"
+         << "    OS << Val;\n"
          << "  }\n";
       OS << "  OS << \"";
     }
     void writeDump(raw_ostream &OS) const override {
-      OS << "    for (" << getAttrName() << "Attr::" << getLowerName()
-         << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->"
-         << getLowerName() << "_end(); I != E; ++I)\n";
-      OS << "      OS << \" \" << *I;\n";
+      OS << "    for (const auto &Val : SA->" << pluralize(getLowerName())
+         << "())\n";
+      OS << "      OS << \" \" << Val;\n";
     }
   };
 
