Merge branch 'revert-definition-map-lookup' into release
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx
index 5515f35..fe32dd5 100644
--- a/Source/cmDefinitions.cxx
+++ b/Source/cmDefinitions.cxx
@@ -29,7 +29,7 @@
 
 //----------------------------------------------------------------------------
 cmDefinitions::Def const&
-cmDefinitions::GetInternal(const std::string& key) const
+cmDefinitions::GetInternal(const std::string& key)
 {
   MapType::const_iterator i = this->Map.find(key);
   if(i != this->Map.end())
@@ -38,8 +38,9 @@
     }
   if(cmDefinitions* up = this->Up)
     {
-    // Query the parent scope.
-    return up->GetInternal(key);
+    // Query the parent scope and store the result locally.
+    Def def = up->GetInternal(key);
+    return this->Map.insert(MapType::value_type(key, def)).first->second;
     }
   return this->NoDef;
 }
@@ -62,26 +63,13 @@
 }
 
 //----------------------------------------------------------------------------
-const char* cmDefinitions::Get(const std::string& key) const
+const char* cmDefinitions::Get(const std::string& key)
 {
   Def const& def = this->GetInternal(key);
   return def.Exists? def.c_str() : 0;
 }
 
 //----------------------------------------------------------------------------
-void cmDefinitions::Pull(const std::string& key)
-{
-  if (this->Up)
-    {
-    Def const& def = this->Up->GetInternal(key);
-    if (def.Exists)
-      {
-      this->SetInternal(key, def);
-      }
-    }
-}
-
-//----------------------------------------------------------------------------
 const char* cmDefinitions::Set(const std::string& key, const char* value)
 {
   Def const& def = this->SetInternal(key, Def(value));
diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h
index 5209a8b..a2f053f 100644
--- a/Source/cmDefinitions.h
+++ b/Source/cmDefinitions.h
@@ -36,11 +36,9 @@
   /** Returns the parent scope, if any.  */
   cmDefinitions* GetParent() const { return this->Up; }
 
-  /** Get the value associated with a key; null if none. */
-  const char* Get(const std::string& key) const;
-
-  /** Pull a variable from the parent. */
-  void Pull(const std::string& key);
+  /** Get the value associated with a key; null if none.
+      Store the result locally if it came from a parent.  */
+  const char* Get(const std::string& key);
 
   /** Set (or unset if null) a value associated with a key.  */
   const char* Set(const std::string& key, const char* value);
@@ -82,7 +80,7 @@
   MapType Map;
 
   // Internal query and update methods.
-  Def const& GetInternal(const std::string& key) const;
+  Def const& GetInternal(const std::string& key);
   Def const& SetInternal(const std::string& key, Def const& def);
 
   // Implementation of Closure() method.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 8806205..0bd1624 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -4476,7 +4476,7 @@
   if(cmDefinitions* up = cur.GetParent())
     {
     // First localize the definition in the current scope.
-    cur.Pull(var);
+    cur.Get(var);
 
     // Now update the definition in the parent scope.
     up->Set(var, varDef);
diff --git a/Tests/RunCMake/set/ParentPulling-stderr.txt b/Tests/RunCMake/set/ParentPulling-stderr.txt
new file mode 100644
index 0000000..768549b
--- /dev/null
+++ b/Tests/RunCMake/set/ParentPulling-stderr.txt
@@ -0,0 +1,3 @@
+^before PARENT_SCOPE blah=value2
+after PARENT_SCOPE blah=value2
+in parent scope, blah=value2$
diff --git a/Tests/RunCMake/set/ParentPulling.cmake b/Tests/RunCMake/set/ParentPulling.cmake
new file mode 100644
index 0000000..2614533
--- /dev/null
+++ b/Tests/RunCMake/set/ParentPulling.cmake
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.0)
+project(Minimal NONE)
+
+function(test_set)
+    set(blah "value2")
+    message("before PARENT_SCOPE blah=${blah}")
+    set(blah ${blah} PARENT_SCOPE)
+    message("after PARENT_SCOPE blah=${blah}")
+endfunction()
+
+set(blah value1)
+test_set()
+message("in parent scope, blah=${blah}")
diff --git a/Tests/RunCMake/set/ParentPullingRecursive-stderr.txt b/Tests/RunCMake/set/ParentPullingRecursive-stderr.txt
new file mode 100644
index 0000000..f3260ae
--- /dev/null
+++ b/Tests/RunCMake/set/ParentPullingRecursive-stderr.txt
@@ -0,0 +1,144 @@
+----------
+variable values at top before calls:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->top<--
+top_explicit_inner_unset: <undefined>
+top_explicit_inner_tounset: -->top<--
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: <undefined>
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: <undefined>
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: <undefined>
+----------
+----------
+variable values at outer start:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->top<--
+top_explicit_inner_unset: <undefined>
+top_explicit_inner_tounset: -->top<--
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: <undefined>
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: <undefined>
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: <undefined>
+----------
+----------
+variable values at outer before inner:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->top<--
+top_explicit_inner_unset: <undefined>
+top_explicit_inner_tounset: -->top<--
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: -->outer<--
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: -->outer<--
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: -->outer<--
+----------
+----------
+variable values at inner start:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->top<--
+top_explicit_inner_unset: <undefined>
+top_explicit_inner_tounset: -->top<--
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: -->outer<--
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: -->outer<--
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: -->outer<--
+----------
+----------
+variable values at inner end:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->top<--
+top_explicit_inner_unset: <undefined>
+top_explicit_inner_tounset: -->top<--
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: -->outer<--
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: -->outer<--
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: -->outer<--
+----------
+----------
+variable values at outer after inner:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->inner<--
+top_explicit_inner_unset: -->inner<--
+top_explicit_inner_tounset: <undefined>
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: -->outer<--
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: -->inner<--
+outer_explicit_inner_unset: -->inner<--
+outer_explicit_inner_tounset: <undefined>
+----------
+----------
+variable values at outer end:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->inner<--
+top_explicit_inner_unset: -->inner<--
+top_explicit_inner_tounset: <undefined>
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_set: -->top<--
+top_explicit_outer_unset: <undefined>
+top_explicit_outer_tounset: -->top<--
+outer_implicit_inner_set: -->outer<--
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: -->inner<--
+outer_explicit_inner_unset: -->inner<--
+outer_explicit_inner_tounset: <undefined>
+----------
+----------
+variable values at top after calls:
+top_implicit_inner_set: -->top<--
+top_implicit_inner_unset: <undefined>
+top_explicit_inner_set: -->outer<--
+top_explicit_inner_unset: -->outer<--
+top_explicit_inner_tounset: <undefined>
+top_implicit_outer_set: -->top<--
+top_explicit_outer_unset: -->outer<--
+top_explicit_outer_set: -->outer<--
+top_explicit_outer_unset: -->outer<--
+top_explicit_outer_tounset: <undefined>
+outer_implicit_inner_set: <undefined>
+outer_implicit_inner_unset: <undefined>
+outer_explicit_inner_set: <undefined>
+outer_explicit_inner_unset: <undefined>
+outer_explicit_inner_tounset: <undefined>
+----------
diff --git a/Tests/RunCMake/set/ParentPullingRecursive.cmake b/Tests/RunCMake/set/ParentPullingRecursive.cmake
new file mode 100644
index 0000000..a3e29f5
--- /dev/null
+++ b/Tests/RunCMake/set/ParentPullingRecursive.cmake
@@ -0,0 +1,104 @@
+cmake_minimum_required(VERSION 3.0)
+project(Minimal NONE)
+
+function(report where)
+    message("----------")
+    message("variable values at ${where}:")
+    foreach(var IN ITEMS
+            top_implicit_inner_set top_implicit_inner_unset
+            top_explicit_inner_set top_explicit_inner_unset top_explicit_inner_tounset
+            top_implicit_outer_set top_explicit_outer_unset
+            top_explicit_outer_set top_explicit_outer_unset top_explicit_outer_tounset
+
+            outer_implicit_inner_set outer_implicit_inner_unset
+            outer_explicit_inner_set outer_explicit_inner_unset outer_explicit_inner_tounset)
+        if(DEFINED ${var})
+            message("${var}: -->${${var}}<--")
+        else()
+            message("${var}: <undefined>")
+        endif()
+    endforeach()
+    message("----------")
+endfunction()
+
+macro(set_values upscope downscope value)
+    # Pull the value in implicitly.
+    set(dummy ${${upscope}_implicit_${downscope}_set})
+    set(dummy ${${upscope}_implicit_${downscope}_unset})
+    # Pull it down explicitly.
+    set(${upscope}_explicit_${downscope}_set "${value}" PARENT_SCOPE)
+    set(${upscope}_explicit_${downscope}_unset "${value}" PARENT_SCOPE)
+    set(${upscope}_explicit_${downscope}_tounset PARENT_SCOPE)
+endmacro()
+
+function(inner)
+    report("inner start")
+
+    set_values(top inner inner)
+    set_values(outer inner inner)
+
+    report("inner end")
+endfunction()
+
+function(outer)
+    report("outer start")
+
+    set_values(top outer outer)
+
+    # Set values for inner to manipulate.
+    set(outer_implicit_inner_set outer)
+    set(outer_implicit_inner_unset)
+    set(outer_explicit_inner_set outer)
+    set(outer_explicit_inner_unset)
+    set(outer_explicit_inner_tounset outer)
+
+    report("outer before inner")
+
+    inner()
+
+    report("outer after inner")
+
+    # Do what inner does so that we can test the values that inner should have
+    # pulled through to here.
+    set_values(top inner outer)
+
+    report("outer end")
+endfunction()
+
+# variable name is:
+#
+#    <upscope>_<pulltype>_<downscope>_<settype>
+#
+# where the value is the name of the scope it was set in. The scopes available
+# are "top", "outer", and "inner". The pull type may either be "implicit" or
+# "explicit" based on whether the pull is due to a variable dereference or a
+# PARENT_SCOPE setting. The settype is "set" where both scopes set a value,
+# "unset" where upscope unsets it and downscope sets it, and "tounset" where
+# upscope sets it and downscope unsets it.
+#
+# We test the following combinations:
+#
+#   - outer overriding top's values;
+#   - inner overriding top's values;
+#   - inner overriding outer's values; and
+#   - outer overriding inner's values in top after inner has run.
+
+# Set values for inner to manipulate.
+set(top_implicit_inner_set top)
+set(top_implicit_inner_unset)
+set(top_explicit_inner_set top)
+set(top_explicit_inner_unset)
+set(top_explicit_inner_tounset top)
+
+# Set values for outer to manipulate.
+set(top_implicit_outer_set top)
+set(top_implicit_outer_unset)
+set(top_explicit_outer_set top)
+set(top_explicit_outer_unset)
+set(top_explicit_outer_tounset top)
+
+report("top before calls")
+
+outer()
+
+report("top after calls")
diff --git a/Tests/RunCMake/set/RunCMakeTest.cmake b/Tests/RunCMake/set/RunCMakeTest.cmake
index 1b51ea2..b8e8cf1 100644
--- a/Tests/RunCMake/set/RunCMakeTest.cmake
+++ b/Tests/RunCMake/set/RunCMakeTest.cmake
@@ -1,3 +1,5 @@
 include(RunCMake)
 
 run_cmake(ParentScope)
+run_cmake(ParentPulling)
+run_cmake(ParentPullingRecursive)