Merge pull request #5129 from chrchr-github/chr_action_yield2

Detect container action and yield functions (2)
This commit is contained in:
chrchr-github 2023-06-16 22:47:19 +02:00 committed by GitHub
commit e31cd05ae9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 33 deletions

View File

@ -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>

View File

@ -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 &lt;" inherits="stdContainer" opLessAllowed="true"> <container id="stdArray" startPattern="std :: array &lt;" 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"/>

View File

@ -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;

View File

@ -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),