diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index 94470cb..2864892
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -225,12 +225,32 @@ public:
 
   SourceLocation getLocation() const LLVM_READONLY { return Loc; }
 
-  typedef Comment * const *child_iterator;
+  /** The iterator for mutable access.
+   *
+   * Iterate over a number of modifieable comments.
+   * For most use-cases the const_child_iterator should be the first choice.
+   * !!! The declaration has changed: When experiecing compile errors concerning
+   *     the constness of the Comment object, then try using the
+   *     const_child_iterator. */
+  typedef Comment** child_iterator;
+  typedef llvm::iterator_range<child_iterator> child_range;
 
-  child_iterator child_begin() const;
-  child_iterator child_end() const;
+  child_range children();
 
-  // TODO: const child iterator
+  child_iterator child_begin() { return children().begin(); }
+  child_iterator child_end() { return children().end(); }
+
+  // const child iterator
+  typedef Comment* const* const_child_iterator;
+  typedef llvm::iterator_range<const_child_iterator> const_child_range;
+
+  const_child_range children() const {
+    auto Children = const_cast<Comment *>(this)->children();
+    return const_child_range(Children.begin(), Children.end());
+  }
+
+  const_child_iterator child_begin() const { return children().begin(); }
+  const_child_iterator child_end() const { return children().end(); }
 
   unsigned child_count() const {
     return child_end() - child_begin();
@@ -280,9 +300,8 @@ public:
     return C->getCommentKind() == TextCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 
   StringRef getText() const LLVM_READONLY { return Text; }
 
@@ -338,9 +357,8 @@ public:
     return C->getCommentKind() == InlineCommandCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 
   unsigned getCommandID() const {
     return InlineCommandCommentBits.CommandID;
@@ -471,9 +489,8 @@ public:
     return C->getCommentKind() == HTMLStartTagCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 
   unsigned getNumAttrs() const {
     return Attributes.size();
@@ -526,9 +543,8 @@ public:
     return C->getCommentKind() == HTMLEndTagCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 };
 
 /// Block content (contains inline content).
@@ -550,10 +566,10 @@ public:
 
 /// A single paragraph that contains inline content.
 class ParagraphComment : public BlockContentComment {
-  ArrayRef<InlineContentComment *> Content;
+  MutableArrayRef<InlineContentComment *> Content;
 
 public:
-  ParagraphComment(ArrayRef<InlineContentComment *> Content) :
+  ParagraphComment(MutableArrayRef<InlineContentComment *> Content) :
       BlockContentComment(ParagraphCommentKind,
                           SourceLocation(),
                           SourceLocation()),
@@ -575,12 +591,13 @@ public:
     return C->getCommentKind() == ParagraphCommentKind;
   }
 
-  child_iterator child_begin() const {
-    return reinterpret_cast<child_iterator>(Content.begin());
+  child_range children() {
+    return child_range(reinterpret_cast<child_iterator>(Content.begin()),
+                       reinterpret_cast<child_iterator>(Content.end()));
   }
-
-  child_iterator child_end() const {
-    return reinterpret_cast<child_iterator>(Content.end());
+  const_child_range children() const {
+    return const_child_range(reinterpret_cast<const_child_iterator>(Content.begin()),
+                             reinterpret_cast<const_child_iterator>(Content.end()));
   }
 
   bool isWhitespace() const {
@@ -611,7 +628,7 @@ public:
 
 protected:
   /// Word-like arguments.
-  ArrayRef<Argument> Args;
+  MutableArrayRef<Argument> Args;
 
   /// Paragraph argument.
   ParagraphComment *Paragraph;
@@ -645,12 +662,13 @@ public:
            C->getCommentKind() <= LastBlockCommandCommentConstant;
   }
 
-  child_iterator child_begin() const {
-    return reinterpret_cast<child_iterator>(&Paragraph);
+  child_range children() {
+    return child_range(reinterpret_cast<child_iterator>(&Paragraph),
+                       reinterpret_cast<child_iterator>(&Paragraph + 1));
   }
-
-  child_iterator child_end() const {
-    return reinterpret_cast<child_iterator>(&Paragraph + 1);
+  const_child_range children() const {
+    return const_child_range(reinterpret_cast<const_child_iterator>(&Paragraph),
+                             reinterpret_cast<const_child_iterator>(&Paragraph + 1));
   }
 
   unsigned getCommandID() const {
@@ -683,7 +701,7 @@ public:
     return Args[Idx].Range;
   }
 
-  void setArgs(ArrayRef<Argument> A) {
+  void setArgs(MutableArrayRef<Argument> A) {
     Args = A;
     if (Args.size() > 0) {
       SourceLocation NewLocEnd = Args.back().Range.getEnd();
@@ -882,9 +900,8 @@ public:
     return C->getCommentKind() == VerbatimBlockLineCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 
   StringRef getText() const LLVM_READONLY {
     return Text;
@@ -898,7 +915,7 @@ class VerbatimBlockComment : public BlockCommandComment {
 protected:
   StringRef CloseName;
   SourceLocation CloseNameLocBegin;
-  ArrayRef<VerbatimBlockLineComment *> Lines;
+  MutableArrayRef<VerbatimBlockLineComment *> Lines;
 
 public:
   VerbatimBlockComment(SourceLocation LocBegin,
@@ -913,12 +930,13 @@ public:
     return C->getCommentKind() == VerbatimBlockCommentKind;
   }
 
-  child_iterator child_begin() const {
-    return reinterpret_cast<child_iterator>(Lines.begin());
+  child_range children() {
+    return child_range(reinterpret_cast<child_iterator>(Lines.begin()),
+                       reinterpret_cast<child_iterator>(Lines.end()));
   }
-
-  child_iterator child_end() const {
-    return reinterpret_cast<child_iterator>(Lines.end());
+  const_child_range children() const {
+    return const_child_range(reinterpret_cast<const_child_iterator>(Lines.begin()),
+                             reinterpret_cast<const_child_iterator>(Lines.end()));
   }
 
   void setCloseName(StringRef Name, SourceLocation LocBegin) {
@@ -926,7 +944,7 @@ public:
     CloseNameLocBegin = LocBegin;
   }
 
-  void setLines(ArrayRef<VerbatimBlockLineComment *> L) {
+  void setLines(MutableArrayRef<VerbatimBlockLineComment *> L) {
     Lines = L;
   }
 
@@ -969,9 +987,8 @@ public:
     return C->getCommentKind() == VerbatimLineCommentKind;
   }
 
-  child_iterator child_begin() const { return nullptr; }
-
-  child_iterator child_end() const { return nullptr; }
+  child_range children() { return child_range(nullptr, nullptr); }
+  const_child_range children() const { return const_child_range(nullptr, nullptr); }
 
   StringRef getText() const {
     return Text;
@@ -1095,11 +1112,11 @@ struct DeclInfo {
 
 /// A full comment attached to a declaration, contains block content.
 class FullComment : public Comment {
-  ArrayRef<BlockContentComment *> Blocks;
+  MutableArrayRef<BlockContentComment *> Blocks;
   DeclInfo *ThisDeclInfo;
 
 public:
-  FullComment(ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
+  FullComment(MutableArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
       Comment(FullCommentKind, SourceLocation(), SourceLocation()),
       Blocks(Blocks), ThisDeclInfo(D) {
     if (Blocks.empty())
@@ -1114,12 +1131,13 @@ public:
     return C->getCommentKind() == FullCommentKind;
   }
 
-  child_iterator child_begin() const {
-    return reinterpret_cast<child_iterator>(Blocks.begin());
+  child_range children() {
+    return child_range(reinterpret_cast<child_iterator>(Blocks.begin()),
+                       reinterpret_cast<child_iterator>(Blocks.end()));
   }
-
-  child_iterator child_end() const {
-    return reinterpret_cast<child_iterator>(Blocks.end()); 
+  const_child_range children() const {
+    return const_child_range(reinterpret_cast<const_child_iterator>(Blocks.begin()),
+                             reinterpret_cast<const_child_iterator>(Blocks.end()));
   }
 
   const Decl *getDecl() const LLVM_READONLY {
@@ -1132,8 +1150,7 @@ public:
     return ThisDeclInfo;
   }
   
-  ArrayRef<BlockContentComment *> getBlocks() const { return Blocks; }
-  
+  MutableArrayRef<BlockContentComment *> getBlocks() { return Blocks; }
 };
 } // end namespace comments
 } // end namespace clang
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 6a80383..0b2f0d6
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -84,8 +84,18 @@ public:
     return None;
   }
 
-  ParagraphComment *actOnParagraphComment(
-      ArrayRef<InlineContentComment *> Content);
+  template<typename T>
+  MutableArrayRef<T> copyArray(MutableArrayRef<T> Source) {
+    if (!Source.empty())
+    {
+      T *Buff = Allocator.template Allocate<T>(Source.size());
+      std::uninitialized_copy(Source.begin(), Source.end(), Buff);
+      return MutableArrayRef<T>(Buff, Source.size());
+    }
+    return None;
+  }
+
+  ParagraphComment *actOnParagraphComment(MutableArrayRef<InlineContentComment*> Content);
 
   BlockCommandComment *actOnBlockCommandStart(SourceLocation LocBegin,
                                               SourceLocation LocEnd,
@@ -93,7 +103,7 @@ public:
                                               CommandMarkerKind CommandMarker);
 
   void actOnBlockCommandArgs(BlockCommandComment *Command,
-                             ArrayRef<BlockCommandComment::Argument> Args);
+                             MutableArrayRef<BlockCommandComment::Argument> Args);
 
   void actOnBlockCommandFinish(BlockCommandComment *Command,
                                ParagraphComment *Paragraph);
@@ -161,7 +171,7 @@ public:
   void actOnVerbatimBlockFinish(VerbatimBlockComment *Block,
                                 SourceLocation CloseNameLocBegin,
                                 StringRef CloseName,
-                                ArrayRef<VerbatimBlockLineComment *> Lines);
+                                MutableArrayRef<VerbatimBlockLineComment*> Lines);
 
   VerbatimLineComment *actOnVerbatimLine(SourceLocation LocBegin,
                                          unsigned CommandID,
@@ -180,7 +190,7 @@ public:
                                      SourceLocation LocEnd,
                                      StringRef TagName);
 
-  FullComment *actOnFullComment(ArrayRef<BlockContentComment *> Blocks);
+  FullComment *actOnFullComment(MutableArrayRef<BlockContentComment*> Blocks);
 
   void checkBlockCommandEmptyParagraph(BlockCommandComment *Command);
 
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 05d8da2..07315f9
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2301,9 +2301,8 @@ void ASTDumper::dumpComment(const Comment *C) {
     dumpPointer(C);
     dumpSourceRange(C->getSourceRange());
     ConstCommentVisitor<ASTDumper>::visit(C);
-    for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-         I != E; ++I)
-      dumpComment(*I);
+    for (Comment const* I : C->children())
+      dumpComment(I);
   });
 }
 
diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp
index d05c5de..e85e78f
--- a/lib/AST/Comment.cpp
+++ b/lib/AST/Comment.cpp
@@ -34,29 +34,30 @@ const char *Comment::getCommentKindName() const {
 }
 
 namespace {
-struct good {};
-struct bad {};
+  struct good {};
+  struct bad {};
 
-template <typename T>
-good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
-  return good();
-}
+  static inline good is_good(good) { return good(); }
 
-LLVM_ATTRIBUTE_UNUSED
-static inline bad implements_child_begin_end(
-                      Comment::child_iterator (Comment::*)() const) {
-  return bad();
-}
+  template <class T>
+  good implements_children(Comment::child_range (T::*)()) {
+    return good();
+  }
 
-#define ASSERT_IMPLEMENTS_child_begin(function) \
-  (void) good(implements_child_begin_end(function))
+  LLVM_ATTRIBUTE_UNUSED
+  static inline bad implements_children(
+                        Comment::child_range (Comment::*)()) {
+    return bad();
+  }
+
+#define ASSERT_IMPLEMENTS_children(type) \
+  (void) is_good(implements_children(&type::children))
 
 LLVM_ATTRIBUTE_UNUSED
 static inline void CheckCommentASTNodes() {
 #define ABSTRACT_COMMENT(COMMENT)
 #define COMMENT(CLASS, PARENT) \
-  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
-  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
+  ASSERT_IMPLEMENTS_children(CLASS);
 #include "clang/AST/CommentNodes.inc"
 #undef COMMENT
 #undef ABSTRACT_COMMENT
@@ -66,27 +67,13 @@ static inline void CheckCommentASTNodes() {
 
 } // end unnamed namespace
 
-Comment::child_iterator Comment::child_begin() const {
-  switch (getCommentKind()) {
-  case NoCommentKind: llvm_unreachable("comment without a kind");
-#define ABSTRACT_COMMENT(COMMENT)
-#define COMMENT(CLASS, PARENT) \
-  case CLASS##Kind: \
-    return static_cast<const CLASS *>(this)->child_begin();
-#include "clang/AST/CommentNodes.inc"
-#undef COMMENT
-#undef ABSTRACT_COMMENT
-  }
-  llvm_unreachable("Unknown comment kind!");
-}
-
-Comment::child_iterator Comment::child_end() const {
+Comment::child_range Comment::children() {
   switch (getCommentKind()) {
   case NoCommentKind: llvm_unreachable("comment without a kind");
 #define ABSTRACT_COMMENT(COMMENT)
 #define COMMENT(CLASS, PARENT) \
   case CLASS##Kind: \
-    return static_cast<const CLASS *>(this)->child_end();
+        return static_cast< CLASS *>(this)->children();
 #include "clang/AST/CommentNodes.inc"
 #undef COMMENT
 #undef ABSTRACT_COMMENT
@@ -104,7 +91,7 @@ bool TextComment::isWhitespaceNoCache() const {
 }
 
 bool ParagraphComment::isWhitespaceNoCache() const {
-  for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
+  for (const_child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
     if (const TextComment *TC = dyn_cast<TextComment>(*I)) {
       if (!TC->isWhitespace())
         return false;
diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp
index cb37ec3..7b990af
--- a/lib/AST/CommentParser.cpp
+++ b/lib/AST/CommentParser.cpp
@@ -305,7 +305,7 @@ void Parser::parseBlockCommandArgs(BlockCommandComment *BC,
     ParsedArgs++;
   }
 
-  S.actOnBlockCommandArgs(BC, llvm::makeArrayRef(Args, ParsedArgs));
+  S.actOnBlockCommandArgs(BC, llvm::MutableArrayRef<Argument>(Args, ParsedArgs));
 }
 
 BlockCommandComment *Parser::parseBlockCommand() {
@@ -649,7 +649,7 @@ BlockContentComment *Parser::parseParagraphOrBlockCommand() {
     break;
   }
 
-  return S.actOnParagraphComment(S.copyArray(llvm::makeArrayRef(Content)));
+  return S.actOnParagraphComment(S.copyArray(llvm::MutableArrayRef<InlineContentComment *>(Content)));
 }
 
 VerbatimBlockComment *Parser::parseVerbatimBlock() {
@@ -688,12 +688,12 @@ VerbatimBlockComment *Parser::parseVerbatimBlock() {
     const CommandInfo *Info = Traits.getCommandInfo(Tok.getVerbatimBlockID());
     S.actOnVerbatimBlockFinish(VB, Tok.getLocation(),
                                Info->Name,
-                               S.copyArray(llvm::makeArrayRef(Lines)));
+                               S.copyArray(llvm::MutableArrayRef<VerbatimBlockLineComment *>(Lines)));
     consumeToken();
   } else {
     // Unterminated \\verbatim block
     S.actOnVerbatimBlockFinish(VB, SourceLocation(), "",
-                               S.copyArray(llvm::makeArrayRef(Lines)));
+                               S.copyArray(llvm::MutableArrayRef<VerbatimBlockLineComment *>(Lines)));
   }
 
   return VB;
@@ -769,7 +769,7 @@ FullComment *Parser::parseFullComment() {
     while (Tok.is(tok::newline))
       consumeToken();
   }
-  return S.actOnFullComment(S.copyArray(llvm::makeArrayRef(Blocks)));
+  return S.actOnFullComment(S.copyArray(llvm::MutableArrayRef<BlockContentComment *>(Blocks)));
 }
 
 } // end namespace comments
diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp
index f5f4f70..b2aaff5
--- a/lib/AST/CommentSema.cpp
+++ b/lib/AST/CommentSema.cpp
@@ -43,7 +43,7 @@ void Sema::setDecl(const Decl *D) {
 }
 
 ParagraphComment *Sema::actOnParagraphComment(
-                              ArrayRef<InlineContentComment *> Content) {
+                              MutableArrayRef<InlineContentComment *> Content) {
   return new (Allocator) ParagraphComment(Content);
 }
 
@@ -60,7 +60,7 @@ BlockCommandComment *Sema::actOnBlockCommandStart(
 }
 
 void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
-                                 ArrayRef<BlockCommandComment::Argument> Args) {
+                                 MutableArrayRef<BlockCommandComment::Argument> Args) {
   Command->setArgs(Args);
 }
 
@@ -269,7 +269,7 @@ void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                      ArgLocEnd),
                                          Arg);
-  Command->setArgs(llvm::makeArrayRef(A, 1));
+  Command->setArgs(llvm::MutableArrayRef<Argument>(A, 1));
 }
 
 void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
@@ -307,7 +307,7 @@ void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                      ArgLocEnd),
                                          Arg);
-  Command->setArgs(llvm::makeArrayRef(A, 1));
+  Command->setArgs(llvm::MutableArrayRef<Argument>(A, 1));
 
   if (!isTemplateOrSpecialization()) {
     // We already warned that this \\tparam is not attached to a template decl.
@@ -435,7 +435,7 @@ void Sema::actOnVerbatimBlockFinish(
                             VerbatimBlockComment *Block,
                             SourceLocation CloseNameLocBegin,
                             StringRef CloseName,
-                            ArrayRef<VerbatimBlockLineComment *> Lines) {
+                            MutableArrayRef<VerbatimBlockLineComment *> Lines) {
   Block->setCloseName(CloseName, CloseNameLocBegin);
   Block->setLines(Lines);
 }
@@ -542,7 +542,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
 }
 
 FullComment *Sema::actOnFullComment(
-                              ArrayRef<BlockContentComment *> Blocks) {
+                              MutableArrayRef<BlockContentComment *> Blocks) {
   FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
   resolveParamCommandIndexes(FC);
 
@@ -725,9 +725,8 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) {
   ParamVarDocs.resize(ParamVars.size(), nullptr);
 
   // First pass over all \\param commands: resolve all parameter names.
-  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
-       I != E; ++I) {
-    ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
+  for (auto* I : FC->children()) {
+    ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(I);
     if (!PCC || !PCC->hasParamName())
       continue;
     StringRef ParamName = PCC->getParamNameAsWritten();
diff --git a/lib/Index/CommentToXML.cpp b/lib/Index/CommentToXML.cpp
index c4beef2..69b17b5
--- a/lib/Index/CommentToXML.cpp
+++ b/lib/Index/CommentToXML.cpp
@@ -97,9 +97,7 @@ struct FullCommentParts {
 FullCommentParts::FullCommentParts(const FullComment *C,
                                    const CommandTraits &Traits) :
     Brief(nullptr), Headerfile(nullptr), FirstParagraph(nullptr) {
-  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-       I != E; ++I) {
-    const Comment *Child = *I;
+  for (auto const* Child : C->children()) {
     if (!Child)
       continue;
     switch (Child->getCommentKind()) {
@@ -321,9 +319,8 @@ void CommentASTToHTMLConverter::visitParagraphComment(
     return;
 
   Result << "<p>";
-  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-       I != E; ++I) {
-    visit(*I);
+  for (auto const* I : C->children()) {
+    visit(I);
   }
   Result << "</p>";
 }
@@ -488,9 +485,8 @@ void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
   if (!C)
     return;
 
-  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-       I != E; ++I) {
-    visit(*I);
+  for (auto const *I : C->children()) {
+    visit(I);
   }
 }
 
@@ -699,9 +695,8 @@ void CommentASTToXMLConverter::appendParagraphCommentWithKind(
   else
     Result << "<Para kind=\"" << ParagraphKind << "\">";
 
-  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
-       I != E; ++I) {
-    visit(*I);
+  for (auto const* I : C->children()) {
+    visit(I);
   }
   Result << "</Para>";
 }
diff --git a/unittests/AST/CommentParser.cpp b/unittests/AST/CommentParser.cpp
index f6ef9b9..b337745
--- a/unittests/AST/CommentParser.cpp
+++ b/unittests/AST/CommentParser.cpp
@@ -101,7 +101,7 @@ template <typename T>
         << "Idx out of range.  Idx = " << Idx
         << ", child_count = " << C->child_count();
 
-  Comment::child_iterator I = C->child_begin() + Idx;
+  Comment::const_child_iterator I = C->child_begin() + Idx;
   Comment *CommentChild = *I;
   if (!CommentChild)
     return ::testing::AssertionFailure() << "Child is NULL";
