|  | @@ -44,12 +44,22 @@ class cmMakefile::Internals
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  public:
 | 
	
		
			
				|  |  |    std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
 | 
	
		
			
				|  |  | +  std::stack<std::set<cmStdString> > VarInitStack;
 | 
	
		
			
				|  |  | +  std::stack<std::set<cmStdString> > VarUsageStack;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // default is not to be building executables
 | 
	
		
			
				|  |  |  cmMakefile::cmMakefile(): Internal(new Internals)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  this->Internal->VarStack.push(cmDefinitions());
 | 
	
		
			
				|  |  | +  const cmDefinitions& defs = cmDefinitions();
 | 
	
		
			
				|  |  | +  const std::set<cmStdString> globalKeys = defs.LocalKeys();
 | 
	
		
			
				|  |  | +  this->Internal->VarStack.push(defs);
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.push(globalKeys);
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.push(globalKeys);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Initialize these first since AddDefaultDefinitions calls AddDefinition
 | 
	
		
			
				|  |  | +  this->WarnUnused = false;
 | 
	
		
			
				|  |  | +  this->CheckSystemVars = false;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Setup the default include file regular expression (match everything).
 | 
	
		
			
				|  |  |    this->IncludeFileRegularExpression = "^.*$";
 | 
	
	
		
			
				|  | @@ -92,6 +102,8 @@ cmMakefile::cmMakefile(): Internal(new Internals)
 | 
	
		
			
				|  |  |  cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    this->Internal->VarStack.push(mf.Internal->VarStack.top().Closure());
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.push(mf.Internal->VarInitStack.top());
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.push(mf.Internal->VarUsageStack.top());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    this->Prefix = mf.Prefix;
 | 
	
		
			
				|  |  |    this->AuxSourceDirectories = mf.AuxSourceDirectories;
 | 
	
	
		
			
				|  | @@ -129,8 +141,10 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
 | 
	
		
			
				|  |  |    this->SubDirectoryOrder = mf.SubDirectoryOrder;
 | 
	
		
			
				|  |  |    this->Properties = mf.Properties;
 | 
	
		
			
				|  |  |    this->PreOrder = mf.PreOrder;
 | 
	
		
			
				|  |  | -  this->ListFileStack = mf.ListFileStack;
 | 
	
		
			
				|  |  | +  this->WarnUnused = mf.WarnUnused;
 | 
	
		
			
				|  |  |    this->Initialize();
 | 
	
		
			
				|  |  | +  this->CheckSystemVars = mf.CheckSystemVars;
 | 
	
		
			
				|  |  | +  this->ListFileStack = mf.ListFileStack;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  //----------------------------------------------------------------------------
 | 
	
	
		
			
				|  | @@ -571,6 +585,7 @@ bool cmMakefile::ReadListFile(const char* filename_in,
 | 
	
		
			
				|  |  |    std::string currentFile
 | 
	
		
			
				|  |  |      = this->GetSafeDefinition("CMAKE_CURRENT_LIST_FILE");
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_PARENT_LIST_FILE", filename_in);
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    const char* external = 0;
 | 
	
		
			
				|  |  |    std::string external_abs;
 | 
	
	
		
			
				|  | @@ -611,8 +626,10 @@ bool cmMakefile::ReadListFile(const char* filename_in,
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_CURRENT_LIST_FILE", filenametoread);
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
 | 
	
		
			
				|  |  |                         cmSystemTools::GetFilenamePath(filenametoread).c_str());
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // try to see if the list file is the top most
 | 
	
		
			
				|  |  |    // list file for a project, and if it is, then it
 | 
	
	
		
			
				|  | @@ -645,9 +662,12 @@ bool cmMakefile::ReadListFile(const char* filename_in,
 | 
	
		
			
				|  |  |        *fullPath = "";
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
 | 
	
		
			
				|  |  | +    this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
 | 
	
		
			
				|  |  |      this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
 | 
	
		
			
				|  |  | +    this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
 | 
	
		
			
				|  |  |      this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
 | 
	
		
			
				|  |  |                          cmSystemTools::GetFilenamePath(currentFile).c_str());
 | 
	
		
			
				|  |  | +    this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    // add this list file to the list of dependencies
 | 
	
	
		
			
				|  | @@ -687,13 +707,19 @@ bool cmMakefile::ReadListFile(const char* filename_in,
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentParentFile.c_str());
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_PARENT_LIST_FILE");
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_CURRENT_LIST_FILE", currentFile.c_str());
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE");
 | 
	
		
			
				|  |  |    this->AddDefinition("CMAKE_CURRENT_LIST_DIR",
 | 
	
		
			
				|  |  |                        cmSystemTools::GetFilenamePath(currentFile).c_str());
 | 
	
		
			
				|  |  | +  this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // pop the listfile off the stack
 | 
	
		
			
				|  |  |    this->ListFileStack.pop_back();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  // Check for unused variables
 | 
	
		
			
				|  |  | +  this->CheckForUnusedVariables();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    return true;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -759,6 +785,8 @@ void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
 | 
	
		
			
				|  |  |    this->AddSourceGroup("Resources", "\\.plist$");
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
 | 
	
		
			
				|  |  | +  this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
 | 
	
	
		
			
				|  | @@ -1627,6 +1655,13 @@ void cmMakefile::AddDefinition(const char* name, const char* value)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    this->Internal->VarStack.top().Set(name, value);
 | 
	
		
			
				|  |  | +  if (this->Internal->VarUsageStack.size() &&
 | 
	
		
			
				|  |  | +      this->VariableInitialized(name))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->CheckForUnused("changing definition", name);
 | 
	
		
			
				|  |  | +    this->Internal->VarUsageStack.top().erase(name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.top().insert(name);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef CMAKE_BUILD_WITH_CMAKE
 | 
	
		
			
				|  |  |    cmVariableWatch* vv = this->GetVariableWatch();
 | 
	
	
		
			
				|  | @@ -1691,6 +1726,13 @@ void cmMakefile::AddCacheDefinition(const char* name, const char* value,
 | 
	
		
			
				|  |  |  void cmMakefile::AddDefinition(const char* name, bool value)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
 | 
	
		
			
				|  |  | +  if (this->Internal->VarUsageStack.size() &&
 | 
	
		
			
				|  |  | +      this->VariableInitialized(name))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->CheckForUnused("changing definition", name);
 | 
	
		
			
				|  |  | +    this->Internal->VarUsageStack.top().erase(name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.top().insert(name);
 | 
	
		
			
				|  |  |  #ifdef CMAKE_BUILD_WITH_CMAKE
 | 
	
		
			
				|  |  |    cmVariableWatch* vv = this->GetVariableWatch();
 | 
	
		
			
				|  |  |    if ( vv )
 | 
	
	
		
			
				|  | @@ -1701,9 +1743,90 @@ void cmMakefile::AddDefinition(const char* name, bool value)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void cmMakefile::CheckForUnusedVariables() const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  const cmDefinitions& defs = this->Internal->VarStack.top();
 | 
	
		
			
				|  |  | +  const std::set<cmStdString>& locals = defs.LocalKeys();
 | 
	
		
			
				|  |  | +  std::set<cmStdString>::const_iterator it = locals.begin();
 | 
	
		
			
				|  |  | +  for (; it != locals.end(); ++it)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->CheckForUnused("out of scope", it->c_str());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void cmMakefile::MarkVariableAsUsed(const char* var)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.top().insert(var);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool cmMakefile::VariableInitialized(const char* var) const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if(this->Internal->VarInitStack.top().find(var) !=
 | 
	
		
			
				|  |  | +      this->Internal->VarInitStack.top().end())
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  return false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool cmMakefile::VariableUsed(const char* var) const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if(this->Internal->VarUsageStack.top().find(var) !=
 | 
	
		
			
				|  |  | +      this->Internal->VarUsageStack.top().end())
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  return false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void cmMakefile::CheckForUnused(const char* reason, const char* name) const
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if (this->WarnUnused && !this->VariableUsed(name))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    cmStdString path;
 | 
	
		
			
				|  |  | +    cmListFileBacktrace bt;
 | 
	
		
			
				|  |  | +    if (this->CallStack.size())
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      const cmListFileContext* file = this->CallStack.back().Context;
 | 
	
		
			
				|  |  | +      bt.push_back(*file);
 | 
	
		
			
				|  |  | +      path = file->FilePath.c_str();
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      path = this->GetStartDirectory();
 | 
	
		
			
				|  |  | +      path += "/CMakeLists.txt";
 | 
	
		
			
				|  |  | +      cmListFileContext lfc;
 | 
	
		
			
				|  |  | +      lfc.FilePath = path;
 | 
	
		
			
				|  |  | +      lfc.Line = 0;
 | 
	
		
			
				|  |  | +      bt.push_back(lfc);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    if (this->CheckSystemVars ||
 | 
	
		
			
				|  |  | +        cmSystemTools::IsSubDirectory(path.c_str(),
 | 
	
		
			
				|  |  | +                                      this->GetHomeDirectory()) ||
 | 
	
		
			
				|  |  | +        (cmSystemTools::IsSubDirectory(path.c_str(),
 | 
	
		
			
				|  |  | +                                      this->GetHomeOutputDirectory()) &&
 | 
	
		
			
				|  |  | +        !cmSystemTools::IsSubDirectory(path.c_str(),
 | 
	
		
			
				|  |  | +                                cmake::GetCMakeFilesDirectory())))
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      cmOStringStream msg;
 | 
	
		
			
				|  |  | +      msg << "unused variable (" << reason << ") \'" << name << "\'";
 | 
	
		
			
				|  |  | +      this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
 | 
	
		
			
				|  |  | +                                             msg.str().c_str(),
 | 
	
		
			
				|  |  | +                                             bt);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void cmMakefile::RemoveDefinition(const char* name)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    this->Internal->VarStack.top().Set(name, 0);
 | 
	
		
			
				|  |  | +  if (this->Internal->VarUsageStack.size() &&
 | 
	
		
			
				|  |  | +      this->VariableInitialized(name))
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->CheckForUnused("unsetting", name);
 | 
	
		
			
				|  |  | +    this->Internal->VarUsageStack.top().erase(name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.top().insert(name);
 | 
	
		
			
				|  |  |  #ifdef CMAKE_BUILD_WITH_CMAKE
 | 
	
		
			
				|  |  |    cmVariableWatch* vv = this->GetVariableWatch();
 | 
	
		
			
				|  |  |    if ( vv )
 | 
	
	
		
			
				|  | @@ -2055,6 +2178,7 @@ const char* cmMakefile::GetRequiredDefinition(const char* name) const
 | 
	
		
			
				|  |  |  bool cmMakefile::IsDefinitionSet(const char* name) const
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    const char* def = this->Internal->VarStack.top().Get(name);
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.top().insert(name);
 | 
	
		
			
				|  |  |    if(!def)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |      def = this->GetCacheManager()->GetCacheValue(name);
 | 
	
	
		
			
				|  | @@ -2082,6 +2206,10 @@ const char* cmMakefile::GetDefinition(const char* name) const
 | 
	
		
			
				|  |  |        RecordPropertyAccess(name,cmProperty::VARIABLE);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | +  if (this->WarnUnused)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->Internal->VarUsageStack.top().insert(name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    const char* def = this->Internal->VarStack.top().Get(name);
 | 
	
		
			
				|  |  |    if(!def)
 | 
	
		
			
				|  |  |      {
 | 
	
	
		
			
				|  | @@ -2733,6 +2861,31 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
 | 
	
		
			
				|  |  |    // if cmake args were provided then pass them in
 | 
	
		
			
				|  |  |    if (cmakeArgs)
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | +    // FIXME: Workaround to ignore unused CLI variables in try-compile.
 | 
	
		
			
				|  |  | +    //
 | 
	
		
			
				|  |  | +    // Ideally we should use SetArgs to honor options like --warn-unused-vars.
 | 
	
		
			
				|  |  | +    // However, there is a subtle problem when certain arguments are passed to
 | 
	
		
			
				|  |  | +    // a macro wrapping around try_compile or try_run that does not escape
 | 
	
		
			
				|  |  | +    // semicolons in its parameters but just passes ${ARGV} or ${ARGN}.  In
 | 
	
		
			
				|  |  | +    // this case a list argument like "-DVAR=a;b" gets split into multiple
 | 
	
		
			
				|  |  | +    // cmake arguments "-DVAR=a" and "b".  Currently SetCacheArgs ignores
 | 
	
		
			
				|  |  | +    // argument "b" and uses just "-DVAR=a", leading to a subtle bug in that
 | 
	
		
			
				|  |  | +    // the try_compile or try_run does not get the proper value of VAR.  If we
 | 
	
		
			
				|  |  | +    // call SetArgs here then it would treat "b" as the source directory and
 | 
	
		
			
				|  |  | +    // cause an error such as "The source directory .../CMakeFiles/CMakeTmp/b
 | 
	
		
			
				|  |  | +    // does not exist", thus breaking the try_compile or try_run completely.
 | 
	
		
			
				|  |  | +    //
 | 
	
		
			
				|  |  | +    // Strictly speaking the bug is in the wrapper macro because the CMake
 | 
	
		
			
				|  |  | +    // language has always flattened nested lists and the macro should escape
 | 
	
		
			
				|  |  | +    // the semicolons in its arguments before forwarding them.  However, this
 | 
	
		
			
				|  |  | +    // bug is so subtle that projects typically work anyway, usually because
 | 
	
		
			
				|  |  | +    // the value VAR=a is sufficient for the try_compile or try_run to get the
 | 
	
		
			
				|  |  | +    // correct result.  Calling SetArgs here would break such projects that
 | 
	
		
			
				|  |  | +    // previously built.  Instead we work around the issue by never reporting
 | 
	
		
			
				|  |  | +    // unused arguments and ignoring options such as --warn-unused-vars.
 | 
	
		
			
				|  |  | +    cm.SetWarnUnusedCli(false);
 | 
	
		
			
				|  |  | +    //cm.SetArgs(*cmakeArgs, true);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      cm.SetCacheArgs(*cmakeArgs);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    // to save time we pass the EnableLanguage info directly
 | 
	
	
		
			
				|  | @@ -3416,12 +3569,48 @@ std::string cmMakefile::GetListFileStack()
 | 
	
		
			
				|  |  |  void cmMakefile::PushScope()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    cmDefinitions* parent = &this->Internal->VarStack.top();
 | 
	
		
			
				|  |  | +  const std::set<cmStdString>& init = this->Internal->VarInitStack.top();
 | 
	
		
			
				|  |  | +  const std::set<cmStdString>& usage = this->Internal->VarUsageStack.top();
 | 
	
		
			
				|  |  |    this->Internal->VarStack.push(cmDefinitions(parent));
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.push(init);
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.push(usage);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void cmMakefile::PopScope()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +  cmDefinitions* current = &this->Internal->VarStack.top();
 | 
	
		
			
				|  |  | +  std::set<cmStdString> init = this->Internal->VarInitStack.top();
 | 
	
		
			
				|  |  | +  std::set<cmStdString> usage = this->Internal->VarUsageStack.top();
 | 
	
		
			
				|  |  | +  const std::set<cmStdString>& locals = current->LocalKeys();
 | 
	
		
			
				|  |  | +  // Remove initialization and usage information for variables in the local
 | 
	
		
			
				|  |  | +  // scope.
 | 
	
		
			
				|  |  | +  std::set<cmStdString>::const_iterator it = locals.begin();
 | 
	
		
			
				|  |  | +  for (; it != locals.end(); ++it)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    init.erase(*it);
 | 
	
		
			
				|  |  | +    if (!this->VariableUsed(it->c_str()))
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      this->CheckForUnused("out of scope", it->c_str());
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      usage.erase(*it);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    this->Internal->VarStack.pop();
 | 
	
		
			
				|  |  | +  this->Internal->VarInitStack.pop();
 | 
	
		
			
				|  |  | +  this->Internal->VarUsageStack.pop();
 | 
	
		
			
				|  |  | +  // Push initialization and usage up to the parent scope.
 | 
	
		
			
				|  |  | +  it = init.begin();
 | 
	
		
			
				|  |  | +  for (; it != init.end(); ++it)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->Internal->VarInitStack.top().insert(*it);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  it = usage.begin();
 | 
	
		
			
				|  |  | +  for (; it != usage.end(); ++it)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +    this->Internal->VarUsageStack.top().insert(*it);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void cmMakefile::RaiseScope(const char *var, const char *varDef)
 | 
	
	
		
			
				|  | @@ -3446,7 +3635,14 @@ void cmMakefile::RaiseScope(const char *var, const char *varDef)
 | 
	
		
			
				|  |  |      // directory's scope was initialized by the closure of the parent
 | 
	
		
			
				|  |  |      // scope, so we do not need to localize the definition first.
 | 
	
		
			
				|  |  |      cmMakefile* parent = plg->GetMakefile();
 | 
	
		
			
				|  |  | -    parent->Internal->VarStack.top().Set(var, varDef);
 | 
	
		
			
				|  |  | +    if (varDef)
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      parent->AddDefinition(var, varDef);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    else
 | 
	
		
			
				|  |  | +      {
 | 
	
		
			
				|  |  | +      parent->RemoveDefinition(var);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    else
 | 
	
		
			
				|  |  |      {
 |