From 883031fb45cf0f86cd36b20ad4762da58dd6126c Mon Sep 17 00:00:00 2001
From: Arseny Kapoulkine <arseny.kapoulkine@gmail.com>
Date: Wed, 15 Oct 2014 06:05:49 +0000
Subject: [PATCH] XPath: Fix optimization bug with //name[last()]

The actual condition for the optimization is invariance from context list
-- this includes both position() and last().

Instead of splitting the posinv concept just include last() into
non-posinv expressions - this requires sorting for boolean predicates that
depend on last() and do not depend on position(). These cases should be
very rare.

git-svn-id: https://pugixml.googlecode.com/svn/trunk@1060 99668b35-9821-0410-8761-19e4c4f06640
---
 src/pugixml.cpp            | 1 +
 tests/test_xpath_paths.cpp | 6 ++++++
 2 files changed, 7 insertions(+)

diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 7db62d0c..484f34b2 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -9621,6 +9621,7 @@ PUGI__NS_BEGIN
 			switch (_type)
 			{
 			case ast_func_position:
+			case ast_func_last:
 				return false;
 
 			case ast_string_constant:
diff --git a/tests/test_xpath_paths.cpp b/tests/test_xpath_paths.cpp
index c18acd27..43096bcd 100644
--- a/tests/test_xpath_paths.cpp
+++ b/tests/test_xpath_paths.cpp
@@ -531,6 +531,12 @@ TEST_XML(xpath_paths_descendant_optimize, "<node><para><para/><para/><para><para
 	CHECK_XPATH_NODESET(doc, STR("/descendant-or-self::node()[3]/child::para")) % 4 % 5 % 6;
 }
 
+TEST_XML(xpath_paths_descendant_optimize_last, "<node><para><para/><para/><para><para/></para></para><para/></node>")
+{
+	CHECK_XPATH_NODESET(doc, STR("//para[last()]")) % 6 % 7 % 8;
+	CHECK_XPATH_NODESET(doc, STR("//para[last() = 1]")) % 7;
+}
+
 TEST_XML(xpath_paths_precision, "<node><para/><para/><para/><para/><para/></node>")
 {
 	CHECK_XPATH_NODESET(doc, STR("//para[1]")) % 3;
-- 
GitLab