Handle const, noreturn, return type

This commit is contained in:
chrchr-github 2023-06-05 22:12:30 +02:00 committed by chrchr
parent 220ad27fa8
commit 022fcb3be1
3 changed files with 37 additions and 27 deletions

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,12 +6667,6 @@ 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">
<use-retval/>
<const/>
<returnValue type="std::size_t"/>
<noreturn>false</noreturn>
</function>
<!-- size_type std::map::count( const Key& key ) const; --> <!-- size_type std::map::count( const Key& key ) const; -->
<!-- template< class K > size_type std::map::count( const K& x ) const; // since C++14 --> <!-- template< class K > size_type std::map::count( const K& x ) const; // since C++14 -->
<!-- size_type std::set::count( const value_type& val) const; --> <!-- size_type std::set::count( const value_type& val) const; -->
@ -6969,12 +6954,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 +8568,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 +8619,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"/>
@ -8757,7 +8736,7 @@ 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="length" yields="size" returnType="std::size_t"/>
<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);
} }
@ -1385,6 +1393,11 @@ 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 (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());
}
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
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));
@ -1479,6 +1492,12 @@ bool Library::isFunctionConst(const Token *ftok) const
{ {
if (ftok->function() && ftok->function()->isConst()) if (ftok->function() && ftok->function()->isConst())
return true; return true;
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;
}
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
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));
@ -1489,6 +1508,11 @@ bool Library::isnoreturn(const Token *ftok) const
{ {
if (ftok->function() && ftok->function()->isAttributeNoreturn()) if (ftok->function() && ftok->function()->isAttributeNoreturn())
return true; return true;
if (Token::simpleMatch(ftok->astParent(), ".")) {
if (astContainerAction(ftok->astParent()->astOperand1()) != Library::Container::Action::NO_ACTION ||
astContainerYield(ftok->astParent()->astOperand1()) != Library::Container::Yield::NO_YIELD)
return false;
}
if (isNotLibraryFunction(ftok)) if (isNotLibraryFunction(ftok))
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));

View File

@ -249,8 +249,9 @@ public:
NO_YIELD NO_YIELD
}; };
struct Function { struct Function {
Action action; Action action = Action::NO_ACTION;
Yield yield; Yield yield = Yield::NO_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),