2019-09-17 21:00:59 +02:00
/*
* Cppcheck - A tool for static C / C + + code analysis
* Copyright ( C ) 2007 - 2019 Cppcheck team .
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
# ifndef exprengineH
# define exprengineH
//---------------------------------------------------------------------------
2019-09-19 19:40:00 +02:00
# include "config.h"
2019-09-17 21:00:59 +02:00
# include <functional>
# include <map>
# include <memory>
# include <set>
# include <string>
# include <vector>
# include <stdint.h>
class ErrorLogger ;
class Tokenizer ;
class Scope ;
class Settings ;
class Token ;
2019-09-25 18:33:21 +02:00
class Variable ;
2019-09-17 21:00:59 +02:00
# ifdef __GNUC__
typedef __int128_t int128_t ;
# else
typedef long long int128_t ;
2019-09-18 21:50:23 +02:00
# ifdef _MSC_VER
# pragma message(__FILE__ "(" _CRT_STRINGIZE(__LINE__) ")" ": warning: TODO No 128-bit integer type is available => Limited analysis of large integers...")
# else
2019-09-17 21:00:59 +02:00
# warning TODO No 128-bit integer type is available => Limited analysis of large integers
# endif
2019-09-18 21:50:23 +02:00
# endif
2019-09-17 21:00:59 +02:00
namespace ExprEngine {
std : : string str ( int128_t ) ;
// TODO we need to handle floats, containers, pointers, aliases and structs and stuff
2019-09-23 20:27:13 +02:00
enum class ValueType {
UninitValue ,
IntRange ,
FloatRange ,
PointerValue ,
2019-09-26 10:03:58 +02:00
ConditionalValue ,
2019-09-23 20:27:13 +02:00
ArrayValue ,
StringLiteralValue ,
StructValue ,
AddressOfValue ,
BinOpResult ,
IntegerTruncation
} ;
2019-09-17 21:00:59 +02:00
class Value ;
typedef std : : shared_ptr < Value > ValuePtr ;
class Value {
public :
2019-09-26 10:03:58 +02:00
Value ( const std : : string & name , const ValueType type ) : name ( name ) , type ( type ) { }
2019-09-17 21:00:59 +02:00
virtual ~ Value ( ) { }
2019-09-26 10:03:58 +02:00
virtual std : : string getRange ( ) const {
return name ;
}
virtual std : : string getSymbolicExpression ( ) const {
return name ;
}
2019-09-17 21:00:59 +02:00
virtual bool isIntValueInRange ( int value ) const {
( void ) value ;
return false ;
}
const std : : string name ;
2019-09-26 10:03:58 +02:00
ValueType type ;
2019-09-17 21:00:59 +02:00
} ;
class UninitValue : public Value {
public :
2019-09-26 10:03:58 +02:00
UninitValue ( ) : Value ( " ? " , ValueType : : UninitValue ) { }
2019-09-17 21:00:59 +02:00
} ;
class IntRange : public Value {
public :
IntRange ( const std : : string & name , int128_t minValue , int128_t maxValue )
2019-09-26 10:03:58 +02:00
: Value ( name , ValueType : : IntRange )
2019-09-17 21:00:59 +02:00
, minValue ( minValue )
, maxValue ( maxValue ) {
}
std : : string getRange ( ) const override {
2019-09-21 14:17:16 +02:00
if ( minValue = = maxValue )
return str ( minValue ) ;
return str ( minValue ) + " : " + str ( maxValue ) ;
2019-09-17 21:00:59 +02:00
}
bool isIntValueInRange ( int value ) const override {
return value > = minValue & & value < = maxValue ;
}
int128_t minValue ;
int128_t maxValue ;
} ;
2019-09-22 21:14:20 +02:00
class FloatRange : public Value {
public :
FloatRange ( const std : : string & name , long double minValue , long double maxValue )
2019-09-26 10:03:58 +02:00
: Value ( name , ValueType : : FloatRange )
2019-09-22 21:14:20 +02:00
, minValue ( minValue )
, maxValue ( maxValue ) {
}
std : : string getRange ( ) const override {
return std : : to_string ( minValue ) + " : " + std : : to_string ( maxValue ) ;
}
long double minValue ;
long double maxValue ;
} ;
2019-09-17 21:00:59 +02:00
class PointerValue : public Value {
public :
2019-09-22 10:56:49 +02:00
PointerValue ( const std : : string & name , ValuePtr data , bool null , bool uninitData )
2019-09-26 10:03:58 +02:00
: Value ( name , ValueType : : PointerValue )
2019-09-22 10:56:49 +02:00
, data ( data )
, null ( null )
, uninitData ( uninitData ) {
}
std : : string getRange ( ) const override ;
2019-09-17 21:00:59 +02:00
ValuePtr data ;
2019-09-22 10:56:49 +02:00
bool null ;
bool uninitData ;
2019-09-17 21:00:59 +02:00
} ;
2019-09-26 10:03:58 +02:00
class ConditionalValue : public Value {
public :
typedef std : : vector < std : : pair < ValuePtr , ValuePtr > > Vector ;
ConditionalValue ( const std : : string & name , const Vector & values ) : Value ( name , ValueType : : ConditionalValue ) , values ( values ) { }
std : : string getSymbolicExpression ( ) const override ;
Vector values ;
} ;
2019-09-17 21:00:59 +02:00
class ArrayValue : public Value {
public :
const int MAXSIZE = 0x100000 ;
2019-09-25 18:33:21 +02:00
ArrayValue ( const std : : string & name , ValuePtr size , ValuePtr value ) ;
ArrayValue ( const std : : string & name , const Variable * var ) ;
2019-09-17 21:00:59 +02:00
2019-09-26 10:03:58 +02:00
std : : string getSymbolicExpression ( ) const override ;
2019-09-17 21:00:59 +02:00
void assign ( ValuePtr index , ValuePtr value ) ;
2019-09-24 22:22:16 +02:00
void clear ( ) ;
2019-09-26 10:03:58 +02:00
ConditionalValue : : Vector read ( ValuePtr index ) const ;
2019-09-25 18:33:21 +02:00
struct IndexAndValue {
ValuePtr index ;
ValuePtr value ;
} ;
std : : vector < IndexAndValue > data ;
ValuePtr size ;
2019-09-17 21:00:59 +02:00
} ;
2019-09-21 11:36:34 +02:00
class StringLiteralValue : public Value {
public :
2019-09-26 10:03:58 +02:00
StringLiteralValue ( const std : : string & name , const std : : string & s ) : Value ( name , ValueType : : StringLiteralValue ) , string ( s ) { }
2019-09-21 11:36:34 +02:00
std : : string getRange ( ) const override {
return " \" " + string + " \" " ;
}
int size ( ) const {
return string . size ( ) ;
}
const std : : string string ;
} ;
2019-09-17 21:00:59 +02:00
class StructValue : public Value {
public :
2019-09-26 10:03:58 +02:00
explicit StructValue ( const std : : string & name ) : Value ( name , ValueType : : StructValue ) { }
2019-09-17 21:00:59 +02:00
ValuePtr getValueOfMember ( const std : : string & name ) const {
auto it = member . find ( name ) ;
return ( it = = member . end ( ) ) ? ValuePtr ( ) : it - > second ;
}
std : : map < std : : string , ValuePtr > member ;
} ;
class AddressOfValue : public Value {
public :
AddressOfValue ( const std : : string & name , int varId )
2019-09-26 10:03:58 +02:00
: Value ( name , ValueType : : AddressOfValue )
2019-09-17 21:00:59 +02:00
, varId ( varId )
{ }
std : : string getRange ( ) const override {
2019-09-26 10:03:58 +02:00
return " &@ " + std : : to_string ( varId ) ;
2019-09-17 21:00:59 +02:00
}
int varId ;
} ;
class BinOpResult : public Value {
public :
BinOpResult ( const std : : string & binop , ValuePtr op1 , ValuePtr op2 )
2019-09-26 10:03:58 +02:00
: Value ( " ( " + op1 - > name + " ) " + binop + " ( " + op2 - > name + " ) " , ValueType : : BinOpResult )
2019-09-17 21:00:59 +02:00
, binop ( binop )
, op1 ( op1 )
, op2 ( op2 ) {
auto b1 = std : : dynamic_pointer_cast < BinOpResult > ( op1 ) ;
if ( b1 )
mLeafs = b1 - > mLeafs ;
else
mLeafs . insert ( op1 ) ;
auto b2 = std : : dynamic_pointer_cast < BinOpResult > ( op2 ) ;
if ( b2 )
mLeafs . insert ( b2 - > mLeafs . begin ( ) , b2 - > mLeafs . end ( ) ) ;
else
mLeafs . insert ( op2 ) ;
}
std : : string getRange ( ) const override ;
2019-09-22 21:14:20 +02:00
struct IntOrFloatValue {
void setIntValue ( int128_t v ) {
type = INT ;
intValue = v ;
floatValue = 0 ;
}
void setFloatValue ( long double v ) {
type = FLOAT ;
intValue = 0 ;
floatValue = v ;
}
enum { INT , FLOAT } type ;
bool isFloat ( ) const {
return type = = FLOAT ;
}
int128_t intValue ;
long double floatValue ;
} ;
void getRange ( IntOrFloatValue * minValue , IntOrFloatValue * maxValue ) const ;
2019-09-17 21:00:59 +02:00
bool isIntValueInRange ( int value ) const override ;
std : : string binop ;
ValuePtr op1 ;
ValuePtr op2 ;
private :
2019-09-22 21:14:20 +02:00
IntOrFloatValue evaluate ( int test , const std : : map < ValuePtr , int > & valueBit ) const ;
IntOrFloatValue evaluateOperand ( int test , const std : : map < ValuePtr , int > & valueBit , ValuePtr value ) const ;
2019-09-17 21:00:59 +02:00
std : : set < ValuePtr > mLeafs ;
} ;
2019-09-23 20:27:13 +02:00
class IntegerTruncation : public Value {
public :
IntegerTruncation ( const std : : string & name , ValuePtr inputValue , int bits , char sign )
2019-09-26 10:03:58 +02:00
: Value ( name , ValueType : : IntegerTruncation )
2019-09-23 20:27:13 +02:00
, inputValue ( inputValue )
, bits ( bits )
, sign ( sign ) {
}
2019-09-26 10:03:58 +02:00
std : : string getSymbolicExpression ( ) const override ;
2019-09-23 20:27:13 +02:00
ExprEngine : : ValuePtr inputValue ;
int bits ;
char sign ;
} ;
2019-09-17 21:00:59 +02:00
typedef std : : function < void ( const Token * , const ExprEngine : : Value & ) > Callback ;
/** Execute all functions */
2019-09-19 19:40:00 +02:00
void CPPCHECKLIB executeAllFunctions ( const Tokenizer * tokenizer , const Settings * settings , const std : : vector < Callback > & callbacks ) ;
2019-09-17 21:00:59 +02:00
void executeFunction ( const Scope * functionScope , const Tokenizer * tokenizer , const Settings * settings , const std : : vector < Callback > & callbacks ) ;
void runChecks ( ErrorLogger * errorLogger , const Tokenizer * tokenizer , const Settings * settings ) ;
}
# endif // exprengineH