diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
index 10d8d03ec8d..0b6c3b0f988 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
@@ -5876,4 +5876,52 @@ public class AST2TemplateTests extends AST2BaseTest {
 	public void testConstInTypeParameter_377223() throws Exception {
 		parseAndCheckBindings();
 	}
+
+	//	template<typename T, T v>
+	//	struct integral_constant {
+	//	  static constexpr T value = v;
+	//	  typedef T value_type;
+	//	  typedef integral_constant<T, v> type;
+	//	};
+	//
+	//	typedef integral_constant<bool, true> true_type;
+	//
+	//	typedef integral_constant<bool, false> false_type;
+	//
+	//	template<typename T>
+	//	class helper {
+	//	  typedef char one;
+	//	  typedef struct { char arr[2]; } two;
+	//	  template<typename U> struct Wrap_type {};
+	//	  template<typename U> static one test(Wrap_type<typename U::category>*);
+	//	  template<typename U> static two test(...);
+	//	  public: static const bool value = sizeof(test<T>(0)) == 1;
+	//	};
+	//
+	//	template<typename T>
+	//	struct has_category : integral_constant<bool, helper<T>::value> {};
+	//
+	//	template<typename Iterator, bool = has_category<Iterator>::value>
+	//	struct traits {};
+	//
+	//	template<typename Iterator>
+	//	struct traits<Iterator, true> {
+	//	  typedef typename Iterator::value_type value_type;
+	//	};
+	//
+	//	struct tag {};
+	//
+	//	struct C {
+	//	  typedef int value_type;
+	//	  typedef tag category;
+	//	};
+	//
+	//	template<typename It, typename Val = typename traits<It>::value_type>
+	//	class A {
+	//	};
+	//
+	//	typedef A<C> type;
+	public void testSFINAE() throws Exception {
+		parseAndCheckBindings();
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java
index 74788246143..acd6fc952c9 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java
@@ -94,10 +94,10 @@ public class EvalBinding extends CPPEvaluation {
 			t= ((ICPPTemplateNonTypeParameter) fBinding).getType();
 		} else if (fBinding instanceof IVariable) {
 			t = ((IVariable) fBinding).getType();
-		} else if (fBinding instanceof IFunction) {
-			t= ((IFunction) fBinding).getType();
 		} else if (fBinding instanceof ICPPUnknownBinding) {
 			return true;
+		} else if (fBinding instanceof IFunction) {
+			t= ((IFunction) fBinding).getType();
 		} else {
 			return false;
 		}
@@ -123,12 +123,12 @@ public class EvalBinding extends CPPEvaluation {
 		if (fBinding instanceof IVariable) {
 			return Value.isDependentValue(((IVariable) fBinding).getInitialValue());
 		}
-		if (fBinding instanceof IFunction) {
-			return false;
-		}
 		if (fBinding instanceof ICPPUnknownBinding) {
 			return true;
 		}
+		if (fBinding instanceof IFunction) {
+			return false;
+		}
 		return false;
 	}
 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java
index 752cb08797c..fe5266bae77 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java
@@ -173,14 +173,18 @@ public class EvalComma extends CPPEvaluation {
 	@Override
 	public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
 			ICPPClassSpecialization within, int maxdepth, IASTNode point) {
-		ICPPEvaluation[] args = new ICPPEvaluation[fArguments.length];
-		boolean changed = false;
+		ICPPEvaluation[] args = null;
 		for (int i = 0; i < fArguments.length; i++) {
-			args[i] = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
-			if (args[i] != fArguments[i])
-				changed = true;
+			ICPPEvaluation arg = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
+			if (arg != fArguments[i]) {
+				if (args == null) {
+					args = new ICPPEvaluation[fArguments.length];
+					System.arraycopy(fArguments, 0, args, 0, fArguments.length);
+				}
+				args[i] = arg;
+			}
 		}
-		if (!changed)
+		if (args == null)
 			return this;
 		return new EvalComma(args);
 	}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
index d7737ffc9e4..6cb3db90499 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java
@@ -186,14 +186,18 @@ public class EvalFunctionCall extends CPPEvaluation {
 	@Override
 	public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
 			ICPPClassSpecialization within, int maxdepth, IASTNode point) {
-		ICPPEvaluation[] args = new ICPPEvaluation[fArguments.length];
-		boolean changed = false;
+		ICPPEvaluation[] args = null;
 		for (int i = 0; i < fArguments.length; i++) {
-			args[i] = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
-			if (args[i] != fArguments[i])
-				changed = true;
+			ICPPEvaluation arg = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
+			if (arg != fArguments[i]) {
+				if (args == null) {
+					args = new ICPPEvaluation[fArguments.length];
+					System.arraycopy(fArguments, 0, args, 0, fArguments.length);
+				}
+				args[i] = arg;
+			}
 		}
-		if (!changed)
+		if (args == null)
 			return this;
 
 		if (args[0] instanceof EvalFunctionSet) {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java
index f618cd64020..34d3d063c46 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java
@@ -128,7 +128,7 @@ public class EvalID extends CPPEvaluation {
 
 	@Override
 	public IValue getValue(IASTNode point) {
-		// Name lookup is not needed here because it was already done in "instantiate" method.
+		// Name lookup is not needed here because it was already done in the "instantiate" method.
 //		IBinding nameOwner = fNameOwner;
 //		if (nameOwner == null && fFieldOwner != null)
 //			nameOwner = (IBinding) fFieldOwner.getTypeOrFunctionSet(point);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java
index e1d4b237e29..db7d1c46bba 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java
@@ -105,14 +105,18 @@ public class EvalInitList extends CPPEvaluation {
 	@Override
 	public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
 			ICPPClassSpecialization within, int maxdepth, IASTNode point) {
-		ICPPEvaluation[] clauses = new ICPPEvaluation[fClauses.length];
-		boolean changed = false;
+		ICPPEvaluation[] clauses = null;
 		for (int i = 0; i < fClauses.length; i++) {
-			clauses[i] = fClauses[i].instantiate(tpMap, packOffset, within, maxdepth, point);
-			if (clauses[i] != fClauses[i])
-				changed = true;
+			ICPPEvaluation clause = fClauses[i].instantiate(tpMap, packOffset, within, maxdepth, point);
+			if (clause != fClauses[i]) {
+				if (clauses == null) {
+					clauses = new ICPPEvaluation[fClauses.length];
+					System.arraycopy(fClauses, 0, clauses, 0, fClauses.length);
+				}
+				clauses[i] = clause;
+			}
 		}
-		if (!changed)
+		if (clauses == null)
 			return this;
 		return new EvalInitList(clauses);
 	}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java
index 6e8ef088d12..c0c25271eba 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java
@@ -146,16 +146,23 @@ public class EvalTypeId extends CPPEvaluation {
 	@Override
 	public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset,
 			ICPPClassSpecialization within, int maxdepth, IASTNode point) {
-		ICPPEvaluation[] args = new ICPPEvaluation[fArguments.length];
-		boolean argsChanged = false;
+		ICPPEvaluation[] args = null;
 		for (int i = 0; i < fArguments.length; i++) {
-			args[i] = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
-			if (args[i] != fArguments[i])
-				argsChanged = true;
+			ICPPEvaluation arg = fArguments[i].instantiate(tpMap, packOffset, within, maxdepth, point);
+			if (arg != fArguments[i]) {
+				if (args == null) {
+					args = new ICPPEvaluation[fArguments.length];
+					System.arraycopy(fArguments, 0, args, 0, fArguments.length);
+				}
+				args[i] = arg;
+			}
 		}
 		IType type = CPPTemplates.instantiateType(fInputType, tpMap, packOffset, within, point);
-		if (!argsChanged && type == fInputType)
-			return this;
+		if (args == null) {
+			if (type == fInputType)
+				return this;
+			args = fArguments;
+		}
 		return new EvalTypeId(type, args);
 	}