Complete strict-mode checks for uninitialized vars

This commit is contained in:
Ben Boeckel 2010-08-24 14:38:06 -04:00
parent 52f9637174
commit f332e14ff2
3 changed files with 37 additions and 2 deletions

View File

@ -127,7 +127,7 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
// check to see if we need to print a warning // check to see if we need to print a warning
// if strict mode is on and the variable has // if strict mode is on and the variable has
// not been "cleared"/initialized with a set(foo ) call // not been "cleared"/initialized with a set(foo ) call
if(this->StrictMode && !this->Makefile->VariableCleared(var)) if(this->StrictMode && !this->Makefile->VariableInitialized(var))
{ {
cmOStringStream msg; cmOStringStream msg;
msg << this->FileName << ":" << this->FileLine << ":" << msg << this->FileName << ":" << this->FileLine << ":" <<

View File

@ -43,13 +43,17 @@ class cmMakefile::Internals
{ {
public: public:
std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack; std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack;
std::stack<std::set<cmStdString> > VarInitStack;
std::set<cmStdString> VarRemoved; std::set<cmStdString> VarRemoved;
}; };
// default is not to be building executables // default is not to be building executables
cmMakefile::cmMakefile(): Internal(new Internals) 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);
// Setup the default include file regular expression (match everything). // Setup the default include file regular expression (match everything).
this->IncludeFileRegularExpression = "^.*$"; this->IncludeFileRegularExpression = "^.*$";
@ -1685,6 +1689,7 @@ void cmMakefile::AddCacheDefinition(const char* name, const char* value,
void cmMakefile::AddDefinition(const char* name, bool value) void cmMakefile::AddDefinition(const char* name, bool value)
{ {
this->Internal->VarStack.top().Set(name, value? "ON" : "OFF"); this->Internal->VarStack.top().Set(name, value? "ON" : "OFF");
this->Internal->VarInitStack.top().insert(name);
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch(); cmVariableWatch* vv = this->GetVariableWatch();
if ( vv ) if ( vv )
@ -1695,6 +1700,15 @@ void cmMakefile::AddDefinition(const char* name, bool value)
#endif #endif
} }
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::VariableCleared(const char* var) const bool cmMakefile::VariableCleared(const char* var) const
{ {
if(this->Internal->VarRemoved.find(var) != this->Internal->VarRemoved.end()) if(this->Internal->VarRemoved.find(var) != this->Internal->VarRemoved.end())
@ -1708,6 +1722,7 @@ void cmMakefile::RemoveDefinition(const char* name)
{ {
this->Internal->VarStack.top().Set(name, 0); this->Internal->VarStack.top().Set(name, 0);
this->Internal->VarRemoved.insert(name); this->Internal->VarRemoved.insert(name);
this->Internal->VarInitStack.top().insert(name);
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* vv = this->GetVariableWatch(); cmVariableWatch* vv = this->GetVariableWatch();
if ( vv ) if ( vv )
@ -3316,12 +3331,30 @@ std::string cmMakefile::GetListFileStack()
void cmMakefile::PushScope() void cmMakefile::PushScope()
{ {
cmDefinitions* parent = &this->Internal->VarStack.top(); cmDefinitions* parent = &this->Internal->VarStack.top();
const std::set<cmStdString>& init = this->Internal->VarInitStack.top();
this->Internal->VarStack.push(cmDefinitions(parent)); this->Internal->VarStack.push(cmDefinitions(parent));
this->Internal->VarInitStack.push(init);
} }
void cmMakefile::PopScope() void cmMakefile::PopScope()
{ {
cmDefinitions* current = &this->Internal->VarStack.top();
std::set<cmStdString> init = this->Internal->VarInitStack.top();
const std::set<cmStdString>& locals = current->LocalKeys();
// Remove initialization information for variables in the local scope.
std::set<cmStdString>::const_iterator it = locals.begin();
for (; it != locals.end(); ++it)
{
init.erase(*it);
}
this->Internal->VarStack.pop(); this->Internal->VarStack.pop();
this->Internal->VarInitStack.pop();
// Push initialization up to the parent scope.
it = init.begin();
for (; it != init.end(); ++it)
{
this->Internal->VarInitStack.top().insert(*it);
}
} }
void cmMakefile::RaiseScope(const char *var, const char *varDef) void cmMakefile::RaiseScope(const char *var, const char *varDef)

View File

@ -61,6 +61,8 @@ public:
unsigned int GetCacheMajorVersion(); unsigned int GetCacheMajorVersion();
unsigned int GetCacheMinorVersion(); unsigned int GetCacheMinorVersion();
/* return true if a variable has been initialized */
bool VariableInitialized(const char* ) const;
/* return true if a variable has been set with /* return true if a variable has been set with
set(foo ) set(foo )
*/ */