diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index d2ff604..e666047 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -50,6 +50,7 @@
 #include "clang/ASTMatchers/ASTMatchersMacros.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Regex.h"
+#include <iterator>
 
 namespace clang {
 namespace ast_matchers {
@@ -184,6 +185,70 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument,
   return false;
 }
 
+/// \brief Matches expressions that match InnerMatcher after any implicit casts
+/// are stripped off. Parentheses and explicit casts are not discarded.
+/// Given
+///   int arr[5];
+///   int a = 0;
+///   char b = 0;
+///   const int c = a;
+///   int *d = arr;
+///   long e = (long) 0l;
+/// The matchers
+///    variable(hasInitializer(ignoringImplicitCasts(integerLiteral(0))))
+///    variable(hasInitializer(ignoringImplicitCasts(declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+///    variable(hasInitializer(integerLiteral(0)))
+///    variable(hasInitializer(declarationReference()))
+/// only match the declarations for b, c, and d.
+AST_MATCHER_P(Expr, ignoringImplicitCasts,
+              internal::Matcher<Expr>, InnerMatcher) {
+  return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after parentheses
+/// are stripped off. Implicit and explicit casts are not discarded.
+/// Given
+///   int a = (0);
+///   char b = 0;
+///   char c = (0);
+///   char d = (char)0;
+/// The matcher
+///    variable(hasInitializer(ignoringParenCasts(integerLiteral(0))))
+/// would match the declarations for a, b, and c, but not d.
+/// while
+///    variable(hasInitializer(integerLiteral(0)))
+/// only match the declarations for b.
+AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) {
+  return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder);
+}
+
+/// \brief Matches expressions that match InnerMatcher after implicit casts and
+/// parentheses are stripped off. Explicit casts are not discarded.
+///
+/// Given
+///   int arr[5];
+///   int a = 0;
+///   char b = (0);
+///   const int c = a;
+///   int *d = (arr);
+///   long e = ((long) 0l);
+/// The matchers
+///    variable(hasInitializer(ignoringParenAndImplicitCasts(
+///       integerLiteral(0))))
+///    variable(hasInitializer(ignoringParenAndImplicitCasts(
+///       declarationReference())))
+/// would match the declarations for a, b, c, and d, but not e.
+/// while
+///    variable(hasInitializer(integerLiteral(0)))
+///    variable(hasInitializer(declarationReference()))
+/// would only match the declaration for a.
+AST_MATCHER_P(Expr, ignoringParenAndImplicitCasts,
+              internal::Matcher<Expr>, InnerMatcher) {
+  return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder);
+}
+
 /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
 /// matches the given Matcher.
 ///
@@ -384,6 +449,22 @@ const internal::VariadicDynCastAllOfMatcher<
   Stmt,
   CXXBindTemporaryExpr> bindTemporaryExpression;
 
+/// \brief Matches nodes where temporaries are materialized.
+///
+/// Example: Given
+///   struct T {void func()};
+///   T f();
+///   void g(T);
+/// materializeTemporaryExpression() matches 'f()' in these statements
+///   T u(f());
+///   g(f());
+/// but does not match
+///   f();
+///   f().func();
+const internal::VariadicDynCastAllOfMatcher<
+  Stmt,
+  MaterializeTemporaryExpr> materializeTemporaryExpression;
+
 /// \brief Matches new expressions.
 ///
 /// Given
@@ -672,6 +753,17 @@ const internal::VariadicDynCastAllOfMatcher<
   Expr,
   ImplicitCastExpr> implicitCast;
 
+/// \brief Matches any cast nodes of Clang's AST.
+///
+/// Example: castExpression() matches each of the following:
+///   (int) 3;
+///   const_cast<Expr *>(SubExpr);
+///   (i);
+///   char c = 0;
+const internal::VariadicDynCastAllOfMatcher<
+  Expr,
+  CastExpr> castExpression;
+
 /// \brief Matches functional cast expressions
 ///
 /// Example: Matches Foo(bar);
@@ -1541,7 +1633,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
           InnerMatcher.matches(*Operand, Finder, Builder));
 }
 
-/// \brief Matches if the implicit cast's source expression matches the given
+/// \brief Matches if the cast's source expression matches the given
 /// matcher.
 ///
 /// Example: matches "a string" (matcher =
@@ -1549,7 +1641,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand,
 ///
 /// class URL { URL(string); };
 /// URL url = "a string";
