MantisBT - CMake
View Issue Details
0013786CMakeCMakepublic2012-12-12 05:012016-06-10 14:31
Andreas Mohr 
Kitware Robot 
highmajoralways
closedmoved 
PCLinux / WindowsRHEL5 / 7
CMake 2.8.10.2 
 
0013786: function() set(PARENT_SCOPE) buggy: very surprising warn-uninitialized inconsistency for (non-)empty values
I tried to get all my code free of issues,
thus I enabled --warn-uninitialized.
I was very surprised to find that initialization state of a function result (PARENT_SCOPE) variable is being very negatively influenced by the value of the passed variable being empty vs. non-empty,
as can be gathered from the sample below warning about result_empty yet properly *not* warning about result_non_empty.

This should emphatically _not_ be the case - a result variable should *always* get properly initialized (instantiated) in outer scope, no fr****n' matter which value it may happen to get assigned.

And it's not a "this variable already exists in outer scope" vs. "does not exist --> problem" issue: when assigning non-empty values the outer-scope variable *does* get created, yet not for empty ones --> BUG.

Note that pre-initializing the result var to "" prior to invoking the function does successfully silence the initialization warning.
And note that doing this initialization with a non-empty value and subsequently calling the function *does* let the function reset the variable to empty - IOW the variable *does* get assigned by the function in *this* case - just not if it didn't exist previously!

Happening on both Win7 2.8.10.2 and RHEL5 2.8.8.....

Severity major and prio high since it's a foundation-shattering inconsistency ;)

Given this bug it's impossible to get one's code warning-free (when making use of clean result-use-only variable getter functions which happen to return empty values in certain conditions).
A mere "not succeeding in getting the code warning-free" is a rather benign concern - some actively disrupting bug scenarios due to this issue might be conceivable, too.

Thanks!
cmake_minimum_required(VERSION 2.8)

function(getter _result)
  set(result_ "${desired_result}")
  set(${_result} "${result_}" PARENT_SCOPE)
endfunction(getter _result)

#set(result_empty "bye, cruel world") # <---- toggle this!

set(desired_result "")
getter(result_empty)

set(desired_result "non-empty")
getter(result_non_empty)

message("result_empty ${result_empty}, result_non_empty ${result_non_empty}.")
$ cmake --warn-uninitialized .
Warn about uninitialized values.
CMake Warning (dev) at /home/amoh/privat/cmake_tests/bug_function_result_uninitialized_warning/CMakeLists.txt:14:
  uninitialized variable 'result_empty'
This warning is for project developers. Use -Wno-dev to suppress it.

result_empty , result_non_empty non-empty.
-- Configuring done
-- Generating done
No tags attached.
Issue History
2012-12-12 05:01Andreas MohrNew Issue
2012-12-14 03:46Andreas MohrNote Added: 0031887
2013-08-30 08:03Mark AbrahamNote Added: 0033765
2013-08-30 08:04Mark AbrahamNote Edited: 0033765bug_revision_view_page.php?bugnote_id=33765#r1249
2013-08-30 08:07Mark AbrahamNote Edited: 0033765bug_revision_view_page.php?bugnote_id=33765#r1250
2013-08-30 08:16Mark AbrahamNote Edited: 0033765bug_revision_view_page.php?bugnote_id=33765#r1251
2016-06-10 14:28Kitware RobotNote Added: 0042169
2016-06-10 14:28Kitware RobotStatusnew => resolved
2016-06-10 14:28Kitware RobotResolutionopen => moved
2016-06-10 14:28Kitware RobotAssigned To => Kitware Robot
2016-06-10 14:31Kitware RobotStatusresolved => closed

Notes
(0031887)
Andreas Mohr   
2012-12-14 03:46   
Source side analysis:

Source/cmSetCommand.cxx currently has:

  if (parentScope)
    {
    if (value.empty())
      {
      this->Makefile->RaiseScope(variable, 0);
      }
    else
      {
      this->Makefile->RaiseScope(variable, value.c_str());
      }
      return true;
    }


git blame shows that

commit fc8ce174334c3c33141d37ff2b86ea50226b7ce4
Author: Alexander Neundorf <neundorf@kde.org>
Date: Fri Jan 18 15:52:54 2008 -0500

    ENH: remove RAISE_SCOPE() again and instead add SET(<var> <value> PARENT_SCOPE)
    
    Alex

changed it from

- if (args.size() == 1)
- {
- this->Makefile->RaiseScope(args[0].c_str(), 0);
- }
- else
- {
- this->Makefile->RaiseScope(args[0].c_str(), args[1].c_str());
- }


raise_scope() was documented (git show of this commit) to remove the variable in parent scope in case of a *missing* second arg (variable value).
For raise_scope() this API behaviour likely made sense.
For set(PARENT_SCOPE), value.empty() gets transformed to the former "missing second arg" case, thus the variable gets removed, *even if it does have a valid empty string*!


Note that we seem to have a second problem, too:
When pre-setting a variable (the "toggle this!" case in my sample above) *prior* to invalidating it via set(PARENT_SCOPE) in a function sub scope, there will *not* be an "uninitialized variable" warning printed for a subsequent access by parent scope. However, this is what I would expect for the "removed from the parent scope" case of raise_scope(). The variable should not merely be marked "removed" (by setting its value to empty string, NULL, or whatever), but marked "uninitialized" as well, that's what I would have expected (however whether my expectation actually matches desireable best practice behaviour remains to be discussed, i.e. whether a variable with a former "valid" state should be reverted to "uninitialized" state).
(0033765)
Mark Abraham   
2013-08-30 08:03   
(edited on: 2013-08-30 08:16)
I see similar behaviour with

set(varname value PARENT_SCOPE)

in a CMakeLists.txt accessed via add_subdirectory(), using cmake 2.8.10.1 (distro) and 2.8.11 (compiled by me) on Ubuntu 13.04. Whether or not varname has a previous value in local or parent scope, the call to set() does not set varname to the new value, in either scope.

(0042169)
Kitware Robot   
2016-06-10 14:28   
Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.