#ifndef CXXFOOZZ_STATEMENT_HPP #define CXXFOOZZ_STATEMENT_HPP #include #include "model.hpp" #include "type.hpp" #include "program-context.hpp" /** * Classes in this file are used for random method-call/statement sequence generation * IMPORTANT: Must utilize data fields defined in model.hpp */ namespace cxxfoozz { enum class StatementVariant { kPrimitiveAssignment = 0, kCall, kSTLConstruction, kArrayInitialization, }; class Operand; class Statement { public: explicit Statement(const TypeWithModifier &type); virtual ~Statement(); const TypeWithModifier &GetType() const; void SetType(const TypeWithModifier &type); const bpstd::optional &GetVarName() const; void SetVarName(const bpstd::optional &var_name); void ClearVarName(); virtual std::shared_ptr Clone() = 0; virtual StatementVariant GetVariant() const = 0; virtual std::pair, int> ReplaceRefOperand( const std::map, std::shared_ptr> &repl_map, const std::shared_ptr &tt_ctx ) = 0; virtual std::vector GetStatementOperands() const = 0; private: TypeWithModifier type_; bpstd::optional var_name_; }; enum class OperandType { kConstantOperand = 0, kRefOperand, }; class Operand { public: Operand( TypeWithModifier type, std::shared_ptr ref, bpstd::optional constant_literal ); Operand(const Operand &other); Operand &operator=(const Operand &other); bool operator==(const Operand &rhs) const; bool operator!=(const Operand &rhs) const; static Operand MakeRefOperand(const std::shared_ptr &ref); static Operand MakeConstantOperand(const TypeWithModifier &type, const std::string &literal); static Operand MakeBottom(); const TypeWithModifier &GetType() const; const std::shared_ptr &GetRef() const; const bpstd::optional &GetConstantLiteral() const; OperandType GetOperandType() const; std::string ToStringWithAutoCasting( const TypeWithModifier &type_rq, const std::shared_ptr &itm ) const; std::string ToStringWithAutoCasting( const TypeWithModifier &type_rq, const std::shared_ptr &tt_ctx, const std::shared_ptr &itm ) const; bool IsNullPtr() const; // static void SetKLibFuzzerMode(bool k_lib_fuzzer_mode); static bool IsKLibFuzzerMode(); class LibFuzzerModeHacker { public: LibFuzzerModeHacker(); virtual ~LibFuzzerModeHacker(); }; private: std::string InternalToString() const; TypeWithModifier type_; std::shared_ptr ref_; bpstd::optional constant_literal_; static bool kLibFuzzerMode; }; enum class GeneralPrimitiveOp { kNop = 0, kAdd, kSub, kMul, kDiv, kMod, kMinus, }; enum class OpArity { kUnary = 0, kBinary }; class PrimitiveAssignmentStatement : public Statement { public: PrimitiveAssignmentStatement( const TypeWithModifier &type, GeneralPrimitiveOp op, std::vector operands ); virtual ~PrimitiveAssignmentStatement(); static std::shared_ptr MakeUnaryOpStatement(const Operand &op, GeneralPrimitiveOp o); static std::shared_ptr MakeBinOpStatement(const Operand &op1, const Operand &op2, GeneralPrimitiveOp o); GeneralPrimitiveOp GetOp() const; std::vector &GetOperands(); void SetOp(GeneralPrimitiveOp op); void SetOperands(const std::vector &operands); std::shared_ptr Clone() override; StatementVariant GetVariant() const override; OpArity GetOpArity() const; std::pair, int> ReplaceRefOperand( const std::map, std::shared_ptr> &repl_map, const std::shared_ptr &tt_ctx ) override; std::vector GetStatementOperands() const override; private: GeneralPrimitiveOp op_; std::vector operands_; }; class ArrayInitStatement : public Statement { public: ArrayInitStatement( const TypeWithModifier &type, const bpstd::optional &capacity, bpstd::optional string_literal, bpstd::optional> elements ); static std::shared_ptr MakeCString(const Operand &op); static std::shared_ptr MakeArrayInitialization( const TypeWithModifier &target_type, const std::vector &operands ); std::shared_ptr Clone() override; StatementVariant GetVariant() const override; std::pair, int> ReplaceRefOperand( const std::map, std::shared_ptr> &repl_map, const std::shared_ptr &tt_ctx ) override; std::vector GetStatementOperands() const override; const bpstd::optional &GetCapacity() const; const bpstd::optional &GetStringLiteral() const; const bpstd::optional> &GetElements() const; void SetCapacity(const bpstd::optional &capacity); void SetStringLiteral(const bpstd::optional &string_literal); void SetElements(const bpstd::optional> &elements); private: bpstd::optional capacity_; bpstd::optional string_literal_; // for char[] bpstd::optional> elements_; // for other types }; class CallStatement : public Statement { public: CallStatement( const TypeWithModifier &type, std::shared_ptr target, std::vector operands, bpstd::optional invoking_obj, const std::shared_ptr &template_type_context ); static std::shared_ptr MakeExecutableCall( const std::shared_ptr &target, const std::vector &ops, const bpstd::optional &invoking_obj, const std::shared_ptr &tt_ctx ); const std::shared_ptr &GetTarget() const; std::vector &GetOperands(); const bpstd::optional &GetInvokingObj() const; const std::shared_ptr &GetTemplateTypeContext() const; void SetTarget(const std::shared_ptr &target); void SetOperands(const std::vector &operands); void SetInvokingObj(const bpstd::optional &invoking_obj); std::shared_ptr Clone() override; StatementVariant GetVariant() const override; std::pair, int> ReplaceRefOperand( const std::map, std::shared_ptr> &repl_map, const std::shared_ptr &tt_ctx ) override; std::vector GetStatementOperands() const override; private: std::shared_ptr target_; std::vector operands_; bpstd::optional invoking_obj_; std::shared_ptr template_type_context_; }; class STLStatement; class STLElement { public: STLElement( bpstd::optional> reg_container_elmts, bpstd::optional>> key_value_elmts ); static STLElement ForRegularContainer(const std::vector &operands); static STLElement ForKeyValueContainer(const std::vector> &operands); const std::vector &GetRegContainerElmts() const; const std::vector> &GetKeyValueElmts() const; bool IsKeyValueElements() const; bool IsRegContainerElements() const; friend class STLStatement; private: bpstd::optional> reg_container_elmts_; bpstd::optional>> key_value_elmts_; }; class STLStatement : public Statement { public: STLStatement( const TypeWithModifier &type, std::shared_ptr target, STLElement elements ); static std::shared_ptr MakeSTLStatement( const TypeWithModifier &type, std::shared_ptr target, STLElement elements ); const std::shared_ptr &GetTarget() const; const STLElement &GetElements() const; std::shared_ptr Clone() override; StatementVariant GetVariant() const override; std::pair, int> ReplaceRefOperand( const std::map, std::shared_ptr> &repl_map, const std::shared_ptr &tt_ctx ) override; std::vector GetStatementOperands() const override; void SetElements(const STLElement &elements); private: std::shared_ptr target_; STLElement elements_; }; class StatementWriter { public: explicit StatementWriter(const std::shared_ptr &context); std::string StmtAsString(const std::shared_ptr &stmt, unsigned int stmt_id); private: std::string PrimitiveAssStmtAsString(const std::shared_ptr &stmt, unsigned int stmt_id); std::string CallStmtAsString(const std::shared_ptr &stmt, unsigned int stmt_id); std::string ArrayInitStmtAsString(const std::shared_ptr &stmt, unsigned int stmt_id); private: const std::shared_ptr &context_; }; class STLStatementWriter { public: STLStatementWriter(const std::shared_ptr &context); std::string STLStmtAsString( const std::shared_ptr &stmt, unsigned int stmt_id, const std::string &force_varname = "" ); private: void HandleStackAndQueue( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandlePriorityQueue( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, unsigned int stmt_id, std::stringstream &ss, std::stringstream &prelim_ss ); void HandleStandardRegContainer( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandleArray( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandleKeyValueContainer( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandlePair( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandleTuple( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandleSmartPointer( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); void HandleString( const TemplateTypeInstList &inst_list, const STLElement &stl_elements, std::stringstream &ss ); private: const std::shared_ptr &context_; }; } // namespace cxxfoozz #endif //CXXFOOZZ_STATEMENT_HPP