diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index d1ec7ae..c62661c 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -9116,6 +9116,35 @@ bool Expr::EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,
       return false;
   }
 
+  if (!Callee->isVariadic() && Args.size() < Callee->param_size()) {
+    ArgValues.resize(Callee->param_size());
+    for (FunctionDecl::param_const_iterator
+             I = Callee->param_begin() + Args.size(),
+             E = Callee->param_end();
+         I != E; ++I) {
+      const Expr *Arg;
+
+      // Try getting a default argument.
+      if ((*I)->hasUninstantiatedDefaultArg())
+        Arg = (*I)->getUninstantiatedDefaultArg();
+      else
+        Arg = (*I)->getDefaultArg();
+
+      // Default argument available, try evaluting it.
+      if (Arg) {
+        if (Arg->isValueDependent() ||
+            !Evaluate(ArgValues[I - Callee->param_begin()], Info, Arg))
+          // If evaluation fails, throw away the argument entirely.
+          ArgValues[I - Callee->param_begin()] = APValue();
+        if (Info.EvalStatus.HasSideEffects)
+          return false;
+      } else {
+        // If no default argument, provide an invalid one.
+        ArgValues[I - Callee->param_begin()] = APValue();
+      }
+    }
+  }
+
   // Build fake call to Callee.
   CallStackFrame Frame(Info, Callee->getLocation(), Callee, /*This*/nullptr,
                        ArgValues.data());
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 9d87a10..95af64e 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -11613,6 +11613,16 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
     FoundDecl = MemExpr->getFoundDecl();
     Qualifier = MemExpr->getQualifier();
     UnbridgedCasts.restore();
+
+    if (const EnableIfAttr *Attr = CheckEnableIf(Method, Args, true)) {
+      Diag(MemExprE->getLocStart(),
+           diag::err_ovl_no_viable_member_function_in_call)
+          << Method << Method->getSourceRange();
+      Diag(Method->getLocation(),
+           diag::note_ovl_candidate_disabled_by_enable_if_attr)
+          << Attr->getCond()->getSourceRange() << Attr->getMessage();
+      return ExprError();
+    }
   } else {
     UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
     Qualifier = UnresExpr->getQualifier();
diff --git a/test/SemaCXX/enable_if.cpp b/test/SemaCXX/enable_if.cpp
index 99545e0..e26136e 100644
--- a/test/SemaCXX/enable_if.cpp
+++ b/test/SemaCXX/enable_if.cpp
@@ -11,6 +11,10 @@ struct X {
   void f(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero")));
   void f(int n) __attribute__((enable_if(n == 1, "chosen when 'n' is one")));  // expected-note{{member declaration nearly matches}} expected-note{{candidate disabled: chosen when 'n' is one}}
 
+  void g(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero")));  // expected-note{{candidate disabled: chosen when 'n' is zero}}
+
+  void h(int n, int m = 0) __attribute((enable_if(m == 0, "chosen when 'm' is zero")));  // expected-note{{candidate disabled: chosen when 'm' is zero}}
+
   static void s(int n) __attribute__((enable_if(n == 0, "chosen when 'n' is zero")));  // expected-note2{{candidate disabled: chosen when 'n' is zero}}
 
   void conflict(int n) __attribute__((enable_if(n+n == 10, "chosen when 'n' is five")));  // expected-note{{candidate function}}
@@ -40,6 +44,8 @@ void deprec2(int i) __attribute__((enable_if(old() == 0, "chosen when old() is z
 void overloaded(int);
 void overloaded(long);
 
+void default_argument(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero")));  // expected-note{{candidate disabled: chosen when 'm' is zero}}
+
 struct Nothing { };
 template<typename T> void typedep(T t) __attribute__((enable_if(t, "")));  // expected-note{{candidate disabled:}}  expected-error{{value of type 'Nothing' is not contextually convertible to 'bool'}}
 template<int N> void valuedep() __attribute__((enable_if(N == 1, "")));
@@ -58,6 +64,12 @@ void test() {
   x.f(2);  // no error, suppressed by erroneous out-of-line definition
   x.f(3);  // expected-error{{no matching member function for call to 'f'}}
 
+  x.g(0);
+  x.g(1);  // expected-error{{no matching member function for call to 'g'}}
+
+  x.h(0);
+  x.h(1, 2);  // expected-error{{no matching member function for call to 'h'}}
+
   x.s(0);
   x.s(1);  // expected-error{{no matching member function for call to 's'}}
 
@@ -70,6 +82,9 @@ void test() {
 
   overloaded(x);
 
+  default_argument(0);
+  default_argument(1, 2);  // expected-error{{no matching function for call to 'default_argument'}}
+
   int i = x(1);  // expected-error{{no matching function for call to object of type 'X'}}
 
   Nothing n;
@@ -88,6 +103,18 @@ template <class T> void test3() {
   fn3(sizeof(T) == 1);
 }
 
+template <typename T>
+struct Y {
+  T h(int n, int m = 0) __attribute__((enable_if(m == 0, "chosen when 'm' is zero")));  // expected-note{{candidate disabled: chosen when 'm' is zero}}
+};
+
+void test4() {
+  Y<int> y;
+
+  int t0 = y.h(0);
+  int t1 = y.h(1, 2);  // expected-error{{no matching member function for call to 'h'}}
+}
+
 // FIXME: issue an error (without instantiation) because ::h(T()) is not
 // convertible to bool, because return types aren't overloadable.
 void h(int);
