diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index ac3ff73..28c36e9 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -471,6 +471,31 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt;
 const internal::VariadicDynCastAllOfMatcher<
   Stmt, ForStmt> forStmt;
 
+/// \brief Matches the increment statement of a for loop.
+///
+/// Example:
+///     forSmt(hasIncrement(unaryOperator(hasOperatorName("++"))))
+/// matches '++x' in
+///     for (x; x < N; ++x) { }
+AST_MATCHER_P(clang::ForStmt, hasIncrement, internal::Matcher<clang::Stmt>,
+              InnerMatcher) {
+  const clang::Stmt *const Increment = Node.getInc();
+  return (Increment != NULL &&
+          InnerMatcher.matches(*Increment, Finder, Builder));
+}
+
+/// \brief Matches the initialization statement of a for loop.
+///
+/// Example:
+///     forSmt(hasLoopInit(declarationStatement()))
+/// matches 'int x = 0' in
+///     for (int x = 0; x < N; ++x) { }
+AST_MATCHER_P(clang::ForStmt, hasLoopInit, internal::Matcher<clang::Stmt>,
+              InnerMatcher) {
+  const clang::Stmt *const Init = Node.getInit();
+  return (Init != NULL && InnerMatcher.matches(*Init, Finder, Builder));
+}
+
 /// \brief Matches while statements.
 ///
 /// Given
@@ -1334,18 +1359,21 @@ AST_MATCHER_P(FunctionDecl, returns, internal::Matcher<QualType>, Matcher) {
   return Matcher.matches(Node.getResultType(), Finder, Builder);
 }
 
-/// \brief Matches the condition expression of an if statement or conditional
-/// operator.
+/// \brief Matches the condition expression of an if statement, for loop,
+/// or conditional operator.
 ///
 /// Example matches true (matcher = hasCondition(boolLiteral(equals(true))))
 ///   if (true) {}
 AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher<Expr>,
                           InnerMatcher) {
   TOOLING_COMPILE_ASSERT(
-    (llvm::is_base_of<IfStmt, NodeType>::value) ||
-    (llvm::is_base_of<ConditionalOperator, NodeType>::value),
-    has_condition_requires_if_statement_or_conditional_operator);
-  const Expr *const Condition = Node.getCond();
+    (llvm::is_base_of<clang::IfStmt, NodeType>::value) ||
+    (llvm::is_base_of<clang::ForStmt, NodeType>::value) ||
+    (llvm::is_base_of<clang::WhileStmt, NodeType>::value) ||
+    (llvm::is_base_of<clang::DoStmt, NodeType>::value) ||
+    (llvm::is_base_of<clang::ConditionalOperator, NodeType>::value),
+    has_condition_requires_if_statement_conditional_operator_or_loop);
+  const clang::Expr *const Condition = Node.getCond();
   return (Condition != NULL &&
           InnerMatcher.matches(*Condition, Finder, Builder));
 }
@@ -1393,7 +1421,8 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
   return false;
 }
 
-/// \brief Matches a 'for' statement that has a given body.
+/// \brief Matches a 'for', 'while', or 'do while' statement that has
+/// a given body.
 ///
 /// Given
 ///   for (;;) {}
@@ -1401,9 +1430,14 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
 ///   matches 'for (;;) {}'
 /// with compoundStatement()
 ///   matching '{}'
-AST_MATCHER_P(ForStmt, hasBody, internal::Matcher<Stmt>,
-              InnerMatcher) {
-  const Stmt *const Statement = Node.getBody();
+AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher<Stmt>,
+                          InnerMatcher) {
+  TOOLING_COMPILE_ASSERT(
+      (llvm::is_base_of<clang::DoStmt, NodeType>::value) ||
+      (llvm::is_base_of<clang::ForStmt, NodeType>::value) ||
+      (llvm::is_base_of<clang::WhileStmt, NodeType>::value),
+      has_body_requires_for_while_or_do_statement);
+  const clang::Stmt *const Statement = Node.getBody();
   return (Statement != NULL &&
           InnerMatcher.matches(*Statement, Finder, Builder));
 }
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index a529459..0075fca 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1747,6 +1770,20 @@ TEST(For, FindsForLoops) {
   EXPECT_TRUE(matches("void f() { if(true) for(;;); }", forStmt()));
 }
 
+TEST(For, ForLoopInternals) {
+  EXPECT_TRUE(matches("void f(){ int i; for (; i < 3 ; ); }",
+                      forStmt(hasCondition(anything()))));
+  EXPECT_TRUE(matches("void f() { for (int i = 0; ;); }",
+                      forStmt(hasLoopInit(anything()))));
+}
+
+TEST(For, NegativeForLoopInternals) {
+  EXPECT_FALSE(matches("void f(){ for (int i = 0; ; ++i); }",
+                       forStmt(hasCondition(expression()))));
+  EXPECT_FALSE(matches("void f() {int i; for (; i < 4; ++i) {} }",
+                       forStmt(hasLoopInit(anything()))));
+}
+
 TEST(For, ReportsNoFalsePositives) {
   EXPECT_TRUE(notMatches("void f() { ; }", forStmt()));
   EXPECT_TRUE(notMatches("void f() { if(true); }", forStmt()));
@@ -1767,13 +1804,15 @@ TEST(CompoundStatement, DoesNotMatchEmptyStruct) {
               compoundStatement()));
 }
 
-TEST(HasBody, FindsBodyOfForLoop) {
-  StatementMatcher HasCompoundStatementBody =
-      forStmt(hasBody(compoundStatement()));
+TEST(HasBody, FindsBodyOfForWhileDoLoops) {
   EXPECT_TRUE(matches("void f() { for(;;) {} }",
-              HasCompoundStatementBody));
+              forStmt(hasBody(compoundStatement()))));
   EXPECT_TRUE(notMatches("void f() { for(;;); }",
-              HasCompoundStatementBody));
+              forStmt(hasBody(compoundStatement()))));
+  EXPECT_TRUE(matches("void f() { while(true) {} }",
+              whileStmt(hasBody(compoundStatement()))));
+  EXPECT_TRUE(matches("void f() { do {} while(true); }",
+              doStmt(hasBody(compoundStatement()))));
 }
 
 TEST(HasAnySubstatement, MatchesForTopLevelCompoundStatement) {