-AST_MATCHER_P(ImplicitCastExpr, hasSourceExpression,
+AST_MATCHER_P(CastExpr, hasSourceExpression,
               internal::Matcher<Expr>, InnerMatcher) {
   const Expr* const SubExpression = Node.getSubExpr();
   return (SubExpression != NULL &&
@@ -1566,6 +1658,7 @@ AST_MATCHER_P(ExplicitCastExpr, hasDestinationType,
   return InnerMatcher.matches(NodeType, Finder, Builder);
 }
 
+
 /// \brief Matches implicit casts whose destination type matches a given
 /// matcher.
 ///
diff --git a/unittests/ASTMatchers/ASTMatchersTest.cpp b/unittests/ASTMatchers/ASTMatchersTest.cpp
index 5791932..74a6c76 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -1970,6 +1970,21 @@ TEST(IsConstQualified, DoesNotMatchInappropriately) {
                          variable(hasType(isConstQualified()))));
 }
 
+TEST(CastExpression, MatchesSimpleCases) {
+  EXPECT_TRUE(matches("char *p = reinterpret_cast<char *>(&p);",
+                      expression(castExpression())));
+  EXPECT_TRUE(matches("void *p = (void *)(&p);", expression(castExpression())));
+  EXPECT_TRUE(matches("char q, *p = const_cast<char *>(&q);",
+                      expression(castExpression())));
+  EXPECT_TRUE(matches("char c = 0;", expression(castExpression())));
+  EXPECT_TRUE(matches("char c = char(0);", expression(castExpression())));
+}
+
+TEST(CastExpression, DoesNotMatchNonCasts) {
+  EXPECT_TRUE(notMatches("char c = '0';", expression(castExpression())));
+  EXPECT_TRUE(notMatches("char c, &q = c;", expression(castExpression())));
+}
+
 TEST(ReinterpretCast, MatchesSimpleCase) {
   EXPECT_TRUE(matches("char* p = reinterpret_cast<char*>(&p);",
                       expression(reinterpretCast())));
@@ -2036,6 +2051,145 @@ TEST(HasDestinationType, MatchesSimpleCase) {
                               pointsTo(TypeMatcher(anything())))))));
 }
 
