diff --git include/clang/Sema/Sema.h include/clang/Sema/Sema.h
index 74114a8..676f529 100644
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -234,6 +234,12 @@ public:
   /// VisContext - Manages the stack for \#pragma GCC visibility.
   void *VisContext; // Really a "PragmaVisStack*"
 
+  /// \brief Flag indicating if Sema is building a recovery call expression.
+  ///
+  /// This flag is used to avoid building recovery call expressions
+  /// if Sema is already doing so, which would cause infinite recursions.
+  bool IsBuildingRecoveryCallExpr;
+
   /// ExprNeedsCleanups - True if the current evaluation context
   /// requires cleanups to be run at its conclusion.
   bool ExprNeedsCleanups;
diff --git lib/Sema/Sema.cpp lib/Sema/Sema.cpp
index bd7c851..08ccfa4 100644
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -90,6 +90,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
     CurContext(0), OriginalLexicalContext(0),
     PackContext(0), MSStructPragmaOn(false), VisContext(0),
+    IsBuildingRecoveryCallExpr(false),
     ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     NSNumberDecl(0),
diff --git lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.cpp
index fe4cac8..e9c2c6c 100644
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -9655,6 +9655,20 @@ class NoTypoCorrectionCCC : public CorrectionCandidateCallback {
     return false;
   }
 };
+
+class BuildRecoveryCallExprRAII {
+  Sema &SemaRef;
+public:
+  BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S) {
+    assert(SemaRef.IsBuildingRecoveryCallExpr == false);
+    SemaRef.IsBuildingRecoveryCallExpr = true;
+  }
+
+  ~BuildRecoveryCallExprRAII() {
+    SemaRef.IsBuildingRecoveryCallExpr = false;
+  }
+};
+
 }
 
 /// Attempts to recover from a call where no functions were found.
@@ -9667,6 +9681,15 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
                       llvm::MutableArrayRef<Expr *> Args,
                       SourceLocation RParenLoc,
                       bool EmptyLookup, bool AllowTypoCorrection) {
+  // Do not try to recover if it is already building a recovery call.
+  // This stops infinite loops for template instantiations like
+  //
+  // template <typename T> auto foo(T t) -> decltype(foo(t)) {}
+  // template <typename T> auto foo(T t) -> decltype(foo(&t)) {}
+  //
+  if (SemaRef.IsBuildingRecoveryCallExpr)
+    return ExprError();
+  BuildRecoveryCallExprRAII RCE(SemaRef);
 
   CXXScopeSpec SS;
   SS.Adopt(ULE->getQualifierLoc());
diff --git test/SemaCXX/PR12053.cpp test/SemaCXX/PR12053.cpp
new file mode 100644
index 0000000..d643e2b
--- /dev/null
+++ test/SemaCXX/PR12053.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+template <typename T>
+auto f1(T t) -> decltype(f1(t)) {} // expected-note{{candidate template ignored}}
+
+void test_f1() {
+  f1(0); // expected-error{{no matching function for call to 'f1'}}
+}
+
+template <typename T>
+auto f2(T t) -> decltype(f2(&t)) {} // expected-note{{candidate template ignored}}
+
+void test_f2() {
+  f2(0); // expected-error{{no matching function for call to 'f2'}}
+}
