Merge pull request #5129 from chrchr-github/chr_action_yield2
Detect container action and yield functions (2)
This commit is contained in:
commit
e31cd05ae9
|
@ -498,6 +498,11 @@
|
||||||
<ref name="CONTAINER-YIELDS"/>
|
<ref name="CONTAINER-YIELDS"/>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="returnType">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<empty/>
|
<empty/>
|
||||||
</element>
|
</element>
|
||||||
</zeroOrMore>
|
</zeroOrMore>
|
||||||
|
|
25
cfg/std.cfg
25
cfg/std.cfg
|
@ -6600,15 +6600,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<!-- bool empty() const; // until C++11 -->
|
|
||||||
<!-- constexpr bool empty() const noexcept; // since C++11 until C++20 -->
|
|
||||||
<!-- [[nodiscard]] constexpr bool empty() const noexcept; // since C++20 -->
|
|
||||||
<function name="std::array::empty,std::deque::empty,std::list::empty,std::forward_list::empty,std::map::empty,std::unordered_map::empty,std::queue::empty,std::set::empty,std::unordered_set::empty,std::stack::empty,std::string::empty,std::wstring::empty,std::basic_string::empty,std::vector::empty,std::span::empty">
|
|
||||||
<use-retval/>
|
|
||||||
<const/>
|
|
||||||
<returnValue type="bool"/>
|
|
||||||
<noreturn>false</noreturn>
|
|
||||||
</function>
|
|
||||||
<!-- void std::deque::push_back( const T& value ); -->
|
<!-- void std::deque::push_back( const T& value ); -->
|
||||||
<!-- void std::deque::push_back( T&& value ); // since C++11 -->
|
<!-- void std::deque::push_back( T&& value ); // since C++11 -->
|
||||||
<!-- void std::deque::push_front( const T& value ); -->
|
<!-- void std::deque::push_front( const T& value ); -->
|
||||||
|
@ -6676,7 +6667,7 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<not-uninit/>
|
<not-uninit/>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<function name="std::deque::size,std::deque::max_size,std::list::size,std::list::max_size,std::map::size,std::map::max_size,std::unordered_map::size,std::unordered_map::max_size,std::queue::size,std::set::size,std::set::max_size,std::unordered_set::size,std::unordered_set::max_size,std::stack::size,std::string::size,std::wstring::size,std::vector::size,std::vector::capacity,std::vector::max_size,std::array::size,std::array::max_size,std::span::size,std::span::size_bytes">
|
<function name="std::deque::max_size,std::list::max_size,std::map::max_size,std::unordered_map::max_size,std::set::max_size,std::unordered_set::max_size,std::vector::capacity,std::vector::max_size,std::span::size,std::span::size_bytes">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
<const/>
|
<const/>
|
||||||
<returnValue type="std::size_t"/>
|
<returnValue type="std::size_t"/>
|
||||||
|
@ -6969,12 +6960,6 @@ The obsolete function 'gets' is called. With 'gets' you'll get a buffer overrun
|
||||||
<valid>0:</valid>
|
<valid>0:</valid>
|
||||||
</arg>
|
</arg>
|
||||||
</function>
|
</function>
|
||||||
<function name="std::string::length,std::wstring::length,std::basic_string::size,std::basic_string::length">
|
|
||||||
<const/>
|
|
||||||
<use-retval/>
|
|
||||||
<returnValue type="std::size_t"/>
|
|
||||||
<noreturn>false</noreturn>
|
|
||||||
</function>
|
|
||||||
<function name="std::string::substr">
|
<function name="std::string::substr">
|
||||||
<use-retval/>
|
<use-retval/>
|
||||||
<returnValue type="std::string"/>
|
<returnValue type="std::string"/>
|
||||||
|
@ -8589,8 +8574,8 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
|
||||||
<size>
|
<size>
|
||||||
<function name="resize" action="resize"/>
|
<function name="resize" action="resize"/>
|
||||||
<function name="clear" action="clear"/>
|
<function name="clear" action="clear"/>
|
||||||
<function name="size" yields="size"/>
|
<function name="size" yields="size" returnType="std::size_t"/>
|
||||||
<function name="empty" yields="empty"/>
|
<function name="empty" yields="empty" returnType="bool"/>
|
||||||
<function name="erase" action="erase"/>
|
<function name="erase" action="erase"/>
|
||||||
<function name="insert" action="insert" yields="iterator"/>
|
<function name="insert" action="insert" yields="iterator"/>
|
||||||
<function name="emplace" action="push" yields="iterator"/>
|
<function name="emplace" action="push" yields="iterator"/>
|
||||||
|
@ -8640,7 +8625,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
|
||||||
</container>
|
</container>
|
||||||
<container id="stdArray" startPattern="std :: array <" inherits="stdContainer" opLessAllowed="true">
|
<container id="stdArray" startPattern="std :: array <" inherits="stdContainer" opLessAllowed="true">
|
||||||
<size templateParameter="1">
|
<size templateParameter="1">
|
||||||
<function name="max_size" yields="size"/>
|
<function name="max_size" yields="size" returnType="std::size_t"/>
|
||||||
</size>
|
</size>
|
||||||
<access indexOperator="array-like">
|
<access indexOperator="array-like">
|
||||||
<function name="at" yields="at_index"/>
|
<function name="at" yields="at_index"/>
|
||||||
|
@ -8750,6 +8735,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
|
||||||
<function name="replace" action="change"/>
|
<function name="replace" action="change"/>
|
||||||
<function name="reserve" action="change-internal"/>
|
<function name="reserve" action="change-internal"/>
|
||||||
<function name="shrink_to_fit" action="change-internal"/>
|
<function name="shrink_to_fit" action="change-internal"/>
|
||||||
|
<function name="length" yields="size" returnType="std::size_t"/>
|
||||||
</size>
|
</size>
|
||||||
<access indexOperator="array-like">
|
<access indexOperator="array-like">
|
||||||
<function name="at" yields="at_index"/>
|
<function name="at" yields="at_index"/>
|
||||||
|
@ -8757,7 +8743,6 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
|
||||||
<function name="back" yields="item"/>
|
<function name="back" yields="item"/>
|
||||||
<function name="data" yields="buffer"/>
|
<function name="data" yields="buffer"/>
|
||||||
<function name="c_str" yields="buffer-nt"/>
|
<function name="c_str" yields="buffer-nt"/>
|
||||||
<function name="length" yields="size"/>
|
|
||||||
<function name="find" action="find"/>
|
<function name="find" action="find"/>
|
||||||
<function name="rfind" action="find"/>
|
<function name="rfind" action="find"/>
|
||||||
<function name="find_last_of" action="find"/>
|
<function name="find_last_of" action="find"/>
|
||||||
|
|
|
@ -484,6 +484,10 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
|
||||||
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, yieldName);
|
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, yieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* const returnType = functionNode->Attribute("returnType");
|
||||||
|
if (returnType)
|
||||||
|
container.functions[functionName].returnType = returnType;
|
||||||
|
|
||||||
container.functions[functionName].action = action;
|
container.functions[functionName].action = action;
|
||||||
container.functions[functionName].yield = yield;
|
container.functions[functionName].yield = yield;
|
||||||
}
|
}
|
||||||
|
@ -905,6 +909,10 @@ Library::Error Library::loadFunction(const tinyxml2::XMLElement * const node, co
|
||||||
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, yieldName);
|
return Error(ErrorCode::BAD_ATTRIBUTE_VALUE, yieldName);
|
||||||
}
|
}
|
||||||
func.containerYield = yield;
|
func.containerYield = yield;
|
||||||
|
|
||||||
|
const char* const returnType = functionnode->Attribute("returnType");
|
||||||
|
if (returnType)
|
||||||
|
func.returnType = returnType;
|
||||||
} else
|
} else
|
||||||
unknown_elements.insert(functionnodename);
|
unknown_elements.insert(functionnodename);
|
||||||
}
|
}
|
||||||
|
@ -1358,17 +1366,18 @@ const Library::NonOverlappingData* Library::getNonOverlappingData(const Token *f
|
||||||
|
|
||||||
Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
|
Library::UseRetValType Library::getUseRetValType(const Token *ftok) const
|
||||||
{
|
{
|
||||||
if (Token::simpleMatch(ftok->astParent(), ".")) {
|
if (isNotLibraryFunction(ftok)) {
|
||||||
using Yield = Library::Container::Yield;
|
if (Token::simpleMatch(ftok->astParent(), ".")) {
|
||||||
using Action = Library::Container::Action;
|
const Token* contTok = ftok->astParent()->astOperand1();
|
||||||
const Yield yield = astContainerYield(ftok->astParent()->astOperand1());
|
using Yield = Library::Container::Yield;
|
||||||
if (yield == Yield::START_ITERATOR || yield == Yield::END_ITERATOR || yield == Yield::AT_INDEX ||
|
const Yield yield = astContainerYield(contTok);
|
||||||
yield == Yield::SIZE || yield == Yield::EMPTY || yield == Yield::BUFFER || yield == Yield::BUFFER_NT ||
|
if (yield == Yield::START_ITERATOR || yield == Yield::END_ITERATOR || yield == Yield::AT_INDEX ||
|
||||||
((yield == Yield::ITEM || yield == Yield::ITERATOR) && astContainerAction(ftok->astParent()->astOperand1()) == Action::NO_ACTION))
|
yield == Yield::SIZE || yield == Yield::EMPTY || yield == Yield::BUFFER || yield == Yield::BUFFER_NT ||
|
||||||
return Library::UseRetValType::DEFAULT;
|
((yield == Yield::ITEM || yield == Yield::ITERATOR) && astContainerAction(contTok) == Library::Container::Action::NO_ACTION))
|
||||||
}
|
return Library::UseRetValType::DEFAULT;
|
||||||
if (isNotLibraryFunction(ftok))
|
}
|
||||||
return Library::UseRetValType::NONE;
|
return Library::UseRetValType::NONE;
|
||||||
|
}
|
||||||
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
||||||
if (it != functions.cend())
|
if (it != functions.cend())
|
||||||
return it->second.useretval;
|
return it->second.useretval;
|
||||||
|
@ -1385,8 +1394,14 @@ const std::string& Library::returnValue(const Token *ftok) const
|
||||||
|
|
||||||
const std::string& Library::returnValueType(const Token *ftok) const
|
const std::string& Library::returnValueType(const Token *ftok) const
|
||||||
{
|
{
|
||||||
if (isNotLibraryFunction(ftok))
|
if (isNotLibraryFunction(ftok)) {
|
||||||
|
if (Token::simpleMatch(ftok->astParent(), ".") && ftok->astParent()->astOperand1()) {
|
||||||
|
const Token* contTok = ftok->astParent()->astOperand1();
|
||||||
|
if (contTok->valueType() && contTok->valueType()->container)
|
||||||
|
return contTok->valueType()->container->getReturnType(ftok->str());
|
||||||
|
}
|
||||||
return emptyString;
|
return emptyString;
|
||||||
|
}
|
||||||
const std::map<std::string, std::string>::const_iterator it = mReturnValueType.find(getFunctionName(ftok));
|
const std::map<std::string, std::string>::const_iterator it = mReturnValueType.find(getFunctionName(ftok));
|
||||||
return it != mReturnValueType.cend() ? it->second : emptyString;
|
return it != mReturnValueType.cend() ? it->second : emptyString;
|
||||||
}
|
}
|
||||||
|
@ -1479,8 +1494,15 @@ bool Library::isFunctionConst(const Token *ftok) const
|
||||||
{
|
{
|
||||||
if (ftok->function() && ftok->function()->isConst())
|
if (ftok->function() && ftok->function()->isConst())
|
||||||
return true;
|
return true;
|
||||||
if (isNotLibraryFunction(ftok))
|
if (isNotLibraryFunction(ftok)) {
|
||||||
|
if (Token::simpleMatch(ftok->astParent(), ".")) {
|
||||||
|
using Yield = Library::Container::Yield;
|
||||||
|
const Yield yield = astContainerYield(ftok->astParent()->astOperand1());
|
||||||
|
if (yield == Yield::EMPTY || yield == Yield::SIZE || yield == Yield::BUFFER_NT)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
const std::unordered_map<std::string, Function>::const_iterator it = functions.find(getFunctionName(ftok));
|
||||||
return (it != functions.cend() && it->second.isconst);
|
return (it != functions.cend() && it->second.isconst);
|
||||||
}
|
}
|
||||||
|
@ -1489,8 +1511,15 @@ bool Library::isnoreturn(const Token *ftok) const
|
||||||
{
|
{
|
||||||
if (ftok->function() && ftok->function()->isAttributeNoreturn())
|
if (ftok->function() && ftok->function()->isAttributeNoreturn())
|
||||||
return true;
|
return true;
|
||||||
if (isNotLibraryFunction(ftok))
|
if (isNotLibraryFunction(ftok)) {
|
||||||
|
if (Token::simpleMatch(ftok->astParent(), ".")) {
|
||||||
|
const Token* contTok = ftok->astParent()->astOperand1();
|
||||||
|
if (astContainerAction(contTok) != Library::Container::Action::NO_ACTION ||
|
||||||
|
astContainerYield(contTok) != Library::Container::Yield::NO_YIELD)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
const std::unordered_map<std::string, FalseTrueMaybe>::const_iterator it = mNoReturn.find(getFunctionName(ftok));
|
const std::unordered_map<std::string, FalseTrueMaybe>::const_iterator it = mNoReturn.find(getFunctionName(ftok));
|
||||||
if (it == mNoReturn.end())
|
if (it == mNoReturn.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -251,6 +251,7 @@ public:
|
||||||
struct Function {
|
struct Function {
|
||||||
Action action;
|
Action action;
|
||||||
Yield yield;
|
Yield yield;
|
||||||
|
std::string returnType;
|
||||||
};
|
};
|
||||||
struct RangeItemRecordTypeItem {
|
struct RangeItemRecordTypeItem {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -284,6 +285,11 @@ public:
|
||||||
return Yield::NO_YIELD;
|
return Yield::NO_YIELD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& getReturnType(const std::string& function) const {
|
||||||
|
auto i = functions.find(function);
|
||||||
|
return (i != functions.end()) ? i->second.returnType : emptyString;
|
||||||
|
}
|
||||||
|
|
||||||
static Yield yieldFrom(const std::string& yieldName);
|
static Yield yieldFrom(const std::string& yieldName);
|
||||||
static Action actionFrom(const std::string& actionName);
|
static Action actionFrom(const std::string& actionName);
|
||||||
};
|
};
|
||||||
|
@ -359,6 +365,7 @@ public:
|
||||||
bool formatstr_secure;
|
bool formatstr_secure;
|
||||||
Container::Action containerAction;
|
Container::Action containerAction;
|
||||||
Container::Yield containerYield;
|
Container::Yield containerYield;
|
||||||
|
std::string returnType;
|
||||||
Function()
|
Function()
|
||||||
: use(false),
|
: use(false),
|
||||||
leakignore(false),
|
leakignore(false),
|
||||||
|
|
Loading…
Reference in New Issue