+TEST(HasImplicitDestinationType, MatchesSimpleCase) {
+  EXPECT_TRUE(matches("int x; const int i = x;",
+                      expression(implicitCast(
+                          hasImplicitDestinationType(isInteger())))));
+  EXPECT_TRUE(matches("int arr[3]; int *p = arr;",
+                      expression(implicitCast(hasImplicitDestinationType(
+                          pointsTo(TypeMatcher(anything())))))));
+}
+
+TEST(HasImplicitDestinationType, DoesNotMatchIncorrectly) {
+  EXPECT_TRUE(notMatches("char c = 0;",
+                      expression(implicitCast(hasImplicitDestinationType(
+                          isConstQualified())))));
+  EXPECT_TRUE(notMatches("int arr[3]; int *p = arr;",
+                      expression(implicitCast(hasImplicitDestinationType(
+                          asString("int"))))));
+}
+
+TEST(ImplicitCast, MatchesSimpleCase) {
+  EXPECT_TRUE(matches("int x = 0; const int y = x;",
+                      variable(hasInitializer(implicitCast(expression())))));
+  EXPECT_TRUE(matches("char c = 0;",
+                      variable(hasInitializer(implicitCast(expression())))));
+  EXPECT_TRUE(matches("int arr[6]; int *p = arr;",
+                      variable(hasInitializer(implicitCast(expression())))));
+}
+
+TEST(ImplicitCast, DoesNotMatchIncorrectly) {
+  EXPECT_TRUE(notMatches("int x = 0;",
+                         variable(hasInitializer(implicitCast(expression())))));
+  EXPECT_TRUE(notMatches("int x = 0, &y = x;",
+                         variable(hasInitializer(implicitCast(expression())))));
+  EXPECT_TRUE(notMatches("int x = 0; double d = (double) x;",
+                         variable(hasInitializer(implicitCast(expression())))));
+  EXPECT_TRUE(notMatches("const int *p; int *q = const_cast<int *>(p);",
+                         variable(hasInitializer(implicitCast(expression())))));
+}
+
+TEST(IgnoringImplicitCasts, MatchesOnlyWithImpCasts) {
+  EXPECT_TRUE(notMatches("int x = 0; const int y = x;",
+                         variable(hasInitializer(declarationReference()))));
+  EXPECT_TRUE(matches("int x = 0; const int y = x;",
+                      variable(hasInitializer(ignoringImplicitCasts(
+                          declarationReference())))));
+}
+
+TEST(IgnoringImplicitCasts, DoesNotMatchIncorrectly) {
+  EXPECT_TRUE(notMatches("int x; const int y = x;",
+                         variable(hasInitializer(ignoringImplicitCasts(
+                             integerLiteral(equals(0)))))));
+
+  EXPECT_TRUE(notMatches("int x = 0; float y = (float)x;",
+                      variable(hasInitializer(ignoringImplicitCasts(
+                          declarationReference())))));
+}
+
+TEST(IgnoringImplicitCasts, MatchesWithAndWithoutImpCasts) {
+  EXPECT_TRUE(matches("int x = 0; int &y = x;",
+                      variable(hasInitializer(declarationReference()))));
+  EXPECT_TRUE(matches("int x = 0; int &y = x;",
+                      variable(hasInitializer(ignoringImplicitCasts(
+                          declarationReference())))));
+}
+
+TEST(IgnoringParenCasts, MatchesOnlyWithParenCasts) {
+  EXPECT_TRUE(notMatches("int x = (0);",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("int x = (0);",
+                         variable(hasInitializer(ignoringParenCasts(
+                             integerLiteral(equals(0)))))));
+  EXPECT_TRUE(notMatches("int x = (0);",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("char x = (char)0;",
+                         variable(hasInitializer(ignoringParenCasts(
+                             integerLiteral(equals(0)))))));
+  EXPECT_TRUE(notMatches("int x = (((((0)))));",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("int x = (((((0)))));",
+                         variable(hasInitializer(ignoringParenCasts(
+                             integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringParenCasts, MatchesWithAndWithoutParenCasts) {
+  EXPECT_TRUE(matches("int x = 0;",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("int x = 0;",
+                         variable(hasInitializer(ignoringParenCasts(
+                             integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringParenCasts, DoesNotMatchIncorrectly) {
+  EXPECT_TRUE(notMatches("int x = ((3));",
+                         variable(hasInitializer(ignoringParenCasts(
+                             integerLiteral(equals(0)))))));
+
+  EXPECT_TRUE(notMatches(
+      "int x = 0; float *y = (reinterpret_cast<float *>(&x));",
+      variable(hasInitializer(ignoringParenCasts(declarationReference())))));
+}
+
+TEST(IgnoringParenAndImpCasts, MatchesOnlyWithParenImpCasts) {
+  EXPECT_TRUE(notMatches("int x = 0; const int y = x;",
+                         variable(hasInitializer(declarationReference()))));
+  EXPECT_TRUE(matches("int x = 0; const int y = x;",
+                      variable(hasInitializer(ignoringParenAndImplicitCasts(
+                          declarationReference())))));
+  EXPECT_TRUE(notMatches("const int x = (0);",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("const int x = (0);",
+                         variable(hasInitializer(ignoringParenAndImplicitCasts(
+                             integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringParenAndImpCasts, MatchesWithAndWithoutParenImpCasts) {
+  EXPECT_TRUE(matches("int x = 0; int &y = x;",
+                      variable(hasInitializer(ignoringParenAndImplicitCasts(
+                          declarationReference())))));
+  EXPECT_TRUE(matches("int x = 0; int &y = x;",
+                      variable(hasInitializer(declarationReference()))));
+  EXPECT_TRUE(matches("int x = 0;",
+                         variable(hasInitializer(integerLiteral(equals(0))))));
+  EXPECT_TRUE(matches("int x = 0;",
+                         variable(hasInitializer(ignoringParenAndImplicitCasts(
+                             integerLiteral(equals(0)))))));
+}
+
+TEST(IgnoringParenAndImpCasts, DoesNotMatchIncorrectly) {
+  EXPECT_TRUE(notMatches("char c = ((3));",
+                         variable(hasInitializer(ignoringParenAndImplicitCasts(
+                             integerLiteral(equals(0)))))));
+
+  EXPECT_TRUE(notMatches("int x = 0; float y = (float(x));",
+                      variable(hasInitializer(ignoringParenAndImplicitCasts(
+                          declarationReference())))));
+  EXPECT_TRUE(notMatches("int x = 0; float *y = reinterpret_cast<float*>(&x);",
+                      variable(hasInitializer(ignoringParenAndImplicitCasts(
+                          declarationReference())))));
+}
+
 TEST(HasSourceExpression, MatchesSimpleCase) {
   EXPECT_TRUE(matches("class string {}; class URL { public: URL(string s); };"
                       "void r() {string a_string; URL url = a_string; }",
