diff options
author | user1 <user1@ubuntu> | 2017-05-27 19:43:58 +0000 |
---|---|---|
committer | user1 <user1@ubuntu> | 2017-05-27 19:43:58 +0000 |
commit | 1ac6fe4340271b25d8a86c8b17bd059ed3642358 (patch) | |
tree | 60862a3fb6ac37b95348e94a186482881dee5b66 /safercpp | |
parent | added more bad strain extractions (diff) | |
download | mutator-1ac6fe4340271b25d8a86c8b17bd059ed3642358.tar.gz mutator-1ac6fe4340271b25d8a86c8b17bd059ed3642358.zip |
a bunch of stuff, including handling of fread and fwrite
Diffstat (limited to 'safercpp')
-rw-r--r-- | safercpp/safercpp-arr.cpp | 2804 |
1 files changed, 2015 insertions, 789 deletions
diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index f647ed1..7142e70 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -294,12 +294,34 @@ public: class CIndirectionState { public: - CIndirectionState(std::string original, std::string current, bool current_is_function_type = false) - : m_original(original), m_current(current), m_current_is_function_type(current_is_function_type) {} + CIndirectionState(const std::string& original, const std::string& current, + bool current_is_function_type = false, const std::vector<std::string>& params = std::vector<std::string>()) + : m_original(original), m_current(current), m_current_is_function_type(current_is_function_type), + m_params_original(params), m_params_current(params) {} + CIndirectionState(const std::string& original, const std::string& current, + const std::string& array_size_expr) + : m_original(original), m_current(current), m_original_array_size_expr(array_size_expr) {} CIndirectionState(const CIndirectionState& src) = default; + + bool current_is_function_type() const { return m_current_is_function_type; } + std::string current_params_string() const { + std::string retval; + if (1 <= m_params_current.size()) { + static const std::string comma_space_str = ", "; + for (auto& param_current : m_params_current) { + retval += param_current + comma_space_str; + } + retval = retval.substr(0, retval.size() - comma_space_str.size()); + retval = "(" + retval + ")"; + } + return retval; + } + std::string m_original; std::string m_current; + std::string m_original_array_size_expr; + bool m_current_is_function_type = false; std::vector<std::string> m_params_original; std::vector<std::string> m_params_current; @@ -312,19 +334,24 @@ class CIndirectionStateStack : public std::vector<CIndirectionState> {}; * can, of course, function as arrays, but context is required to identify those situations. Such identification * is not done in this function. It is done elsewhere. */ clang::QualType populateQTypeIndirectionStack(CIndirectionStateStack& stack, clang::QualType qtype, int depth = 0) { - bool current_is_function_type = false; - std::vector<const clang::DeclaratorDecl*> current_function_params; - if(qtype->isFunctionType()) { - auto type_class = qtype->getTypeClass(); + auto l_qtype = qtype; + bool is_function_type = false; + std::vector<std::string> param_strings; + if(l_qtype->isFunctionType()) { + auto type_class = l_qtype->getTypeClass(); if (clang::Type::Decayed == type_class) { int q = 5; } else if (clang::Type::FunctionNoProto == type_class) { int q = 5; } else if (clang::Type::FunctionProto == type_class) { - if (llvm::isa<const clang::FunctionProtoType>(qtype)) { - auto FNQT = llvm::cast<const clang::FunctionProtoType>(qtype); + if (llvm::isa<const clang::FunctionProtoType>(l_qtype)) { + auto FNQT = llvm::cast<const clang::FunctionProtoType>(l_qtype); if (FNQT) { auto num_params = FNQT->getNumParams(); + auto param_types = FNQT->param_types(); + for (auto& param_type : param_types) { + param_strings.push_back(param_type.getAsString()); + } } else { assert(false); } @@ -334,52 +361,104 @@ clang::QualType populateQTypeIndirectionStack(CIndirectionStateStack& stack, cla int q = 5; } - if (llvm::isa<const clang::FunctionType>(qtype)) { - auto FNQT = llvm::cast<const clang::FunctionType>(qtype); + if (clang::Type::Paren == type_class) { + if (llvm::isa<const clang::ParenType>(l_qtype)) { + auto PNQT = llvm::cast<const clang::ParenType>(l_qtype); + if (PNQT) { + return populateQTypeIndirectionStack(stack, PNQT->getInnerType(), depth+1); + } else { + assert(false); + } + } else { + int q = 7; + } + } else if (llvm::isa<const clang::FunctionType>(l_qtype)) { + auto FNQT = llvm::cast<const clang::FunctionType>(l_qtype); if (FNQT) { - current_is_function_type = true; - qtype = FNQT->getReturnType(); + is_function_type = true; + l_qtype = FNQT->getReturnType(); } else { assert(false); } - } else { - int q = 5; } } - std::string qtype_str = qtype.getAsString(); - auto TP = qtype.getTypePtr(); + std::string l_qtype_str = l_qtype.getAsString(); + auto TP = l_qtype.getTypePtr(); if (TP->isArrayType()) { - auto type_class = qtype->getTypeClass(); + auto type_class = l_qtype->getTypeClass(); if (clang::Type::Decayed == type_class) { int q = 5; } else if (clang::Type::ConstantArray == type_class) { int q = 5; } + std::string size_text; + if (llvm::isa<const clang::VariableArrayType>(TP)) { + auto VATP = llvm::cast<const clang::VariableArrayType>(TP); + if (!VATP) { + assert(false); + } else { + auto size_expr = VATP->getSizeExpr(); + //auto SR = nice_source_range(size_expr->getSourceRange(), Rewrite); + //size_text = Rewrite.getRewrittenText(SR); + } + } else if (llvm::isa<const clang::ConstantArrayType>(TP)) { + auto CATP = llvm::cast<const clang::ConstantArrayType>(TP); + if (!CATP) { + assert(false); + } else { + auto array_size = CATP->getSize(); + size_text = array_size.toString(10, false);/*check this*/ + + if (false) { + /* + auto DDSR = nice_source_range(DD->getSourceRange(), Rewrite); + std::string array_size_expression_text; + std::string source_text; + if (DDSR.isValid()) { + source_text = Rewrite.getRewrittenText(DDSR); + + auto left_bracket_pos = source_text.find('['); + auto right_bracket_pos = source_text.find(']'); + if ((std::string::npos != left_bracket_pos) && (std::string::npos != right_bracket_pos) + && (left_bracket_pos + 1 < right_bracket_pos)) { + auto array_size_expression_text = source_text.substr(left_bracket_pos + 1, right_bracket_pos - (left_bracket_pos + 1)); + int q = 3; + } else { + int q = 7; + } + } else { + int q = 5; + } + */ + } + } + } + const clang::ArrayType* ATP = TP->getAsArrayTypeUnsafe(); if (ATP) { clang::QualType QT = ATP->getElementType(); - auto l_TP = QT.getTypePtr(); auto l_type_str = QT.getAsString(); - stack.push_back(CIndirectionState("native array", "native array")); + stack.push_back(CIndirectionState("native array", "native array", size_text)); return populateQTypeIndirectionStack(stack, QT, depth+1); } else { assert(false); } - } else if (qtype->isPointerType()) { - auto type_class = qtype->getTypeClass(); + + } else if (l_qtype->isPointerType()) { + auto type_class = l_qtype->getTypeClass(); if (clang::Type::Decayed == type_class) { int q = 5; } else if (clang::Type::Pointer == type_class) { int q = 5; } - if (llvm::isa<const clang::PointerType>(qtype)) { - auto PQT = llvm::cast<const clang::PointerType>(qtype); + if (llvm::isa<const clang::PointerType>(l_qtype)) { + auto PQT = llvm::cast<const clang::PointerType>(l_qtype); if (PQT) { int q = 5; } else { @@ -389,14 +468,19 @@ clang::QualType populateQTypeIndirectionStack(CIndirectionStateStack& stack, cla int q = 5; } - clang::QualType QT = qtype->getPointeeType(); + clang::QualType QT = l_qtype->getPointeeType(); auto l_type_str = QT.getAsString(); - stack.push_back(CIndirectionState("native pointer", "native pointer")); + stack.push_back(CIndirectionState("native pointer", "native pointer", is_function_type, param_strings)); return populateQTypeIndirectionStack(stack, QT, depth+1); } - return qtype; + + if (is_function_type) { + return qtype; + } else { + return l_qtype; + } } /* Given an expression (in the form of a clang::Stmt) and an (empty) (string) stack, @@ -440,7 +524,7 @@ const clang::Expr* populateStmtIndirectionStack(std::vector<std::string>& stack, auto cast_kind_name = ICE->getCastKindName(); auto cast_kind = ICE->getCastKind(); if ((clang::CK_FunctionToPointerDecay == cast_kind)) { - process_child_flag = false; + process_child_flag = true; } else { if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { process_child_flag = true; @@ -456,7 +540,7 @@ const clang::Expr* populateStmtIndirectionStack(std::vector<std::string>& stack, auto cast_kind = CSCE->getCastKind(); auto qtype = CSCE->getType(); if ((clang::CK_FunctionToPointerDecay == cast_kind)) { - process_child_flag = false; + process_child_flag = true; } else { if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { process_child_flag = true; @@ -509,6 +593,29 @@ const clang::Expr* populateStmtIndirectionStack(std::vector<std::string>& stack, return retval; } +const clang::Stmt* find_stmt(const clang::Stmt::StmtClass& target_stmt_class, const clang::Stmt& stmt, int depth = 0) { + const clang::Stmt* ST = &stmt; + const auto stmt_class = ST->getStmtClass(); + const auto stmt_class_name = ST->getStmtClassName(); + if (stmt_class == target_stmt_class) { + return ST; + } + bool process_children_flag = true; + if (process_children_flag) { + for (auto child_iter = ST->child_begin(); child_iter != ST->child_end(); child_iter++) { + if (nullptr != (*child_iter)) { + auto res1 = find_stmt(target_stmt_class, *(*child_iter), depth+1); + if (res1) { + return res1; + } + } else { + assert(false); + } + } + } + return nullptr; +} + void walkTheAST1(const clang::Stmt& stmt, int depth = 0) { const clang::Stmt* ST = &stmt; auto stmt_class = ST->getStmtClass(); @@ -599,9 +706,18 @@ public: m_is_a_function = true; } m_original_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); - m_current_direct_qtype = m_original_direct_qtype; + set_current_direct_qtype(m_original_direct_qtype); //std::reverse(m_indirection_state_stack.begin(), m_indirection_state_stack.end()); } + void set_current_direct_qtype(clang::QualType& new_direct_qtype) { + m_current_direct_qtype = new_direct_qtype; + m_current_direct_qtype_is_current = true; + m_current_direct_qtype_str = m_current_direct_qtype.getAsString(); + } + void set_current_direct_qtype_str(const std::string& str) { + m_current_direct_qtype_is_current = false; + m_current_direct_qtype_str = str; + } bool is_an_indirect_type(size_t indirection_level = 0) const { return (m_indirection_state_stack.size() > indirection_level); } bool has_been_determined_to_be_an_array(size_t indirection_level = 0) const { bool retval = false; @@ -628,7 +744,10 @@ public: const DeclaratorDecl* m_ddecl_cptr = nullptr; CIndirectionStateStack m_indirection_state_stack; clang::QualType m_original_direct_qtype; + bool m_current_direct_qtype_is_current = false; clang::QualType m_current_direct_qtype; + std::string m_current_direct_qtype_str; + std::string m_initializer_info_str; bool m_original_initialization_has_been_noted = false; std::string m_original_initialization_expr_str; @@ -661,7 +780,7 @@ bool is_an_indirect_type(const clang::DeclaratorDecl& ddecl) { bool is_an_indirect_type(const QualType& QT, size_t indirection_level = 0) { CIndirectionStateStack m_indirection_state_stack; - auto m_current_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); + auto direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); return (indirection_level < m_indirection_state_stack.size()); } @@ -767,6 +886,13 @@ public: Rewriter &Rewrite; }; +template<class X, class... Args> +std::shared_ptr<X> make_expr_conversion_state_shared_ptr(Args&&... args) { + std::shared_ptr<X> retval = std::make_shared<X>(std::forward<Args>(args)...); + retval->set_childrens_parent_shptr(retval); + return retval; +} + class CConditionalOperatorExprConversionState : public CExprConversionState { public: CConditionalOperatorExprConversionState(const clang::ConditionalOperator& co_cref, Rewriter &Rewrite) : CExprConversionState(co_cref, Rewrite) { @@ -868,13 +994,6 @@ private: const clang::ArraySubscriptExpr* m_arraysubscriptexpr_cptr = nullptr; }; -template<class X, class... Args> -std::shared_ptr<X> make_expr_conversion_state_shared_ptr(Args&&... args) { - std::shared_ptr<X> retval = std::make_shared<X>(std::forward<Args>(args)...); - retval->set_childrens_parent_shptr(retval); - return retval; -} - class CExprConversionStateMap : public std::map<const clang::Expr*, std::shared_ptr<CExprConversionState>> { public: typedef std::map<const clang::Expr*, std::shared_ptr<CExprConversionState>> base_class; @@ -938,6 +1057,37 @@ public: CDDeclIndirection m_ddecl_indirection; }; +class CExprTextReplacementAction : public CDDecl2ReplacementAction { +public: + CExprTextReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const Expr* EX, const std::string& replacement_code) : + CDDecl2ReplacementAction(Rewrite, MR, ddecl_indirection), m_EX(EX), m_replacement_code(replacement_code) {} + virtual ~CExprTextReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + /* + { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + const Expr* EX = m_EX; + + if (EX != nullptr) + { + auto EXSR = nice_source_range(EX->getSourceRange(), Rewrite); + + if (ConvertToSCPP && (EXSR.isValid())) { + auto res2 = Rewrite.ReplaceText(EXSR, m_replacement_code); + } else { + int q = 7; + } + } + } + */ + + const Expr* m_EX = nullptr; + std::string m_replacement_code; +}; + class CArray2ReplacementAction : public CDDecl2ReplacementAction { public: using CDDecl2ReplacementAction::CDDecl2ReplacementAction; @@ -1027,6 +1177,19 @@ public: const clang::ArraySubscriptExpr* m_arraysubscriptexpr_cptr = nullptr; }; +class CUpdateIndirectFunctionTypeParamsArray2ReplacementAction : public CArray2ReplacementAction { +public: + CUpdateIndirectFunctionTypeParamsArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const DeclaratorDecl& indirect_function_ddecl, const clang::CallExpr& call_expr) : + CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_indirect_function_DD(&indirect_function_ddecl), m_CE(&call_expr) {} + virtual ~CUpdateIndirectFunctionTypeParamsArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const clang::DeclaratorDecl *m_indirect_function_DD = nullptr; + const clang::CallExpr* m_CE = nullptr; +}; + class CDDecl2ReplacementActionMap : public std::multimap<CDDeclIndirection, std::shared_ptr<CDDecl2ReplacementAction>> { public: typedef std::multimap<CDDeclIndirection, std::shared_ptr<CDDecl2ReplacementAction>> base_class; @@ -1074,13 +1237,13 @@ public: std::string m_bo_replacement_code; }; -class CMallocInitializerArray2ReplacementAction : public CDynamicArray2ReplacementAction { +class CInitializerArray2ReplacementAction : public CDynamicArray2ReplacementAction { public: - CMallocInitializerArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + CInitializerArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, const DeclStmt* DS, const std::string& initializer_info_str) : CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_DS(DS), m_DD(ddecl_indirection.m_ddecl_cptr), m_initializer_info_str(initializer_info_str) {} - virtual ~CMallocInitializerArray2ReplacementAction() {} + virtual ~CInitializerArray2ReplacementAction() {} virtual void do_replacement(CState1& state1) const; @@ -1107,21 +1270,16 @@ public: std::string m_ce_replacement_code; }; -class CSetArrayPointerToNull2ReplacementAction : public CDynamicArray2ReplacementAction { +class CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction : public CDynamicArray2ReplacementAction { public: - CSetArrayPointerToNull2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, - const BinaryOperator* BO, const std::string& bo_replacement_code) : - CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_BO(BO), m_DD(ddecl_indirection.m_ddecl_cptr), - m_bo_replacement_code(bo_replacement_code) {} - virtual ~CSetArrayPointerToNull2ReplacementAction() {} + CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const CDDeclIndirection& ddecl_indirection2) : + CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_ddecl_indirection2(ddecl_indirection2) {} + virtual ~CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction() {} virtual void do_replacement(CState1& state1) const; - const BinaryOperator* m_BO = nullptr; - //const DeclRefExpr* m_DRE = nullptr; - //const MemberExpr* m_ME = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_bo_replacement_code; + const CDDeclIndirection m_ddecl_indirection2; }; /* This class represents and "enforces" the constraint that the lhs and rhs @@ -1150,9 +1308,11 @@ public: class CArray2ReplacementActionMap : public CDDecl2ReplacementActionMap { public: + /* iterator insert( const std::shared_ptr<CArray2ReplacementAction>& cr_shptr ) { return CDDecl2ReplacementActionMap::insert(static_cast<std::shared_ptr<CDDecl2ReplacementAction> >(cr_shptr)); } + */ }; class CState1 { @@ -1174,6 +1334,133 @@ public: CExprConversionStateMap m_expr_conversion_state_map; }; +class CTypeIndirectionPrefixAndSuffixItem { +public: + std::string m_prefix_str; + std::string m_suffix_str; + std::string m_action_species; + bool m_direct_type_must_be_non_const = false; +}; + +static CTypeIndirectionPrefixAndSuffixItem generate_type_indirection_prefix_and_suffix(CIndirectionStateStack& indirection_state_stack, + bool direct_type_is_char_type, bool direct_type_is_function_type, bool is_a_function_parameter) { + CTypeIndirectionPrefixAndSuffixItem retval; + + bool changed_from_original = false; + std::string replacement_code; + std::string prefix_str; + std::string suffix_str; + + if (true) { + for (size_t i = 0; i < indirection_state_stack.size(); i += 1) { + bool is_char_star = false; + bool is_function_pointer = false; + bool is_last_indirection = (indirection_state_stack.size() == (i+1)); + if (is_last_indirection && (direct_type_is_char_type)) { + is_char_star = true; + } else if (is_last_indirection && direct_type_is_function_type) { + is_function_pointer = true; + } else if ((!is_last_indirection) && indirection_state_stack[i+1].current_is_function_type()) { + is_function_pointer = true; + } + + if (indirection_state_stack[i].current_is_function_type()) { + //suffix_str = indirection_state_stack[i].current_params_string() + suffix_str; + } + + if ("inferred array" == indirection_state_stack[i].m_current) { + if (is_char_star) { + /* We're assuming this is a null terminated string. We'll just leave it as a + * char* for now. At some point we'll replace it with an mse::string or whatever. */ + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "char*"; + } else { + if (is_last_indirection) { + //retval.m_direct_type_must_be_non_const = true; + } + prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; + suffix_str = "> " + suffix_str; + retval.m_action_species = "native pointer to TNullableAnyRandomAccessIterator"; + } + } else if ("dynamic array" == indirection_state_stack[i].m_current) { + if (is_char_star) { + /* We're assuming this is a null terminated string. We'll just leave it as a + * char* for now. At some point we'll replace it with an mse::string or whatever. */ + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "char*"; + } else { + if (is_last_indirection) { + retval.m_direct_type_must_be_non_const = true; + } + prefix_str = prefix_str + "mse::lh::TIPointerWithBundledVector<"; + if (is_a_function_parameter) { + suffix_str = "> " + suffix_str; + retval.m_action_species = "native pointer parameter to TIPointerWithBundledVector"; + } else { + suffix_str = "> " + suffix_str; + retval.m_action_species = "native pointer to TIPointerWithBundledVector"; + } + } + } else if ("native array" == indirection_state_stack[i].m_current) { + std::string size_text = indirection_state_stack[i].m_original_array_size_expr; + + if (is_char_star) { + /* We're assuming this is a null terminated string. We'll just leave it as a + * char[] for now. At some point we'll replace it with an mse::string or whatever. */ + //prefix_str = prefix_str + ""; + suffix_str = "[" + size_text + "]" + suffix_str; + } else { + if (is_a_function_parameter) { + prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; + suffix_str = ", " + size_text + "> " + suffix_str; + retval.m_action_species = "native array parameter to TNullableAnyRandomAccessIterator"; + } else { + if (is_last_indirection) { + retval.m_direct_type_must_be_non_const = true; + } + prefix_str = prefix_str + "mse::lh::TNativeArrayReplacement<"; + suffix_str = ", " + size_text + "> " + suffix_str; + retval.m_action_species = "native array to TNativeArrayReplacement"; + } + } + } else if ("native pointer" == indirection_state_stack[i].m_current) { + if (is_char_star) { + /* We're assuming this is a null terminated string. We'll just leave it as a + * char* for now. At some point we'll replace it with an mse::string or whatever. */ + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "char*"; + } else if (is_function_pointer) { + prefix_str = prefix_str + "std::function<"; + suffix_str = "> " + suffix_str; + retval.m_action_species = "function pointer to std::function"; + } else { + if (false/*for now*/) { + prefix_str = prefix_str + "mse::TAnyPointer<"; + suffix_str = "> " + suffix_str; + retval.m_action_species = "native pointer to TAnyPointer"; + } else { + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "native pointer"; + } + } + } else if ("malloc target" == indirection_state_stack[i].m_current) { + /* We'll just leaving it as a native pointer for now. Ultimately, this won't be the case. */ + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "malloc target"; + } + } + } + retval.m_prefix_str = prefix_str; + retval.m_suffix_str = suffix_str; + + return retval; +} + class CDeclarationReplacementCodeItem { public: std::string m_replacement_code; @@ -1209,28 +1496,6 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } } - const clang::Type* TP = QT.getTypePtr(); - auto qtype_str = QT.getAsString(); - auto direct_qtype_str = ddcs_ref.m_current_direct_qtype.getAsString(); - if ("_Bool" == direct_qtype_str) { - direct_qtype_str = "bool"; - } else if ("const _Bool" == direct_qtype_str) { - direct_qtype_str = "const bool"; - } - - auto non_const_direct_qtype = ddcs_ref.m_current_direct_qtype; - non_const_direct_qtype.removeLocalConst(); - auto non_const_direct_qtype_str = non_const_direct_qtype.getAsString(); - if ("_Bool" == non_const_direct_qtype_str) { - non_const_direct_qtype_str = "bool"; - } - - auto direct_TP = ddcs_ref.m_current_direct_qtype.getTypePtr(); - if (!direct_TP) { - return retval; - } - bool direct_type_is_function_type = direct_TP->isFunctionType(); - std::string variable_name = DD->getNameAsString(); std::string identifier_name_str; auto pIdentifier = DD->getIdentifier(); @@ -1239,27 +1504,10 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } if ("" == variable_name) { int q = 7; - } else if ("LODEPNG_VERSION_STRING" == variable_name) { + } else if ("bitlen_ll" == variable_name) { int q = 5; } - if (!(ddcs_ref.m_original_source_text_has_been_noted)) { - ddcs_ref.m_original_source_text_str = Rewrite.getRewrittenText(decl_source_range); - if (FND) { - assert(type_is_function_type); - ddcs_ref.m_is_a_function = true; - for (size_t i = 0; i < FND->getNumParams(); i+=1) { - ddcs_ref.m_original_function_parameter_decl_cptrs.push_back(FND->getParamDecl(i)); - } - auto return_type_source_range = nice_source_range(FND->getReturnTypeSourceRange(), Rewrite); - if (!(return_type_source_range.isValid())) { - return retval; - } - ddcs_ref.m_function_return_type_original_source_text_str = Rewrite.getRewrittenText(return_type_source_range); - } - ddcs_ref.m_original_source_text_has_been_noted = true; - } - clang::StorageClass storage_class = clang::StorageClass::SC_None; bool is_extern = false; clang::StorageDuration storage_duration = clang::StorageDuration::SD_Automatic; @@ -1352,141 +1600,68 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } ddcs_ref.m_original_initialization_has_been_noted = true; + const clang::Type* TP = QT.getTypePtr(); + auto qtype_str = QT.getAsString(); + auto direct_qtype_str = ddcs_ref.m_current_direct_qtype_str; + if ("_Bool" == direct_qtype_str) { + direct_qtype_str = "bool"; + } else if ("const _Bool" == direct_qtype_str) { + direct_qtype_str = "const bool"; + } + + auto non_const_direct_qtype_str = ddcs_ref.m_current_direct_qtype_str; + if (ddcs_ref.m_current_direct_qtype_is_current) { + auto non_const_direct_qtype = ddcs_ref.m_current_direct_qtype; + non_const_direct_qtype.removeLocalConst(); + non_const_direct_qtype_str = non_const_direct_qtype.getAsString(); + } else { + static const std::string const_space_str = "const "; + if (string_begins_with(non_const_direct_qtype_str, const_space_str)) { + non_const_direct_qtype_str = non_const_direct_qtype_str.substr(const_space_str.size()); + } + } + if ("_Bool" == non_const_direct_qtype_str) { + non_const_direct_qtype_str = "bool"; + } + + auto direct_TP = ddcs_ref.m_current_direct_qtype.getTypePtr(); + if (!direct_TP) { + return retval; + } + bool direct_type_is_function_type = direct_TP->isFunctionType(); + + if (!(ddcs_ref.m_original_source_text_has_been_noted)) { + ddcs_ref.m_original_source_text_str = Rewrite.getRewrittenText(decl_source_range); + if (FND) { + assert(type_is_function_type); + ddcs_ref.m_is_a_function = true; + for (size_t i = 0; i < FND->getNumParams(); i+=1) { + ddcs_ref.m_original_function_parameter_decl_cptrs.push_back(FND->getParamDecl(i)); + } + auto return_type_source_range = nice_source_range(FND->getReturnTypeSourceRange(), Rewrite); + if (!(return_type_source_range.isValid())) { + return retval; + } + ddcs_ref.m_function_return_type_original_source_text_str = Rewrite.getRewrittenText(return_type_source_range); + } + ddcs_ref.m_original_source_text_has_been_noted = true; + } + + bool direct_type_is_char_type = (("char" == direct_qtype_str) || ("const char" == direct_qtype_str)); bool changed_from_original = false; std::string replacement_code; std::string prefix_str; std::string suffix_str; - if (true) { - for (size_t i = 0; i < ddcs_ref.m_indirection_state_stack.size(); i += 1) { - bool is_char_star = false; - bool is_function_pointer = false; - bool is_last_indirection = (ddcs_ref.m_indirection_state_stack.size() == (i+1)); - if (is_last_indirection && (("char" == direct_qtype_str) || ("const char" == direct_qtype_str))) { - is_char_star = true; - } else if (is_last_indirection && direct_type_is_function_type) { - is_function_pointer = true; - } - if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (is_char_star) { - /* We're assuming this is a null terminated string. We'll just leave it as a - * char* for now. At some point we'll replace it with an mse::string or whatever. */ - //prefix_str = prefix_str + ""; - suffix_str = "* " + suffix_str; - retval.m_action_species = "char*"; - } else { - direct_qtype_str = non_const_direct_qtype_str; - prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; - suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer to TNullableAnyRandomAccessIterator"; - } - } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - direct_qtype_str = non_const_direct_qtype_str; - if (is_char_star) { - /* We're assuming this is a null terminated string. We'll just leave it as a - * char* for now. At some point we'll replace it with an mse::string or whatever. */ - //prefix_str = prefix_str + ""; - suffix_str = "* " + suffix_str; - retval.m_action_species = "char*"; - } else { - prefix_str = prefix_str + "mse::TIPointerWithBundledVector<"; - if (is_a_function_parameter) { - suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer parameter to TIPointerWithBundledVector"; - } else { - suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer to TIPointerWithBundledVector"; - } - } - } else if ("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - direct_qtype_str = non_const_direct_qtype_str; - std::string size_text; - if (TP->isVariableArrayType()) { - auto VATP = llvm::cast<const clang::VariableArrayType>(TP); - if (!VATP) { - assert(false); - } else { - auto size_expr = VATP->getSizeExpr(); - auto SR = nice_source_range(size_expr->getSourceRange(), Rewrite); - size_text = Rewrite.getRewrittenText(SR); - } - } else if (TP->isConstantArrayType()) { - auto CATP = llvm::cast<const clang::ConstantArrayType>(TP); - if (!CATP) { - assert(false); - } else { - auto array_size = CATP->getSize(); - size_text = array_size.toString(10, false);/*check this*/ - - if (false) { - auto DDSR = nice_source_range(DD->getSourceRange(), Rewrite); - std::string array_size_expression_text; - std::string source_text; - if (DDSR.isValid()) { - source_text = Rewrite.getRewrittenText(DDSR); - - auto left_bracket_pos = source_text.find('['); - auto right_bracket_pos = source_text.find(']'); - if ((std::string::npos != left_bracket_pos) && (std::string::npos != right_bracket_pos) - && (left_bracket_pos + 1 < right_bracket_pos)) { - auto array_size_expression_text = source_text.substr(left_bracket_pos + 1, right_bracket_pos - (left_bracket_pos + 1)); - int q = 3; - } else { - int q = 7; - } - } else { - int q = 5; - } - } - } - } + auto res4 = generate_type_indirection_prefix_and_suffix(ddcs_ref.m_indirection_state_stack, + direct_type_is_char_type, direct_type_is_function_type, is_a_function_parameter); + retval.m_action_species = res4.m_action_species; - if (is_char_star) { - /* We're assuming this is a null terminated string. We'll just leave it as a - * char[] for now. At some point we'll replace it with an mse::string or whatever. */ - //prefix_str = prefix_str + ""; - suffix_str = "[" + size_text + "]" + suffix_str; - } else { - if (is_a_function_parameter) { - prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; - suffix_str = ", " + size_text + "> " + suffix_str; - retval.m_action_species = "native array parameter to TNullableAnyRandomAccessIterator"; - } else { - prefix_str = prefix_str + "mse::TIteratorWithBundledArray<"; - suffix_str = ", " + size_text + "> " + suffix_str; - retval.m_action_species = "native array to TIteratorWithBundledArray"; - } - } - } else if ("native pointer" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (is_char_star) { - /* We're assuming this is a null terminated string. We'll just leave it as a - * char* for now. At some point we'll replace it with an mse::string or whatever. */ - //prefix_str = prefix_str + ""; - suffix_str = "* " + suffix_str; - retval.m_action_species = "char*"; - } else if (is_function_pointer) { - prefix_str = prefix_str + "std::function<"; - suffix_str = "> " + suffix_str; - retval.m_action_species = "function pointer to std::function"; - } else { - if (false/*for now*/) { - prefix_str = prefix_str + "mse::TAnyPointer<"; - suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer to TAnyPointer"; - } else { - //prefix_str = prefix_str + ""; - suffix_str = "* " + suffix_str; - retval.m_action_species = "native pointer"; - } - } - } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[i].m_current) { - /* We'll just leaving it as a native pointer for now. Ultimately, this won't be the case. */ - //prefix_str = prefix_str + ""; - suffix_str = "* " + suffix_str; - retval.m_action_species = "malloc target"; - } - } + if (res4.m_direct_type_must_be_non_const) { + direct_qtype_str = non_const_direct_qtype_str; } + prefix_str = res4.m_prefix_str; + suffix_str = res4.m_suffix_str; bool discard_initializer_option_flag = (std::string::npos != options_str.find("[discard-initializer]")); std::string initializer_append_str; @@ -1512,7 +1687,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con if (FND) { assert(type_is_function_type); if (changed_from_original) { - replacement_code += prefix_str + non_const_direct_qtype_str + suffix_str; + replacement_code += prefix_str + direct_qtype_str + suffix_str; } else { replacement_code = ddcs_ref.m_function_return_type_original_source_text_str; } @@ -1567,6 +1742,10 @@ static void update_declaration(const DeclaratorDecl& ddecl, Rewriter &Rewrite, C if ((TP->isFunctionType()) || (false)) { const clang::FunctionDecl* FND = dynamic_cast<const clang::FunctionDecl*>(DD); if (FND) { + auto name_str = FND->getNameAsString(); + if (std::string::npos != name_str.find("lodepng_chunk_data_const")) { + int q = 5; + } auto return_type_source_range = nice_source_range(FND->getReturnTypeSourceRange(), Rewrite); if (!(return_type_source_range.isValid())) { return; @@ -1626,6 +1805,248 @@ static void update_declaration(const DeclaratorDecl& ddecl, Rewriter &Rewrite, C } } +struct CLeadingAddressofOperatorInfo { + bool leading_addressof_operator_detected = false; + const clang::Expr* without_leading_addressof_operator_expr_cptr = nullptr; + const clang::UnaryOperator* addressof_unary_operator_cptr = nullptr; +}; +CLeadingAddressofOperatorInfo leading_addressof_operator_info_from_stmt(const clang::Stmt& stmt_cref, int depth = 0) { + CLeadingAddressofOperatorInfo retval; + const clang::Stmt* ST = &stmt_cref; + auto stmt_class = ST->getStmtClass(); + auto stmt_class_name = ST->getStmtClassName(); + bool process_child_flag = false; + if (clang::Stmt::StmtClass::UnaryOperatorClass == stmt_class) { + auto UO = llvm::cast<const clang::UnaryOperator>(ST); + if (UO) { + if (clang::UnaryOperatorKind::UO_AddrOf == UO->getOpcode()) { + retval.leading_addressof_operator_detected = true; + retval.addressof_unary_operator_cptr = UO; + + auto child_iter = ST->child_begin(); + if ((child_iter != ST->child_end()) && (llvm::isa<const clang::Expr>(*child_iter))) { + retval.without_leading_addressof_operator_expr_cptr = + llvm::cast<const clang::Expr>(*child_iter); + } else { + assert(false); + } + } + } else { + assert(false); + } + } else if ((clang::Stmt::StmtClass::ImplicitCastExprClass == stmt_class)) { + auto ICE = llvm::cast<const clang::ImplicitCastExpr>(ST); + if (ICE) { + auto cast_kind_name = ICE->getCastKindName(); + auto cast_kind = ICE->getCastKind(); + if ((clang::CK_FunctionToPointerDecay == cast_kind)) { + process_child_flag = false; + } else { + if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { + process_child_flag = true; + } else { + process_child_flag = true; + } + } + } else { assert(false); } + } else if ((clang::Stmt::StmtClass::CStyleCastExprClass == stmt_class)) { + auto CSCE = llvm::cast<const clang::CStyleCastExpr>(ST); + if (CSCE) { + auto cast_kind_name = CSCE->getCastKindName(); + auto cast_kind = CSCE->getCastKind(); + auto qtype = CSCE->getType(); + if ((clang::CK_FunctionToPointerDecay == cast_kind)) { + process_child_flag = false; + } else { + if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { + process_child_flag = true; + } else { + process_child_flag = true; + } + } + } else { assert(false); } + } else if ((clang::Stmt::StmtClass::ParenExprClass == stmt_class)) { + process_child_flag = true; + } else if ((clang::Stmt::StmtClass::CallExprClass == stmt_class)) { + process_child_flag = true; + } else if(clang::Stmt::StmtClass::DeclRefExprClass == stmt_class) { + auto DRE = llvm::cast<const clang::DeclRefExpr>(ST); + if (DRE) { + //retval = DRE; + //process_child_flag = true; + } else { + assert(false); + } + } else if(clang::Stmt::StmtClass::MemberExprClass == stmt_class) { + auto ME = llvm::cast<const clang::MemberExpr>(ST); + if (ME) { + //retval = ME; + } else { + assert(false); + } + } else { + if (0 == depth) { + int q = 5; + } + int q = 5; + } + if (process_child_flag) { + auto child_iter = ST->child_begin(); + if (child_iter != ST->child_end()) { + if (nullptr != (*child_iter)) { + retval = leading_addressof_operator_info_from_stmt(*(*child_iter), depth+1); + } else { + assert(false); + } + } else { + int q = 5; + } + } + return retval; +} + +struct CArrayInferenceInfo { + bool is_an_indirect_type() const { + if (nullptr != ddecl_conversion_state_ptr) { + return (1 <= ddecl_conversion_state_ptr->m_indirection_state_stack.size()); + } else { + return false; + } + } + bool update_declaration_flag = false; + bool has_just_been_determined_to_be_an_array_flag = false; + size_t has_just_been_determined_to_be_an_array_indirection_level = 0; + size_t indirection_level = 0; + const DeclaratorDecl* ddecl_cptr = nullptr; + CDDeclConversionState* ddecl_conversion_state_ptr = nullptr; + const clang::Expr* declaration_expr_cptr = nullptr; +}; +CArrayInferenceInfo infer_array_type_info_from_stmt_indirection_stack(CDDeclConversionState& ddcs_ref, + const std::vector<std::string>& stmt_indirection_stack, CState1& state1_ref) { + CArrayInferenceInfo retval; + auto DD = ddcs_ref.m_ddecl_cptr; + if (!DD) { assert(false); return retval; } + for (size_t i = 0; ((i < ddcs_ref.m_indirection_state_stack.size()) + && (i < stmt_indirection_stack.size())); i += 1) { + if (("" == stmt_indirection_stack[i])) { + /* We're using the empty string as a generic state for the "terminal level of indirection" + * when we don't want to bother specifying a specific state. */ + retval.indirection_level = i; + } else if ("native pointer" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; + retval.update_declaration_flag = true; + state1_ref.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); + } else if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "malloc target"; + retval.indirection_level = i; + } else if (("set to null" == stmt_indirection_stack[i]) || + ("memset/cpy target" == stmt_indirection_stack[i])) { + retval.indirection_level = i; + } + } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + retval.update_declaration_flag = true; + state1_ref.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); + state1_ref.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); + } + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("malloc target" == stmt_indirection_stack[i]) || + ("set to null" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + retval.update_declaration_flag = true; + retval.has_just_been_determined_to_be_an_array_flag = true; + retval.indirection_level = i; + state1_ref.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); + } else if (("memset/cpy target" == stmt_indirection_stack[i])) { + retval.has_just_been_determined_to_be_an_array_flag = true; + retval.indirection_level = i; + } + } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("malloc target" == stmt_indirection_stack[i]) || + ("set to null" == stmt_indirection_stack[i])) { + retval.has_just_been_determined_to_be_an_array_flag = true; + retval.indirection_level = i; + } + } + /* We've changed it here so that retval.indirection_level will always end up being + * (stmt_indirection_stack.size() - 1) when (1 <= stmt_indirection_stack.size()). This + * renders the above "retval.indirection_level = i;" statements redundant, but we'll + * leave them there for now in case we need them again. */ + retval.indirection_level = i; + } + return retval; +} + +/* We are trying to determine, for each and every pointer, whether or not it is being used as an + * array iterator. So this function takes an expression using a declared (pointer) variable + * and notes when the (pointer) variable, or any dereference of the + * (pointer) variable, is being used as an array iterator. So for example, given a declaration, + * say, "int*** ptr1;" and an expression, say, "(*(ptr1[3]))[5]", it will note the two levels + * of dereference/"indirection" that are being used as array iterators/pointers. Upon determining + * that a pointer (or a dereference/indirection of the pointer) is being used as an array iterator, + * the function will execute any queued up actions that were contingent on such a determination. */ +CArrayInferenceInfo infer_array_type_info_from_stmt(const clang::Stmt& stmt_cref, const std::string& stmt_array_info_str, + CState1& state1_ref, const DeclaratorDecl* DD = nullptr) { + CArrayInferenceInfo retval; + + std::vector<std::string> stmt_indirection_stack; + const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, stmt_cref); + std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); + stmt_indirection_stack.push_back(stmt_array_info_str); + if (expr2) { + const DeclaratorDecl* l_DD = DD; + std::string expr2_stmt_class_name; + expr2_stmt_class_name = expr2->getStmtClassName(); + const DeclaratorDecl* expr2_DD = nullptr; + if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { + auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); + if (expr2_DRE) { + auto expr2_decl = expr2_DRE->getDecl(); + expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); + } else { assert(false); } + } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { + auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); + if (expr2_ME) { + auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); + if (expr2_FD) { + expr2_DD = expr2_FD; + } else { assert(false); } + } else { assert(false); } + } + if (expr2_DD) { + auto expr2_QT = expr2_DD->getType(); + auto expr2_type_str = expr2_QT.getAsString(); + std::string expr2_variable_name = expr2_DD->getNameAsString(); + + if (nullptr == l_DD) { + l_DD = expr2_DD; + } + auto res1 = state1_ref.m_ddecl_conversion_state_map.insert(*l_DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; + + auto QT = (*l_DD).getType(); + std::string variable_name = (*l_DD).getNameAsString(); + + if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { + retval = infer_array_type_info_from_stmt_indirection_stack(ddcs_ref, stmt_indirection_stack, state1_ref); + } + + retval.update_declaration_flag |= update_declaration_flag; + retval.ddecl_conversion_state_ptr = &ddcs_ref; + } + retval.ddecl_cptr = expr2_DD; + } + retval.declaration_expr_cptr = expr2; + + return retval; +} + void CMallocArray2ReplacementAction::do_replacement(CState1& state1) const { Rewriter &Rewrite = m_Rewrite; const MatchFinder::MatchResult &MR = m_MR; @@ -1644,6 +2065,31 @@ void CMallocArray2ReplacementAction::do_replacement(CState1& state1) const { return; } + if (ddecl_indirection_cref().m_ddecl_cptr) { + auto res1 = state1.m_ddecl_conversion_state_map.insert(*(ddecl_indirection_cref().m_ddecl_cptr)); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; + + if (ddcs_ref.m_indirection_state_stack.size() >= ddecl_indirection_cref().m_indirection_level) { + if ("inferred array" == ddcs_ref.m_indirection_state_stack[ddecl_indirection_cref().m_indirection_level].m_current) { + ddcs_ref.m_indirection_state_stack[ddecl_indirection_cref().m_indirection_level].m_current = "dynamic array"; + update_declaration_flag |= true; + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, ddecl_indirection_cref()); + } else { + int q = 5; + } + } else { + int q = 7; + } + + if (update_declaration_flag) { + //update_declaration(*(ddecl_indirection_cref().m_ddecl_cptr), Rewrite, state1); + } + } else { + int q = 7; + } + if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { update_declaration(*DD, Rewrite, state1); @@ -1659,7 +2105,7 @@ void CMallocArray2ReplacementAction::do_replacement(CState1& state1) const { } } -void CMallocInitializerArray2ReplacementAction::do_replacement(CState1& state1) const { +void CInitializerArray2ReplacementAction::do_replacement(CState1& state1) const { Rewriter &Rewrite = m_Rewrite; const MatchFinder::MatchResult &MR = m_MR; const DeclStmt* DS = m_DS; @@ -1680,7 +2126,7 @@ void CMallocInitializerArray2ReplacementAction::do_replacement(CState1& state1) auto ddcs_map_iter = res1.first; auto& ddcs_ref = (*ddcs_map_iter).second; - std::string current_direct_qtype_str = ddcs_ref.m_current_direct_qtype.getAsString(); + std::string current_direct_qtype_str = ddcs_ref.m_current_direct_qtype_str; std::string initializer_info_str = m_initializer_info_str; static const std::string void_str = "void"; auto void_pos = initializer_info_str.find(void_str); @@ -1736,33 +2182,28 @@ void CFreeDynamicArray2ReplacementAction::do_replacement(CState1& state1) const } } -void CSetArrayPointerToNull2ReplacementAction::do_replacement(CState1& state1) const { +void CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction::do_replacement(CState1& state1) const { Rewriter &Rewrite = m_Rewrite; const MatchFinder::MatchResult &MR = m_MR; - const BinaryOperator* BO = m_BO; - const DeclaratorDecl* DD = m_DD; - - if ((BO != nullptr) && (DD != nullptr)) - { - auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } - - if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { - update_declaration(*DD, Rewrite, state1); + auto res1 = state1.m_ddecl_conversion_state_map.insert(*(m_ddecl_indirection2.m_ddecl_cptr)); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; - auto res2 = Rewrite.ReplaceText(BOSR, m_bo_replacement_code); - int q = 3; - } else { - int q = 7; + if (ddcs_ref.m_indirection_state_stack.size() >= m_ddecl_indirection2.m_indirection_level) { + if (true) { + ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current = "dynamic array"; + update_declaration_flag |= true; + //state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); } + } else { + int q = 7; + } + + if (update_declaration_flag) { + update_declaration(*(m_ddecl_indirection2.m_ddecl_cptr), Rewrite, state1); } } @@ -2024,6 +2465,32 @@ void CSameTypeArray2ReplacementAction::do_replacement(CState1& state1) const { } } +void CExprTextReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + + const Expr* EX = m_EX; + if (EX) { + auto EXSR = nice_source_range(EX->getSourceRange(), (*this).m_Rewrite); + if (EXSR.isValid()) { + auto excs_iter = state1.m_expr_conversion_state_map.find(EX); + if (state1.m_expr_conversion_state_map.end() == excs_iter) { + std::shared_ptr<CExprConversionState> shptr1 = make_expr_conversion_state_shared_ptr<CExprConversionState>(*EX, m_Rewrite); + excs_iter = state1.m_expr_conversion_state_map.insert(shptr1); + } + auto& excs_shptr_ref = (*excs_iter).second; + + if (ConvertToSCPP) { + std::shared_ptr<CExprTextModifier> shptr1 = std::make_shared<CStraightReplacementExprTextModifier>((*this).m_replacement_code); + (*excs_shptr_ref).m_expr_text_modifier_stack.push_back(shptr1); + (*excs_shptr_ref).update_current_text(); + + (*this).m_Rewrite.ReplaceText(EXSR, (*excs_shptr_ref).m_current_text_str); + } + } + } +} + void CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementAction::do_replacement(CState1& state1) const { Rewriter &Rewrite = m_Rewrite; const MatchFinder::MatchResult &MR = m_MR; @@ -2065,6 +2532,86 @@ void CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementActi } } +void CUpdateIndirectFunctionTypeParamsArray2ReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + + const clang::CallExpr* CE = m_CE; + if (CE) { + auto res1 = state1.m_ddecl_conversion_state_map.insert(*((*this).m_indirect_function_DD)); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + ddcs_ref.m_current_direct_qtype; + + if (llvm::isa<const clang::FunctionType>(ddcs_ref.m_current_direct_qtype)) { + auto FNQT = llvm::cast<const clang::FunctionType>(ddcs_ref.m_current_direct_qtype); + std::string new_function_type_code = FNQT->getReturnType().getAsString(); + new_function_type_code += "("; + + for (size_t i = 0; (i < CE->getNumArgs()); i += 1) { + if (1 <= i) { + new_function_type_code += ", "; + } + + auto arg = CE->getArg(i); + auto rhs_res2 = infer_array_type_info_from_stmt(*arg, "", state1); + bool rhs_is_an_indirect_type = is_an_indirect_type(arg->getType()); + if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { + update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, state1); + } + + if (rhs_res2.ddecl_cptr && rhs_res2.ddecl_conversion_state_ptr) { + CIndirectionStateStack indirection_state_stack; + for (size_t i = rhs_res2.indirection_level; (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size() > i; i += 1) { + indirection_state_stack.push_back((*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack[i]); + } + auto rhs_direct_qtype = (*(rhs_res2.ddecl_conversion_state_ptr)).m_current_direct_qtype; + + bool rhs_direct_type_is_function_type = rhs_direct_qtype->isFunctionType(); + bool rhs_is_a_function_parameter = true; + + std::string rhs_direct_qtype_str = rhs_direct_qtype.getAsString(); + if ("_Bool" == rhs_direct_qtype_str) { + rhs_direct_qtype_str = "bool"; + } else if ("const _Bool" == rhs_direct_qtype_str) { + rhs_direct_qtype_str = "const bool"; + } + bool rhs_direct_type_is_char_type = (("char" == rhs_direct_qtype_str) || ("const char" == rhs_direct_qtype_str)); + auto rhs_non_const_direct_qtype = rhs_direct_qtype; + rhs_non_const_direct_qtype.removeLocalConst(); + std::string rhs_non_const_direct_qtype_str = rhs_non_const_direct_qtype.getAsString(); + if ("_Bool" == rhs_non_const_direct_qtype_str) { + rhs_non_const_direct_qtype_str = "bool"; + } + + auto res3 = generate_type_indirection_prefix_and_suffix(indirection_state_stack, rhs_direct_type_is_char_type, + rhs_direct_type_is_function_type, rhs_is_a_function_parameter); + + if (res3.m_direct_type_must_be_non_const) { + rhs_direct_qtype_str = rhs_non_const_direct_qtype_str; + } + + std::string new_param_type_str = res3.m_prefix_str + rhs_direct_qtype_str + res3.m_suffix_str; + + new_function_type_code += new_param_type_str; + } else { + new_function_type_code += arg->getType().getAsString(); + int q = 7; + } + } + new_function_type_code += ")"; + + ddcs_ref.set_current_direct_qtype_str(new_function_type_code); + + update_declaration(*((*this).m_indirect_function_DD), (*this).m_Rewrite, state1); + } else { + int q = 7; + } + } else { + int q = 7; + } +} + void CConditionalOperatorReconciliation2ReplacementAction::do_replacement(CState1& state1) const { const clang::ConditionalOperator* CO = m_CO; const Expr* COND = nullptr; @@ -2225,242 +2772,6 @@ void CConditionalOperatorReconciliation2ReplacementAction::do_replacement(CState } -struct CLeadingAddressofOperatorInfo { - bool leading_addressof_operator_detected = false; - const clang::Expr* without_leading_addressof_operator_expr_cptr = nullptr; - const clang::UnaryOperator* addressof_unary_operator_cptr = nullptr; -}; -CLeadingAddressofOperatorInfo leading_addressof_operator_info_from_stmt(const clang::Stmt& stmt_cref, int depth = 0) { - CLeadingAddressofOperatorInfo retval; - const clang::Stmt* ST = &stmt_cref; - auto stmt_class = ST->getStmtClass(); - auto stmt_class_name = ST->getStmtClassName(); - bool process_child_flag = false; - if (clang::Stmt::StmtClass::UnaryOperatorClass == stmt_class) { - auto UO = llvm::cast<const clang::UnaryOperator>(ST); - if (UO) { - if (clang::UnaryOperatorKind::UO_AddrOf == UO->getOpcode()) { - retval.leading_addressof_operator_detected = true; - retval.addressof_unary_operator_cptr = UO; - - auto child_iter = ST->child_begin(); - if (child_iter != ST->child_end()) { - retval.without_leading_addressof_operator_expr_cptr = - llvm::cast<const clang::Expr>(*child_iter); - } else { - assert(false); - } - } - } else { - assert(false); - } - } else if ((clang::Stmt::StmtClass::ImplicitCastExprClass == stmt_class)) { - auto ICE = llvm::cast<const clang::ImplicitCastExpr>(ST); - if (ICE) { - auto cast_kind_name = ICE->getCastKindName(); - auto cast_kind = ICE->getCastKind(); - if ((clang::CK_FunctionToPointerDecay == cast_kind)) { - process_child_flag = false; - } else { - if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { - process_child_flag = true; - } else { - process_child_flag = true; - } - } - } else { assert(false); } - } else if ((clang::Stmt::StmtClass::CStyleCastExprClass == stmt_class)) { - auto CSCE = llvm::cast<const clang::CStyleCastExpr>(ST); - if (CSCE) { - auto cast_kind_name = CSCE->getCastKindName(); - auto cast_kind = CSCE->getCastKind(); - auto qtype = CSCE->getType(); - if ((clang::CK_FunctionToPointerDecay == cast_kind)) { - process_child_flag = false; - } else { - if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { - process_child_flag = true; - } else { - process_child_flag = true; - } - } - } else { assert(false); } - } else if ((clang::Stmt::StmtClass::ParenExprClass == stmt_class)) { - process_child_flag = true; - } else if ((clang::Stmt::StmtClass::CallExprClass == stmt_class)) { - process_child_flag = true; - } else if(clang::Stmt::StmtClass::DeclRefExprClass == stmt_class) { - auto DRE = llvm::cast<const clang::DeclRefExpr>(ST); - if (DRE) { - //retval = DRE; - //process_child_flag = true; - } else { - assert(false); - } - } else if(clang::Stmt::StmtClass::MemberExprClass == stmt_class) { - auto ME = llvm::cast<const clang::MemberExpr>(ST); - if (ME) { - //retval = ME; - } else { - assert(false); - } - } else { - if (0 == depth) { - int q = 5; - } - int q = 5; - } - if (process_child_flag) { - auto child_iter = ST->child_begin(); - if (child_iter != ST->child_end()) { - if (nullptr != (*child_iter)) { - retval = leading_addressof_operator_info_from_stmt(*(*child_iter), depth+1); - } else { - assert(false); - } - } else { - int q = 5; - } - } - return retval; -} - -struct CArrayInferenceInfo { - bool is_an_indirect_type() const { - if (nullptr != ddecl_conversion_state_ptr) { - return (1 <= ddecl_conversion_state_ptr->m_indirection_state_stack.size()); - } else { - return false; - } - } - bool update_declaration_flag = false; - bool has_just_been_determined_to_be_an_array = false; - size_t indirection_level = 0; - const DeclaratorDecl* ddecl_cptr = nullptr; - CDDeclConversionState* ddecl_conversion_state_ptr = nullptr; - const clang::Expr* declaration_expr_cptr = nullptr; -}; -CArrayInferenceInfo infer_array_type_info_from_stmt_indirection_stack(CDDeclConversionState& ddcs_ref, - const std::vector<std::string>& stmt_indirection_stack, CState1& state1_ref) { - CArrayInferenceInfo retval; - auto DD = ddcs_ref.m_ddecl_cptr; - if (!DD) { assert(false); return retval; } - for (size_t i = 0; ((i < ddcs_ref.m_indirection_state_stack.size()) - && (i < stmt_indirection_stack.size())); i += 1) { - if (("" == stmt_indirection_stack[i])) { - /* We're using the empty string as a generic state for the "terminal level of indirection" - * when we don't want to bother specifying a specific state. */ - retval.indirection_level = i; - } else if ("native pointer" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (("ArraySubscriptExpr" == stmt_indirection_stack[i]) - || ("pointer arithmetic" == stmt_indirection_stack[i])) { - ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; - retval.update_declaration_flag = true; - state1_ref.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); - } else if (("malloc target" == stmt_indirection_stack[i])) { - ddcs_ref.m_indirection_state_stack[i].m_current = "malloc target"; - retval.indirection_level = i; - } else if (("set to null" == stmt_indirection_stack[i]) || - ("memset/cpy target" == stmt_indirection_stack[i])) { - retval.indirection_level = i; - } - } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (("ArraySubscriptExpr" == stmt_indirection_stack[i]) - || ("pointer arithmetic" == stmt_indirection_stack[i])) { - ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; - retval.update_declaration_flag = true; - state1_ref.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); - state1_ref.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); - } - } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (("malloc target" == stmt_indirection_stack[i]) || - ("set to null" == stmt_indirection_stack[i])) { - ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; - retval.update_declaration_flag = true; - retval.has_just_been_determined_to_be_an_array = true; - retval.indirection_level = i; - state1_ref.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1_ref, CDDeclIndirection(*DD, i)); - } else if (("memset/cpy target" == stmt_indirection_stack[i])) { - retval.has_just_been_determined_to_be_an_array = true; - retval.indirection_level = i; - } - } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - if (("malloc target" == stmt_indirection_stack[i]) || - ("set to null" == stmt_indirection_stack[i])) { - retval.has_just_been_determined_to_be_an_array = true; - retval.indirection_level = i; - } - } - } - return retval; -} - -/* We are trying to determine, for each and every pointer, whether or not it is being used as an - * array iterator. So this function takes an expression using a declared (pointer) variable - * and notes when the (pointer) variable, or any dereference of the - * (pointer) variable, is being used as an array iterator. So for example, given a declaration, - * say, "int*** ptr1;" and an expression, say, "(*(ptr1[3]))[5]", it will note the two levels - * of dereference/"indirection" that are being used as array iterators/pointers. Upon determining - * that a pointer (or a dereference/indirection of the pointer) is being used as an array iterator, - * the function will execute any queued up actions that were contingent on such a determination. */ -CArrayInferenceInfo infer_array_type_info_from_stmt(const clang::Stmt& stmt_cref, const std::string& stmt_array_info_str, - CState1& state1_ref, const DeclaratorDecl* DD = nullptr) { - CArrayInferenceInfo retval; - - std::vector<std::string> stmt_indirection_stack; - const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, stmt_cref); - std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); - stmt_indirection_stack.push_back(stmt_array_info_str); - if (expr2) { - const DeclaratorDecl* l_DD = DD; - std::string expr2_stmt_class_name; - expr2_stmt_class_name = expr2->getStmtClassName(); - const DeclaratorDecl* expr2_DD = nullptr; - if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { - auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); - if (expr2_DRE) { - auto expr2_decl = expr2_DRE->getDecl(); - expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); - } else { assert(false); } - } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { - auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); - if (expr2_ME) { - auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); - if (expr2_FD) { - expr2_DD = expr2_FD; - } else { assert(false); } - } else { assert(false); } - } - if (expr2_DD) { - auto expr2_QT = expr2_DD->getType(); - auto expr2_type_str = expr2_QT.getAsString(); - std::string expr2_variable_name = expr2_DD->getNameAsString(); - - if (nullptr == l_DD) { - l_DD = expr2_DD; - } - auto res1 = state1_ref.m_ddecl_conversion_state_map.insert(*l_DD); - auto ddcs_map_iter = res1.first; - auto& ddcs_ref = (*ddcs_map_iter).second; - bool update_declaration_flag = res1.second; - - auto QT = (*l_DD).getType(); - std::string variable_name = (*l_DD).getNameAsString(); - - if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { - retval = infer_array_type_info_from_stmt_indirection_stack(ddcs_ref, stmt_indirection_stack, state1_ref); - } - - retval.update_declaration_flag |= update_declaration_flag; - retval.ddecl_conversion_state_ptr = &ddcs_ref; - } - retval.ddecl_cptr = expr2_DD; - } - retval.declaration_expr_cptr = expr2; - - return retval; -} - /**********************************************************************************************************************/ class MCSSSArrayToPointerDecay : public MatchFinder::MatchCallback { @@ -2733,6 +3044,98 @@ private: /**********************************************************************************************************************/ +struct CAllocFunctionInfo { + bool m_seems_to_be_some_kind_of_malloc_or_realloc = false; + clang::CallExpr::const_arg_iterator m_num_bytes_arg_iter; + std::string m_num_bytes_arg_source_text; +}; +CAllocFunctionInfo analyze_malloc_resemblance(const clang::CallExpr& call_expr, Rewriter &Rewrite) { + CAllocFunctionInfo retval; + + auto CE = &call_expr; + auto function_decl = CE->getDirectCallee(); + auto num_args = CE->getNumArgs(); + if (function_decl && ((1 == num_args) || (2 == num_args))) { + std::string function_name = function_decl->getNameAsString(); + static const std::string alloc_str = "alloc"; + static const std::string realloc_str = "realloc"; + auto lc_function_name = tolowerstr(function_name); + bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size()) + && (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str))); + bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size()) + && (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str))); + bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args)); + if (still_potentially_valid1) { + auto arg_iter = CE->arg_begin(); + if (ends_with_realloc) { + arg_iter++; + } + bool argIsIntegerType = false; + if (*arg_iter) { + argIsIntegerType = (*arg_iter)->getType().split().asPair().first->isIntegerType(); + } + if (argIsIntegerType) { + auto arg_source_range = nice_source_range((*arg_iter)->getSourceRange(), Rewrite); + std::string arg_source_text; + if (arg_source_range.isValid()) { + arg_source_text = Rewrite.getRewrittenText(arg_source_range); + //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); + + bool asterisk_found = false; + auto sizeof_start_index = arg_source_text.find("sizeof("); + if (std::string::npos != sizeof_start_index) { + auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); + if (std::string::npos != sizeof_end_index) { + assert(sizeof_end_index > sizeof_start_index); + std::string before_str = arg_source_text.substr(0, sizeof_start_index); + std::string after_str; + if (sizeof_end_index + 1 < arg_source_text.size()) { + after_str = arg_source_text.substr(sizeof_end_index + 1); + } + + auto index = before_str.size() - 1; + while (0 <= index) { + if ('*' == before_str[index]) { + asterisk_found = true; + } + if (!std::isspace(before_str[index])) { + break; + } + + index -= 1; + } + if (asterisk_found) { + before_str = before_str.substr(0, index); + } else { + size_t index2 = 0; + while (after_str.size() > index2) { + if ('*' == after_str[index2]) { + asterisk_found = true; + } + if (!std::isspace(after_str[index2])) { + break; + } + + index2 += 1; + } + if (asterisk_found) { + after_str = after_str.substr(index2 + 1); + } + } + } + } + if (true || asterisk_found) { + retval.m_num_bytes_arg_iter = arg_iter; + retval.m_seems_to_be_some_kind_of_malloc_or_realloc = true; + retval.m_num_bytes_arg_source_text = arg_source_text; + } + } + } + } + } + return retval; +} + class MCSSSMalloc2 : public MatchFinder::MatchCallback { public: @@ -2773,6 +3176,175 @@ public: return void(); } + if (std::string::npos != source_location_str.find("130")) { + int q = 5; + } + + auto alloc_function_info1 = analyze_malloc_resemblance(*CE, Rewrite); + if (alloc_function_info1.m_seems_to_be_some_kind_of_malloc_or_realloc) { + /* The argument is in the form "something * sizeof(something_else)" or + * "sizeof(something) * something_else". So we're just going to assume that + * this is an instance of an array being allocated. */ + std::string num_elements_text/* = before_str + after_str*/; + QualType QT; + std::string element_type_str; + clang::SourceRange decl_source_range; + std::string variable_name; + std::string bo_replacement_code; + const clang::DeclaratorDecl* DD = nullptr; + + auto lhs_QT = LHS->getType(); + + auto decl = DRE->getDecl(); + DD = dynamic_cast<const DeclaratorDecl*>(decl); + auto VD = dynamic_cast<const VarDecl*>(decl); + + const clang::FieldDecl* FD = nullptr; + if (nullptr != ME) { + auto member_decl = ME->getMemberDecl(); + FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); + } + if (nullptr != FD) { + DD = FD; + } else if (nullptr != VD) { + DD = VD; + } else { + int q = 7; + } + + if (nullptr != DD) { + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + QT = DD->getType(); + variable_name = DD->getNameAsString(); + + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + return; + } + + auto res2 = infer_array_type_info_from_stmt(*LHS, "malloc target", (*this).m_state1, DD); + + if (res2.update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + + const clang::Type* lhs_TP = lhs_QT.getTypePtr(); + auto lhs_type_str = lhs_QT.getAsString(); + + std::string lhs_element_type_str; + if (llvm::isa<const clang::ArrayType>(lhs_TP)) { + auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } + } else if (llvm::isa<const clang::PointerType>(lhs_TP)) { + auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } + } + if ("" != lhs_element_type_str) { + num_elements_text = "("; + num_elements_text += alloc_function_info1.m_num_bytes_arg_source_text; + num_elements_text += ") / sizeof("; + num_elements_text += lhs_element_type_str; + num_elements_text += ")"; + + auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); + auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); + bo_replacement_code += "(" + lhs_source_text + ")"; + bo_replacement_code += ".resize("; + bo_replacement_code += num_elements_text; + bo_replacement_code += ")"; + + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + + auto BOSR = clang::SourceRange(BOSL, BOSLE); + if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid()) + && (nullptr != res2.ddecl_conversion_state_ptr)) { + auto cr_shptr = std::make_shared<CMallocArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, res2.indirection_level), BO, bo_replacement_code); + + if ((*(res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(res2.indirection_level)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } + } else { + int q = 7; + } + } + } + } + } + } + +private: + Rewriter &Rewrite; + CState1& m_state1; +}; + +class MCSSSMallocInitializer2 : public MatchFinder::MatchCallback +{ +public: + MCSSSMallocInitializer2 (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} + + virtual void run(const MatchFinder::MatchResult &MR) + { + const DeclStmt* DS = MR.Nodes.getNodeAs<clang::DeclStmt>("mcsssmallocinitializer1"); + const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssmallocinitializer2"); + const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssmallocinitializer3"); + + if ((DS != nullptr) && (CE != nullptr) && (DD != nullptr)) + { + auto DSSR = nice_source_range(DS->getSourceRange(), Rewrite); + SourceLocation DSSL = DSSR.getBegin(); + SourceLocation DSSLE = DSSR.getEnd(); + + ASTContext *const ASTC = MR.Context; + FullSourceLoc FDSSL = ASTC->getFullLoc(DSSL); + + SourceManager &SM = ASTC->getSourceManager(); + + auto source_location_str = DSSL.printToString(*MR.SourceManager); + std::string source_text; + if (DSSL.isValid() && DSSLE.isValid()) { + source_text = Rewrite.getRewrittenText(SourceRange(DSSL, DSSLE)); + } else { + return; + } + + if (filtered_out_by_location(MR, DSSL)) { + return void(); + } + + if (std::string::npos != source_location_str.find("288")) { + int q = 5; + } + auto function_decl = CE->getDirectCallee(); auto num_args = CE->getNumArgs(); if (function_decl && ((1 == num_args) || (2 == num_args))) { @@ -2790,11 +3362,7 @@ public: if (ends_with_realloc) { iter++; } - bool argIsIntegerType = false; - if (*iter) { - argIsIntegerType = (*iter)->getType().split().asPair().first->isIntegerType(); - } - if (argIsIntegerType) { + { auto arg_source_range = nice_source_range((*iter)->getSourceRange(), Rewrite); std::string arg_source_text; if (arg_source_range.isValid()) { @@ -2849,31 +3417,6 @@ public: * "sizeof(something) * something_else". So we're just going to assume that * this is an instance of an array being allocated. */ std::string num_elements_text/* = before_str + after_str*/; - QualType QT; - std::string element_type_str; - clang::SourceRange decl_source_range; - std::string variable_name; - std::string bo_replacement_code; - const clang::DeclaratorDecl* DD = nullptr; - - auto lhs_QT = LHS->getType(); - - auto decl = DRE->getDecl(); - DD = dynamic_cast<const DeclaratorDecl*>(decl); - auto VD = dynamic_cast<const VarDecl*>(decl); - - const clang::FieldDecl* FD = nullptr; - if (nullptr != ME) { - auto member_decl = ME->getMemberDecl(); - FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); - } - if (nullptr != FD) { - DD = FD; - } else if (nullptr != VD) { - DD = VD; - } else { - int q = 7; - } if (nullptr != DD) { auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); @@ -2884,8 +3427,8 @@ public: } else { return; } - QT = DD->getType(); - variable_name = DD->getNameAsString(); + QualType QT = DD->getType(); + auto variable_name = DD->getNameAsString(); auto qualified_name = DD->getQualifiedNameAsString(); static const std::string mse_namespace_str1 = "mse::"; @@ -2895,46 +3438,62 @@ public: return; } - auto res2 = infer_array_type_info_from_stmt(*LHS, "malloc target", (*this).m_state1, DD); + if (!is_an_indirect_type(DD->getType())) { + return; + } + + auto res1 = (*this).m_state1.m_ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; - if (res2.update_declaration_flag) { - update_declaration(*DD, Rewrite, m_state1); + bool lhs_has_been_determined_to_be_an_array = false; + if ("native pointer" == ddcs_ref.m_indirection_state_stack[0].m_current) { + ddcs_ref.m_indirection_state_stack[0].m_current = "malloc target"; + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + ddcs_ref.m_indirection_state_stack[0].m_current = "dynamic array"; + lhs_has_been_determined_to_be_an_array = true; + //update_declaration_flag = true; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, 0)); + } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + lhs_has_been_determined_to_be_an_array = true; + } else { + assert("native array" != ddcs_ref.m_indirection_state_stack[0].m_current); } - const clang::Type* lhs_TP = lhs_QT.getTypePtr(); - auto lhs_type_str = lhs_QT.getAsString(); + const clang::Type* TP = QT.getTypePtr(); + auto lhs_type_str = QT.getAsString(); - std::string lhs_element_type_str; - if (lhs_TP->isArrayType()) { - auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); + std::string element_type_str; + if (TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(TP); assert(nullptr != ATP); auto element_type = ATP->getElementType(); auto type_str = element_type.getAsString(); if (("char" != type_str) && ("const char" != type_str)) { - lhs_element_type_str = type_str; + element_type_str = type_str; } - } else if (lhs_TP->isPointerType()) { - auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); + } else if (TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(TP); assert(nullptr != TPP); auto target_type = TPP->getPointeeType(); auto type_str = target_type.getAsString(); if (("char" != type_str) && ("const char" != type_str)) { - lhs_element_type_str = type_str; + element_type_str = type_str; } } - if ("" != lhs_element_type_str) { + if ("" != element_type_str) { num_elements_text = "("; num_elements_text += arg_source_text; - num_elements_text += ") / sizeof("; - num_elements_text += lhs_element_type_str; + if (true || (("void" != element_type_str) && ("const void" != element_type_str))) { + num_elements_text += ") / sizeof("; + num_elements_text += element_type_str; + } else { + /* todo: something */ + } num_elements_text += ")"; - auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); - auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); - bo_replacement_code += "(" + lhs_source_text + ")"; - bo_replacement_code += ".resize("; - bo_replacement_code += num_elements_text; - bo_replacement_code += ")"; + std::string initializer_info_str = "(" + num_elements_text + ")"; auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); std::string decl_source_text; @@ -2944,16 +3503,17 @@ public: return; } - auto BOSR = clang::SourceRange(BOSL, BOSLE); - if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid()) - && (nullptr != res2.ddecl_conversion_state_ptr)) { - auto cr_shptr = std::make_shared<CMallocArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, res2.indirection_level), BO, bo_replacement_code); + auto DSSR = clang::SourceRange(DSSL, DSSLE); + if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { + auto cr_shptr = std::make_shared<CInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); - if ((*(res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(res2.indirection_level)) { + if (lhs_has_been_determined_to_be_an_array) { (*cr_shptr).do_replacement(m_state1); } else { m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } + + int q = 3; } else { int q = 7; } @@ -2977,19 +3537,19 @@ private: CState1& m_state1; }; -class MCSSSMallocInitializer2 : public MatchFinder::MatchCallback +class MCSSSNullInitializer : public MatchFinder::MatchCallback { public: - MCSSSMallocInitializer2 (Rewriter &Rewrite, CState1& state1) : + MCSSSNullInitializer (Rewriter &Rewrite, CState1& state1) : Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) { - const DeclStmt* DS = MR.Nodes.getNodeAs<clang::DeclStmt>("mcsssmallocinitializer1"); - const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssmallocinitializer2"); - const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssmallocinitializer3"); + const DeclStmt* DS = MR.Nodes.getNodeAs<clang::DeclStmt>("mcsssnullinitializer1"); + const Expr* RHS = MR.Nodes.getNodeAs<clang::Expr>("mcsssnullinitializer2"); + const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssnullinitializer3"); - if ((DS != nullptr) && (CE != nullptr) && (DD != nullptr)) + if ((DS != nullptr) && (RHS != nullptr) && (DD != nullptr)) { auto DSSR = nice_source_range(DS->getSourceRange(), Rewrite); SourceLocation DSSL = DSSR.getBegin(); @@ -3012,83 +3572,16 @@ public: return void(); } - if (std::string::npos != source_location_str.find("288")) { + if (std::string::npos != source_location_str.find("99")) { int q = 5; } - auto function_decl = CE->getDirectCallee(); - auto num_args = CE->getNumArgs(); - if (function_decl && ((1 == num_args) || (2 == num_args))) { - std::string function_name = function_decl->getNameAsString(); - static const std::string alloc_str = "alloc"; - static const std::string realloc_str = "realloc"; - auto lc_function_name = tolowerstr(function_name); - bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size()) - && (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str))); - bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size()) - && (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str))); - bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args)); - if (still_potentially_valid1) { - auto iter = CE->arg_begin(); - if (ends_with_realloc) { - iter++; - } + Expr::NullPointerConstantKind kind = RHS->IgnoreParenCasts()->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); + if (clang::Expr::NPCK_NotNull != kind) { + if (true) { { - auto arg_source_range = nice_source_range((*iter)->getSourceRange(), Rewrite); - std::string arg_source_text; - if (arg_source_range.isValid()) { - arg_source_text = Rewrite.getRewrittenText(arg_source_range); - //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); - - bool asterisk_found = false; - auto sizeof_start_index = arg_source_text.find("sizeof("); - if (std::string::npos != sizeof_start_index) { - auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); - if (std::string::npos != sizeof_end_index) { - assert(sizeof_end_index > sizeof_start_index); - std::string before_str = arg_source_text.substr(0, sizeof_start_index); - std::string after_str; - if (sizeof_end_index + 1 < arg_source_text.size()) { - after_str = arg_source_text.substr(sizeof_end_index + 1); - } - - auto index = before_str.size() - 1; - while (0 <= index) { - if ('*' == before_str[index]) { - asterisk_found = true; - } - if (!std::isspace(before_str[index])) { - break; - } - - index -= 1; - } - if (asterisk_found) { - before_str = before_str.substr(0, index); - } else { - size_t index2 = 0; - while (after_str.size() > index2) { - if ('*' == after_str[index2]) { - asterisk_found = true; - } - if (!std::isspace(after_str[index2])) { - break; - } - - index2 += 1; - } - if (asterisk_found) { - after_str = after_str.substr(index2 + 1); - } - } - } - } - if (true || asterisk_found) { - /* The argument is in the form "something * sizeof(something_else)" or - * "sizeof(something) * something_else". So we're just going to assume that - * this is an instance of an array being allocated. */ - std::string num_elements_text/* = before_str + after_str*/; - + if (true) { + if (true) { if (nullptr != DD) { auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); @@ -3109,25 +3602,15 @@ public: return; } + if (!is_an_indirect_type(DD->getType())) { + return; + } + auto res1 = (*this).m_state1.m_ddecl_conversion_state_map.insert(*DD); auto ddcs_map_iter = res1.first; auto& ddcs_ref = (*ddcs_map_iter).second; bool update_declaration_flag = res1.second; - bool lhs_has_been_determined_to_be_an_array = false; - if ("native pointer" == ddcs_ref.m_indirection_state_stack[0].m_current) { - ddcs_ref.m_indirection_state_stack[0].m_current = "malloc target"; - } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[0].m_current) { - ddcs_ref.m_indirection_state_stack[0].m_current = "dynamic array"; - lhs_has_been_determined_to_be_an_array = true; - //update_declaration_flag = true; - m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, 0)); - } else if ("dynamic array" == ddcs_ref.m_indirection_state_stack[0].m_current) { - lhs_has_been_determined_to_be_an_array = true; - } else { - assert("native array" != ddcs_ref.m_indirection_state_stack[0].m_current); - } - const clang::Type* TP = QT.getTypePtr(); auto lhs_type_str = QT.getAsString(); @@ -3150,17 +3633,9 @@ public: } } if ("" != element_type_str) { - num_elements_text = "("; - num_elements_text += arg_source_text; - if (true || (("void" != element_type_str) && ("const void" != element_type_str))) { - num_elements_text += ") / sizeof("; - num_elements_text += element_type_str; - } else { - /* todo: something */ - } - num_elements_text += ")"; - - std::string initializer_info_str = "(" + num_elements_text + ")"; + /* We use a space here because we are currently using the empty string to + * indicate that the initializer_info_str should be ignored. */ + std::string initializer_info_str = " "; auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); std::string decl_source_text; @@ -3172,12 +3647,13 @@ public: auto DSSR = clang::SourceRange(DSSL, DSSLE); if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { - auto cr_shptr = std::make_shared<CMallocInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); + auto cr_shptr = std::make_shared<CInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); - if (lhs_has_been_determined_to_be_an_array) { + if (ddcs_ref.has_been_determined_to_be_an_array(0)) { (*cr_shptr).do_replacement(m_state1); } else { - m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } int q = 3; @@ -3257,74 +3733,50 @@ public: arg_source_text = Rewrite.getRewrittenText(arg_source_range); //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); - QualType QT; - std::string variable_name; - std::string ce_replacement_code; - - auto res2 = infer_array_type_info_from_stmt(*(*(CE->arg_begin())), "malloc target", (*this).m_state1); - auto DD = res2.ddecl_cptr; + auto ARG = (*(arg_iter))->IgnoreParenCasts(); + auto arg_res2 = infer_array_type_info_from_stmt(*ARG, "malloc target", (*this).m_state1); + bool arg_is_an_indirect_type = is_an_indirect_type(ARG->getType()); - if (res2.update_declaration_flag) { - update_declaration(*DD, Rewrite, m_state1); + if (arg_res2.update_declaration_flag) { + update_declaration(*(arg_res2.ddecl_cptr), Rewrite, m_state1); } - if (nullptr != DD) { - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } - QT = DD->getType(); - variable_name = DD->getNameAsString(); + auto arg_QT = ARG->getType(); + const clang::Type* arg_TP = arg_QT.getTypePtr(); + auto arg_type_str = arg_QT.getAsString(); - auto qualified_name = DD->getQualifiedNameAsString(); - static const std::string mse_namespace_str1 = "mse::"; - static const std::string mse_namespace_str2 = "::mse::"; - if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) - || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { - return; + std::string arg_element_type_str; + if (arg_TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(arg_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg_element_type_str = type_str; } - - const clang::Type* TP = QT.getTypePtr(); - auto type_str = QT.getAsString(); - - std::string element_type_str; - if (TP->isArrayType()) { - auto ATP = llvm::cast<const clang::ArrayType>(TP); - assert(nullptr != ATP); - auto element_type = ATP->getElementType(); - auto type_str = element_type.getAsString(); - if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; - } - } else if (TP->isPointerType()) { - auto TPP = llvm::cast<const clang::PointerType>(TP); - assert(nullptr != TPP); - auto target_type = TPP->getPointeeType(); - auto type_str = target_type.getAsString(); - if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; - } + } else if (arg_TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(arg_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg_element_type_str = type_str; } + } - if ("" != element_type_str) { - ce_replacement_code = "(" + arg_source_text + ")"; + if ("" != arg_element_type_str) { + if (ConvertToSCPP && (arg_res2.ddecl_conversion_state_ptr) && arg_is_an_indirect_type) { + auto arg_source_text = Rewrite.getRewrittenText(arg_source_range); + std::string ce_replacement_code = "(" + arg_source_text + ")"; ce_replacement_code += ".resize(0)"; - if (ConvertToSCPP && decl_source_range.isValid() && (CESR.isValid()) - && (nullptr != res2.ddecl_conversion_state_ptr)) { - auto cr_shptr = std::make_shared<CFreeDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(res2.ddecl_cptr), res2.indirection_level), CE, ce_replacement_code); + auto cr_shptr = std::make_shared<CFreeDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(arg_res2.ddecl_cptr), arg_res2.indirection_level), CE, ce_replacement_code); - if ((*(res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(res2.indirection_level)) { - (*cr_shptr).do_replacement(m_state1); - } else { - m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); - } + if ((*(arg_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(arg_res2.indirection_level)) { + (*cr_shptr).do_replacement(m_state1); } else { - int q = 7; + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } } } @@ -3387,7 +3839,7 @@ public: } Expr::NullPointerConstantKind kind = RHS->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); - if (clang::Expr::NPCK_NotNull != kind) { + if (false && (clang::Expr::NPCK_NotNull != kind)) { auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); std::string lhs_source_text; if (lhs_source_range.isValid()) { @@ -3406,7 +3858,7 @@ public: auto lhs_type_str = lhs_QT.getAsString(); std::string lhs_element_type_str; - if (lhs_TP->isArrayType()) { + if (llvm::isa<const clang::ArrayType>(lhs_TP)) { auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); assert(nullptr != ATP); auto element_type = ATP->getElementType(); @@ -3414,7 +3866,7 @@ public: if (("char" != type_str) && ("const char" != type_str)) { lhs_element_type_str = type_str; } - } else if (lhs_TP->isPointerType()) { + } else if (llvm::isa<const clang::PointerType>(lhs_TP)) { auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); assert(nullptr != TPP); auto target_type = TPP->getPointeeType(); @@ -3427,15 +3879,125 @@ public: if ("" != lhs_element_type_str) { if (ConvertToSCPP && (lhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); - std::string bo_replacement_code = "(" + lhs_source_text + ")"; - bo_replacement_code += ".resize(0)"; + std::string bo_replacement_code = "( (" + lhs_source_text + ") = typename std::remove_reference<decltype(" + lhs_source_text + ")>::type() )"; - auto cr_shptr = std::make_shared<CSetArrayPointerToNull2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level), BO, bo_replacement_code); + auto cr_shptr = std::make_shared<CExprTextReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level), BO, bo_replacement_code); if ((*(lhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(lhs_res2.indirection_level)) { (*cr_shptr).do_replacement(m_state1); } else { - m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } + int q = 5; + } else { + int q = 5; + } + int q = 5; + } + } + } + +private: + Rewriter &Rewrite; + CState1& m_state1; +}; + +class MCSSSCompareWithNull2 : public MatchFinder::MatchCallback +{ +public: + MCSSSCompareWithNull2 (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} + + virtual void run(const MatchFinder::MatchResult &MR) + { + const BinaryOperator* BO = MR.Nodes.getNodeAs<clang::BinaryOperator>("mcssscomparewithnull1"); + const Expr* RHS = nullptr; + const Expr* LHS = nullptr; + if (BO != nullptr) { + RHS = BO->getRHS(); + LHS = BO->getLHS(); + } + const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcssscomparewithnull3"); + const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcssscomparewithnull4"); + + if ((BO != nullptr) && (RHS != nullptr) && (LHS != nullptr) && (DRE != nullptr)) + { + auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); + SourceLocation BOSL = BOSR.getBegin(); + SourceLocation BOSLE = BOSR.getEnd(); + + ASTContext *const ASTC = MR.Context; + FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL); + + SourceManager &SM = ASTC->getSourceManager(); + + auto source_location_str = BOSL.printToString(*MR.SourceManager); + std::string source_text; + if (BOSL.isValid() && BOSLE.isValid()) { + source_text = Rewrite.getRewrittenText(SourceRange(BOSL, BOSLE)); + } else { + return; + } + + if (filtered_out_by_location(MR, BOSL)) { + return void(); + } + + Expr::NullPointerConstantKind kind = RHS->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); + if (clang::Expr::NPCK_NotNull != kind) { + auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); + std::string lhs_source_text; + if (lhs_source_range.isValid()) { + lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); + //auto lhs_source_text_sans_ws = with_whitespace_removed(lhs_source_text); + + auto lhs_res2 = infer_array_type_info_from_stmt(*LHS, "compare with null", (*this).m_state1); + bool lhs_is_an_indirect_type = is_an_indirect_type(LHS->getType()); + + if (lhs_res2.update_declaration_flag) { + update_declaration(*(lhs_res2.ddecl_cptr), Rewrite, m_state1); + } + + auto lhs_QT = LHS->getType(); + const clang::Type* lhs_TP = lhs_QT.getTypePtr(); + auto lhs_type_str = lhs_QT.getAsString(); + + std::string lhs_element_type_str; + if (llvm::isa<const clang::ArrayType>(lhs_TP)) { + auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } + } else if (llvm::isa<const clang::PointerType>(lhs_TP)) { + auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } + } + + if ("" != lhs_element_type_str) { + if (ConvertToSCPP && (lhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { + std::string opcode_str = BO->getOpcodeStr(); + + auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); + std::string bo_replacement_code = "bool(" + lhs_source_text + ")"; + + auto cr_shptr = std::make_shared<CExprTextReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level), BO, bo_replacement_code); + + if ((*(lhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(lhs_res2.indirection_level)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } } } @@ -3589,10 +4151,14 @@ public: } } if ("" != arg1_element_type_str) { - ce_replacement_code = "for (size_t i = 0; i < (" + arg_source_text3 - + ")/sizeof(" + arg1_element_type_str + "); i += 1) { "; - ce_replacement_code += "(" + arg_source_text1 + ")[i] = " + arg_source_text2 + "; "; - ce_replacement_code += "}"; + if (false) { + ce_replacement_code = "for (size_t i = 0; i < (" + arg_source_text3 + + ")/sizeof(" + arg1_element_type_str + "); i += 1) { "; + ce_replacement_code += "(" + arg_source_text1 + ")[i] = " + arg_source_text2 + "; "; + ce_replacement_code += "}"; + } else { + ce_replacement_code = "MSE_LH_MEMSET(" + arg_source_text1 + ", " + arg_source_text2 + ", " + arg_source_text3 + ")"; + } if (ConvertToSCPP && decl_source_range.isValid() && (CESR.isValid()) && (nullptr != res2.ddecl_conversion_state_ptr)) { @@ -3767,10 +4333,14 @@ public: } std::string ce_replacement_code; if (("" != arg1_element_type_str) && ("void" != arg1_element_type_str) && ("const void" != arg1_element_type_str)) { - ce_replacement_code = "for (size_t i = 0; i < (" + arg_source_text3 - + ")/sizeof(" + arg1_element_type_str + "); i += 1) { "; - ce_replacement_code += "(" + arg_source_text1 + ")[i] = (" + arg_source_text2 + ")[i]; "; - ce_replacement_code += "}"; + if (false) { + ce_replacement_code = "for (size_t i = 0; i < (" + arg_source_text3 + + ")/sizeof(" + arg1_element_type_str + "); i += 1) { "; + ce_replacement_code += "(" + arg_source_text1 + ")[i] = (" + arg_source_text2 + ")[i]; "; + ce_replacement_code += "}"; + } else { + ce_replacement_code = "MSE_LH_MEMCPY(" + arg_source_text1 + ", " + arg_source_text2 + ", " + arg_source_text3 + ")"; + } } if (ConvertToSCPP && (CESR.isValid()) && ("" != ce_replacement_code)) { @@ -4083,7 +4653,7 @@ public: return void(); } - if (std::string::npos != source_location_str.find("129")) { + if (std::string::npos != source_location_str.find("457")) { int q = 5; } @@ -4108,26 +4678,36 @@ public: auto direct_rhs_qtype = populateQTypeIndirectionStack(rhs_qtype_indirection_state_stack, rhs_QT); auto direct_rhs_qtype_str = direct_rhs_qtype.getAsString(); auto casted_expr_ptr = CCE->IgnoreCasts(); + if (llvm::isa<const clang::CallExpr>(casted_expr_ptr->IgnoreParenCasts())) { + auto CE = llvm::cast<const clang::CallExpr>(casted_expr_ptr->IgnoreParenCasts()); + auto alloc_function_info1 = analyze_malloc_resemblance(*CE, Rewrite); + if (alloc_function_info1.m_seems_to_be_some_kind_of_malloc_or_realloc) { + /* This seems to be some kind of malloc/realloc function. These case should not be + * handled here. They are handled elsewhere. */ + return; + } + } if ((rhs_qtype_indirection_state_stack.size() + rhs_res2.indirection_level == (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) && (1 <= (*rhs_res2.ddecl_conversion_state_ptr).m_indirection_state_stack.size()) && (nullptr != casted_expr_ptr)) { - std::string rhs_ddecl_current_direct_qtype_str = (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype.getAsString(); + std::string rhs_ddecl_current_direct_qtype_str = (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype_str; auto casted_expr_SR = nice_source_range(casted_expr_ptr->getSourceRange(), Rewrite); auto CCESR = nice_source_range(CCE->getSourceRange(), Rewrite); + auto cast_operation_SR = clang::SourceRange(CCE->getLParenLoc(), CCE->getRParenLoc()); - if (CCESR.isValid() && casted_expr_SR.isValid() + if (cast_operation_SR.isValid() && (("void" == rhs_ddecl_current_direct_qtype_str) || ("const void" == rhs_ddecl_current_direct_qtype_str))) { if (ConvertToSCPP) { - (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype = direct_rhs_qtype; + (*rhs_res2.ddecl_conversion_state_ptr).set_current_direct_qtype(direct_rhs_qtype); + auto cast_operation_text = Rewrite.getRewrittenText(cast_operation_SR); /* This is not the proper way to modify an expression. See the function * CConditionalOperatorReconciliation2ReplacementAction::do_replacement() for an example of * the proper way to do it. But for now this is good enough. */ - auto casted_expr_text = Rewrite.getRewrittenText(casted_expr_SR); - auto res2 = Rewrite.ReplaceText(CCESR, casted_expr_text); + auto res2 = Rewrite.ReplaceText(cast_operation_SR, ""); static const std::string void_str = "void"; auto void_pos = (*rhs_res2.ddecl_conversion_state_ptr).m_initializer_info_str.find(void_str); @@ -4139,7 +4719,9 @@ public: } } else { if (ConvertToSCPP) { - //(*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype = direct_rhs_qtype; + if (false) { + (*rhs_res2.ddecl_conversion_state_ptr).set_current_direct_qtype(direct_rhs_qtype); + } } } } else { @@ -4150,6 +4732,32 @@ public: } } + size_t lhs_indirection_level_adjustment = 0; + auto rhs_res3 = leading_addressof_operator_info_from_stmt(*RHS); + if (rhs_res3.without_leading_addressof_operator_expr_cptr) { + assert(rhs_res3.leading_addressof_operator_detected && rhs_res3.addressof_unary_operator_cptr); + + RHS = rhs_res3.without_leading_addressof_operator_expr_cptr; + rhs_res2 = infer_array_type_info_from_stmt(*RHS, "", (*this).m_state1); + lhs_indirection_level_adjustment = 1; + + const clang::ArraySubscriptExpr* array_subscript_expr_cptr = nullptr; + if (clang::Stmt::StmtClass::ArraySubscriptExprClass == (*(rhs_res3.without_leading_addressof_operator_expr_cptr)).getStmtClass()) { + assert(llvm::isa<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr)); + array_subscript_expr_cptr = llvm::cast<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr); + } + if (ConvertToSCPP && array_subscript_expr_cptr) { + std::shared_ptr<CArray2ReplacementAction> cr_shptr = std::make_shared<CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*(lhs_res2.ddecl_cptr), 0), *(rhs_res3.addressof_unary_operator_cptr), *array_subscript_expr_cptr); + + if ((*(lhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array()) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } + if (ConvertToSCPP && (lhs_res2.ddecl_conversion_state_ptr) && (rhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { for (size_t i = 0; (rhs_res2.indirection_level + i < (*(lhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) && (rhs_res2.indirection_level + i < (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()); i += 1) { @@ -4157,11 +4765,18 @@ public: /* Here we're establishing and "enforcing" the constraint that the rhs value must * be of an (array) type that can be assigned to the lhs. */ auto cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level + i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + auto cr_shptr2 = std::make_shared<CAssignmentTargetConstrainsSourceDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level + i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); if ((*(lhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(lhs_res2.indirection_level + i)) { (*cr_shptr).do_replacement(m_state1); + if ((*(lhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_a_dynamic_array(lhs_res2.indirection_level + i)) { + (*cr_shptr2).do_replacement(m_state1); + } else { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr2); + } } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr2); } } { @@ -4221,7 +4836,7 @@ public: return void(); } - if (std::string::npos != source_location_str.find("130")) { + if (std::string::npos != source_location_str.find("438")) { int q = 5; } @@ -4277,6 +4892,104 @@ public: auto& ddcs_ref = (*ddcs_map_iter).second; bool update_declaration_flag = res1.second; + auto lhs_QT = param_VD->getType(); + const clang::Type* lhs_TP = lhs_QT.getTypePtr(); + auto lhs_type_str = lhs_QT.getAsString(); + + bool lhs_element_type_is_const_char = false; + std::string lhs_element_type_str; + if (llvm::isa<const clang::ArrayType>(lhs_TP)) { + auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } else if ("const char" == type_str) { + lhs_element_type_is_const_char = true; + } + } else if (llvm::isa<const clang::PointerType>(lhs_TP)) { + auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } else if ("const char" == type_str) { + lhs_element_type_is_const_char = true; + } + } + + Expr::NullPointerConstantKind kind = arg_EX->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); + if (false && (clang::Expr::NPCK_NotNull != kind)) { + + if ("" != lhs_element_type_str) { + auto lhs_source_range = nice_source_range(param_VD->getSourceRange(), Rewrite); + if (ConvertToSCPP && lhs_is_an_indirect_type && lhs_source_range.isValid()) { + auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); + + auto res4 = generate_type_indirection_prefix_and_suffix(ddcs_ref.m_indirection_state_stack, false/*direct_type_is_char_type*/, false/*direct_type_is_function_type*/, true/*is_a_function_parameter*/); + if (true) { + auto direct_qtype = ddcs_ref.m_current_direct_qtype; + if (res4.m_direct_type_must_be_non_const) { + direct_qtype.removeLocalConst(); + } + std::string direct_qtype_str = direct_qtype.getAsString(); + std::string arg_replacement_code = res4.m_prefix_str + direct_qtype_str + res4.m_suffix_str + "()"; + + auto cr_shptr = std::make_shared<CExprTextReplacementAction>(Rewrite, MR, CDDeclIndirection(*(param_VD), 0/*indirection_level*/), arg_EX, arg_replacement_code); + + if (ddcs_ref.has_been_determined_to_be_an_array()) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + //m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } + } + return; + } + + auto argii_EX = (*arg_iter)->IgnoreImplicit(); + if (rhs_is_an_indirect_type && (argii_EX->getStmtClass() == clang::Stmt::StmtClass::CStyleCastExprClass)) { + bool special_case1_flag = false; + auto casted_expr = argii_EX->IgnoreParenCasts(); + std::string casted_expr_type_str = casted_expr->getType().getAsString(); + if ("const unsigned char" == lhs_element_type_str) { + if (("char *" == casted_expr_type_str) || ("const char *" == casted_expr_type_str)) { + special_case1_flag = true; + } + } else if (lhs_element_type_is_const_char) { + //lhs_element_type_str = "const char"; + if (("unsigned char *" == casted_expr_type_str) || ("const unsigned char *" == casted_expr_type_str)) { + special_case1_flag = true; + } + } + if (special_case1_flag) { + auto casted_expr_SR = nice_source_range(casted_expr->getSourceRange(), Rewrite); + std::string casted_expr_text = Rewrite.getRewrittenText(casted_expr_SR); + std::string replacement_casted_expr_text = "std::addressof(" + casted_expr_text + "[0])"; + Rewrite.ReplaceText(casted_expr_SR, replacement_casted_expr_text); + return; + } else { + auto CSCE = llvm::cast<const clang::CStyleCastExpr>(argii_EX); + if (CSCE) { + auto cast_operation_SR = clang::SourceRange(CSCE->getLParenLoc(), CSCE->getRParenLoc()); + if (ConvertToSCPP && cast_operation_SR.isValid()) { + auto cast_operation_text = Rewrite.getRewrittenText(cast_operation_SR); + /* This is not the proper way to modify an expression. See the function + * CConditionalOperatorReconciliation2ReplacementAction::do_replacement() for an example of + * the proper way to do it. But for now this is good enough. */ + auto res2 = Rewrite.ReplaceText(cast_operation_SR, ""); + } + + auto cast_kind_name = CSCE->getCastKindName(); + auto cast_kind = CSCE->getCastKind(); + } else { assert(false); } + } + } + size_t lhs_indirection_level_adjustment = 0; auto rhs_res3 = leading_addressof_operator_info_from_stmt(*arg_EX); if (rhs_res3.without_leading_addressof_operator_expr_cptr) { @@ -4290,11 +5003,11 @@ public: assert(llvm::isa<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr)); array_subscript_expr_cptr = llvm::cast<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr); } - if (array_subscript_expr_cptr) { + if (ConvertToSCPP && array_subscript_expr_cptr) { std::shared_ptr<CArray2ReplacementAction> cr_shptr = std::make_shared<CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*param_VD, 0), *(rhs_res3.addressof_unary_operator_cptr), *array_subscript_expr_cptr); - if (ddcs_ref.has_been_determined_to_be_an_array(0)) { + if (ddcs_ref.has_been_determined_to_be_an_array()) { (*cr_shptr).do_replacement(m_state1); } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); @@ -4307,56 +5020,6 @@ public: update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); } - if ((nullptr != CCE) && (rhs_res2.ddecl_conversion_state_ptr)) { - auto cce_QT = CCE->getType(); - auto rhs_QT = arg_EX->getType(); - if (cce_QT == rhs_QT) { - CIndirectionStateStack rhs_qtype_indirection_state_stack; - auto direct_rhs_qtype = populateQTypeIndirectionStack(rhs_qtype_indirection_state_stack, rhs_QT); - auto direct_rhs_qtype_str = direct_rhs_qtype.getAsString(); - auto casted_expr_ptr = CCE->IgnoreCasts(); - - if ((rhs_qtype_indirection_state_stack.size() + rhs_res2.indirection_level - == (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) - && (1 <= (*rhs_res2.ddecl_conversion_state_ptr).m_indirection_state_stack.size()) - && (nullptr != casted_expr_ptr)) { - - std::string rhs_ddecl_current_direct_qtype_str = (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype.getAsString(); - auto casted_expr_SR = nice_source_range(casted_expr_ptr->getSourceRange(), Rewrite); - auto CCESR = nice_source_range(CCE->getSourceRange(), Rewrite); - - if (CCESR.isValid() && casted_expr_SR.isValid() - && (("void" == rhs_ddecl_current_direct_qtype_str) || ("const void" == rhs_ddecl_current_direct_qtype_str))) { - if (ConvertToSCPP) { - (*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype = direct_rhs_qtype; - - /* This is not the proper way to modify an expression. See the function - * CConditionalOperatorReconciliation2ReplacementAction::do_replacement() for an example of - * the proper way to do it. But for now this is good enough. */ - auto casted_expr_text = Rewrite.getRewrittenText(casted_expr_SR); - auto res2 = Rewrite.ReplaceText(CCESR, casted_expr_text); - - static const std::string void_str = "void"; - auto void_pos = (*rhs_res2.ddecl_conversion_state_ptr).m_initializer_info_str.find(void_str); - if (std::string::npos != void_pos) { - (*rhs_res2.ddecl_conversion_state_ptr).m_initializer_info_str.replace(void_pos, void_str.length(), direct_rhs_qtype_str); - } - - update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); - } - } else { - if (ConvertToSCPP) { - //(*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype = direct_rhs_qtype; - } - } - } else { - int q = 7; - } - } else { - int q = 7; - } - } - if (ddcs_ref.m_ddecl_cptr && update_declaration_flag) { update_declaration(*(ddcs_ref.m_ddecl_cptr), Rewrite, m_state1); } @@ -4425,7 +5088,65 @@ public: int q = 5; } } + } else { + auto D = CE->getCalleeDecl(); + auto DD = dynamic_cast<const DeclaratorDecl*>(D); + auto EX = CE->getCallee(); + + if (DD && EX) { + auto DDSR = nice_source_range(DD->getSourceRange(), Rewrite); + std::string ddecl_source_text; + if (DDSR.isValid()) { + ddecl_source_text = Rewrite.getRewrittenText(DDSR); + } else { + return; + } + auto EXSR = nice_source_range(EX->getSourceRange(), Rewrite); + std::string expr_source_text; + if (EXSR.isValid()) { + expr_source_text = Rewrite.getRewrittenText(EXSR); + } else { + return; + } + + if (ConvertToSCPP) { + auto args = CE->arguments(); + for (auto& arg : args) { + auto rhs_res2 = infer_array_type_info_from_stmt(*arg, "", (*this).m_state1); + bool rhs_is_an_indirect_type = is_an_indirect_type(arg->getType()); + + if (rhs_res2.ddecl_cptr && rhs_res2.ddecl_conversion_state_ptr) { + int int_max_indirection_level = int((*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) - int(rhs_res2.indirection_level); + size_t szt_max_indirection_level = 0; + if (0 <= int_max_indirection_level) { + szt_max_indirection_level = size_t(int_max_indirection_level); + } + + for (size_t i = 0; i < szt_max_indirection_level; i += 1) { + std::shared_ptr<CUpdateIndirectFunctionTypeParamsArray2ReplacementAction> cr_shptr = + std::make_shared<CUpdateIndirectFunctionTypeParamsArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), *DD, *CE); + + if ((*(rhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(rhs_res2.indirection_level + i)) { + (*cr_shptr).do_replacement(m_state1); + if (!((*(rhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_a_dynamic_array(rhs_res2.indirection_level + i))) { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } else { + int q = 5; + } + } + } + int q = 5; + } else { + int q = 7; + } } } } @@ -4470,6 +5191,11 @@ public: return void(); } + if (std::string::npos != source_location_str.find("129")) { + walkTheAST1(*RS); + int q = 5; + } + auto function_decl1 = FND; auto num_params = FND->getNumParams(); if (function_decl1) { @@ -4493,8 +5219,38 @@ public: return void(); } - auto rhs_res2 = infer_array_type_info_from_stmt(*(RS->getRetValue()), "", (*this).m_state1); - bool rhs_is_an_indirect_type = is_an_indirect_type(RS->getRetValue()->getType()); + auto retval_EX = RS->getRetValue(); + + bool rhs_is_an_indirect_type = is_an_indirect_type(retval_EX->getType()); + + auto retvalii_EX = RS->getRetValue()->IgnoreImplicit(); + if (rhs_is_an_indirect_type && (retvalii_EX->getStmtClass() == clang::Stmt::StmtClass::CStyleCastExprClass)) { + auto CSCE = llvm::cast<const clang::CStyleCastExpr>(retvalii_EX); + if (CSCE) { + auto cast_operation_SR = clang::SourceRange(CSCE->getLParenLoc(), CSCE->getRParenLoc()); + if (ConvertToSCPP && cast_operation_SR.isValid()) { + auto cast_operation_text = Rewrite.getRewrittenText(cast_operation_SR); + /* This is not the proper way to modify an expression. See the function + * CConditionalOperatorReconciliation2ReplacementAction::do_replacement() for an example of + * the proper way to do it. But for now this is good enough. */ + auto res2 = Rewrite.ReplaceText(cast_operation_SR, ""); + } + + auto cast_kind_name = CSCE->getCastKindName(); + auto cast_kind = CSCE->getCastKind(); + } else { assert(false); } + } + + size_t lhs_indirection_level_adjustment = 0; + auto rhs_res3 = leading_addressof_operator_info_from_stmt(*retval_EX); + if (rhs_res3.without_leading_addressof_operator_expr_cptr) { + assert(rhs_res3.leading_addressof_operator_detected && rhs_res3.addressof_unary_operator_cptr); + + retval_EX = rhs_res3.without_leading_addressof_operator_expr_cptr; + lhs_indirection_level_adjustment = 1; + } + + auto rhs_res2 = infer_array_type_info_from_stmt(*(retval_EX), "", (*this).m_state1); if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); } @@ -4512,28 +5268,78 @@ public: update_declaration(*(ddcs_ref.m_ddecl_cptr), Rewrite, m_state1); } + if (rhs_res3.without_leading_addressof_operator_expr_cptr) { + const clang::ArraySubscriptExpr* array_subscript_expr_cptr = nullptr; + if (clang::Stmt::StmtClass::ArraySubscriptExprClass == (*(rhs_res3.without_leading_addressof_operator_expr_cptr)).getStmtClass()) { + assert(llvm::isa<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr)); + array_subscript_expr_cptr = llvm::cast<const clang::ArraySubscriptExpr>(rhs_res3.without_leading_addressof_operator_expr_cptr); + } + if (array_subscript_expr_cptr) { + std::shared_ptr<CArray2ReplacementAction> cr_shptr = std::make_shared<CAssignmentTargetConstrainsAddressofArraySubscriptExprArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*function_decl, 0), *(rhs_res3.addressof_unary_operator_cptr), *array_subscript_expr_cptr); + + if (ddcs_ref.has_been_determined_to_be_an_array(0)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } + if (ConvertToSCPP && (rhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { - for (size_t i = 0; (rhs_res2.indirection_level + i < ddcs_ref.m_indirection_state_stack.size()) - && (rhs_res2.indirection_level + i < (*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()); i += 1) { + int max_indirection_level1 = int((*(rhs_res2.ddecl_conversion_state_ptr)).m_indirection_state_stack.size()) - int(rhs_res2.indirection_level); + int int_max_indirection_level = std::min(int(ddcs_ref.m_indirection_state_stack.size()) - int(lhs_indirection_level_adjustment), max_indirection_level1); + size_t szt_max_indirection_level = 0; + if (0 <= int_max_indirection_level) { + szt_max_indirection_level = size_t(int_max_indirection_level); + } + + for (size_t i = 0; (i < szt_max_indirection_level); i += 1) { { /* Here we're establishing and "enforcing" the constraint that the rhs value must * be of an (array) type that can be assigned to the lhs. */ - auto cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*function_decl, 0 + i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + std::shared_ptr<CArray2ReplacementAction> cr_shptr; + if (1 > (i + lhs_indirection_level_adjustment)) { + cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*function_decl, i + lhs_indirection_level_adjustment), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + } else { + /* Levels of indirection beyond the first one must be of the same type, + * not just of "compatible" types. */ + cr_shptr = std::make_shared<CSameTypeArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*function_decl, i + lhs_indirection_level_adjustment), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + } - if (ddcs_ref.has_been_determined_to_be_an_array(0 + i)) { + if (ddcs_ref.has_been_determined_to_be_an_array(i + lhs_indirection_level_adjustment)) { (*cr_shptr).do_replacement(m_state1); + if (!(ddcs_ref.has_been_determined_to_be_a_dynamic_array(i + lhs_indirection_level_adjustment))) { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } } { /* Here we're establishing the constraint in the opposite direction as well. */ - auto cr_shptr = std::make_shared<CAssignmentSourceConstrainsTargetArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), CDDeclIndirection(*function_decl, 0 + i)); + std::shared_ptr<CArray2ReplacementAction> cr_shptr; + if (1 > (i + lhs_indirection_level_adjustment)) { + cr_shptr = std::make_shared<CAssignmentSourceConstrainsTargetArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), CDDeclIndirection(*function_decl, i + lhs_indirection_level_adjustment)); + } else { + /* Levels of indirection beyond the first one must be of the same type, + * not just of "compatible" types. */ + cr_shptr = std::make_shared<CSameTypeArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), CDDeclIndirection(*function_decl, i + lhs_indirection_level_adjustment)); + } if ((*(rhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(rhs_res2.indirection_level + i)) { (*cr_shptr).do_replacement(m_state1); + if (!((*(rhs_res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_a_dynamic_array(rhs_res2.indirection_level + i))) { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } } } @@ -4549,15 +5355,386 @@ private: CState1& m_state1; }; +class MCSSSFRead : public MatchFinder::MatchCallback +{ +public: + MCSSSFRead (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} + + virtual void run(const MatchFinder::MatchResult &MR) + { + const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssfread1"); + const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssfread2"); + const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcsssfread3"); + + if ((CE != nullptr) && (DRE != nullptr)) + { + auto CESR = nice_source_range(CE->getSourceRange(), Rewrite); + SourceLocation CESL = CESR.getBegin(); + SourceLocation CESLE = CESR.getEnd(); + + ASTContext *const ASTC = MR.Context; + FullSourceLoc FCESL = ASTC->getFullLoc(CESL); + + SourceManager &SM = ASTC->getSourceManager(); + + auto source_location_str = CESL.printToString(*MR.SourceManager); + std::string source_text; + if (CESL.isValid() && CESLE.isValid()) { + source_text = Rewrite.getRewrittenText(SourceRange(CESL, CESLE)); + } else { + return; + } + + if (filtered_out_by_location(MR, CESL)) { + return void(); + } + + auto function_decl = CE->getDirectCallee(); + auto num_args = CE->getNumArgs(); + if (function_decl && (4 == num_args)) { + { + std::string function_name = function_decl->getNameAsString(); + static const std::string fread_str = "fread"; + if (fread_str == function_name) { + auto iter1 = CE->arg_begin(); + assert((*iter1)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range1 = nice_source_range((*iter1)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter2 = iter1; + iter2++; + assert((*iter2)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range2 = nice_source_range((*iter2)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter3 = iter2; + iter3++; + assert((*iter3)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range3 = nice_source_range((*iter3)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter4 = iter3; + iter4++; + assert((*iter4)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range4 = nice_source_range((*iter4)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + std::string arg_source_text1; + std::string arg_source_text2; + std::string arg_source_text3; + std::string arg_source_text4; + if (arg_source_range1.isValid() && arg_source_range2.isValid() && arg_source_range3.isValid() && arg_source_range3.isValid() && arg_source_range4.isValid()) { + arg_source_text1 = Rewrite.getRewrittenText(arg_source_range1); + arg_source_text2 = Rewrite.getRewrittenText(arg_source_range2); + arg_source_text3 = Rewrite.getRewrittenText(arg_source_range3); + arg_source_text4 = Rewrite.getRewrittenText(arg_source_range4); + + QualType QT; + clang::SourceRange decl_source_range; + std::string variable_name; + const clang::DeclaratorDecl* DD = nullptr; + CArrayInferenceInfo res2; + + auto decl = DRE->getDecl(); + DD = dynamic_cast<const DeclaratorDecl*>(decl); + auto VD = dynamic_cast<const VarDecl*>(decl); + + const clang::FieldDecl* FD = nullptr; + if (nullptr != ME) { + auto member_decl = ME->getMemberDecl(); + FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); + } + if (nullptr != FD) { + DD = FD; + } else if (nullptr != VD) { + DD = VD; + } else { + int q = 7; + } + + if (nullptr != DD) { + decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + QT = DD->getType(); + auto qtype_str = QT.getAsString(); + variable_name = DD->getNameAsString(); + + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + return; + } + + res2 = infer_array_type_info_from_stmt(*(*(CE->arg_begin())), "memset/cpy target", (*this).m_state1, DD); + + if (res2.update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + } + + clang::QualType arg1_QT = (*iter1)->IgnoreParenCasts()->getType(); + if (nullptr != DD) { + arg1_QT = QT; + } + const clang::Type* arg1_TP = arg1_QT.getTypePtr(); + auto arg1_type_str = arg1_QT.getAsString(); + + std::string arg1_element_type_str; + if (arg1_TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(arg1_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg1_element_type_str = type_str; + } + } else if (arg1_TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(arg1_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg1_element_type_str = type_str; + } + } + std::string ce_replacement_code; + if (("" != arg1_element_type_str) && ("void" != arg1_element_type_str) && ("const void" != arg1_element_type_str)) { + ce_replacement_code = "MSE_LH_FREAD(" + arg_source_text1 + ", " + arg_source_text2 + + ", "+ arg_source_text3 + ", "+ arg_source_text4 + ")"; + } + + if (ConvertToSCPP && (CESR.isValid()) && ("" != ce_replacement_code)) { + auto cr_shptr = std::make_shared<CExprTextReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, res2.indirection_level), CE, ce_replacement_code); + if ((nullptr != res2.ddecl_conversion_state_ptr)) { + if (true || (*(res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(res2.indirection_level)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } + } else { + (*cr_shptr).do_replacement(m_state1); + } + } else { + int q = 7; + } + + int q = 5; + } else { + int q = 5; + } + int q = 5; + } + } + + } + } + } + +private: + Rewriter &Rewrite; + CState1& m_state1; +}; + +class MCSSSFWrite : public MatchFinder::MatchCallback +{ +public: + MCSSSFWrite (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} + + virtual void run(const MatchFinder::MatchResult &MR) + { + const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssfwrite1"); + const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssfwrite2"); + const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcsssfwrite3"); + + if ((CE != nullptr) && (DRE != nullptr)) + { + auto CESR = nice_source_range(CE->getSourceRange(), Rewrite); + SourceLocation CESL = CESR.getBegin(); + SourceLocation CESLE = CESR.getEnd(); + + ASTContext *const ASTC = MR.Context; + FullSourceLoc FCESL = ASTC->getFullLoc(CESL); + + SourceManager &SM = ASTC->getSourceManager(); + + auto source_location_str = CESL.printToString(*MR.SourceManager); + std::string source_text; + if (CESL.isValid() && CESLE.isValid()) { + source_text = Rewrite.getRewrittenText(SourceRange(CESL, CESLE)); + } else { + return; + } + + if (filtered_out_by_location(MR, CESL)) { + return void(); + } + + auto function_decl = CE->getDirectCallee(); + auto num_args = CE->getNumArgs(); + if (function_decl && (4 == num_args)) { + { + std::string function_name = function_decl->getNameAsString(); + static const std::string fwrite_str = "fwrite"; + if (fwrite_str == function_name) { + auto iter1 = CE->arg_begin(); + assert((*iter1)->IgnoreParenCasts()->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range1 = nice_source_range((*iter1)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter2 = iter1; + iter2++; + assert((*iter2)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range2 = nice_source_range((*iter2)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter3 = iter2; + iter3++; + assert((*iter3)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range3 = nice_source_range((*iter3)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + auto iter4 = iter3; + iter4++; + assert((*iter4)->IgnoreParenCasts()->getType().getTypePtrOrNull()); + auto arg_source_range4 = nice_source_range((*iter4)->IgnoreParenCasts()->getSourceRange(), Rewrite); + + std::string arg_source_text1; + std::string arg_source_text2; + std::string arg_source_text3; + std::string arg_source_text4; + if (arg_source_range1.isValid() && arg_source_range2.isValid() && arg_source_range3.isValid() && arg_source_range3.isValid() && arg_source_range4.isValid()) { + arg_source_text1 = Rewrite.getRewrittenText(arg_source_range1); + arg_source_text2 = Rewrite.getRewrittenText(arg_source_range2); + arg_source_text3 = Rewrite.getRewrittenText(arg_source_range3); + arg_source_text4 = Rewrite.getRewrittenText(arg_source_range4); + + QualType QT; + clang::SourceRange decl_source_range; + std::string variable_name; + const clang::DeclaratorDecl* DD = nullptr; + CArrayInferenceInfo res2; + + auto decl = DRE->getDecl(); + DD = dynamic_cast<const DeclaratorDecl*>(decl); + auto VD = dynamic_cast<const VarDecl*>(decl); + + const clang::FieldDecl* FD = nullptr; + if (nullptr != ME) { + auto member_decl = ME->getMemberDecl(); + FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); + } + if (nullptr != FD) { + DD = FD; + } else if (nullptr != VD) { + DD = VD; + } else { + int q = 7; + } + + if (nullptr != DD) { + decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + QT = DD->getType(); + auto qtype_str = QT.getAsString(); + variable_name = DD->getNameAsString(); + + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + return; + } + + res2 = infer_array_type_info_from_stmt(*(*(CE->arg_begin())), "memset/cpy target", (*this).m_state1, DD); + + if (res2.update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + } + + clang::QualType arg1_QT = (*iter1)->IgnoreParenCasts()->getType(); + if (nullptr != DD) { + arg1_QT = QT; + } + const clang::Type* arg1_TP = arg1_QT.getTypePtr(); + auto arg1_type_str = arg1_QT.getAsString(); + + std::string arg1_element_type_str; + if (arg1_TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(arg1_TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto type_str = element_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg1_element_type_str = type_str; + } + } else if (arg1_TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(arg1_TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto type_str = target_type.getAsString(); + if (("char" != type_str) && ("const char" != type_str)) { + arg1_element_type_str = type_str; + } + } + std::string ce_replacement_code; + if (("" != arg1_element_type_str) && ("void" != arg1_element_type_str) && ("const void" != arg1_element_type_str)) { + ce_replacement_code = "MSE_LH_FWRITE(" + arg_source_text1 + ", " + arg_source_text2 + + ", "+ arg_source_text3 + ", "+ arg_source_text4 + ")"; + } + + if (ConvertToSCPP && (CESR.isValid()) && ("" != ce_replacement_code)) { + auto cr_shptr = std::make_shared<CExprTextReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, res2.indirection_level), CE, ce_replacement_code); + if ((nullptr != res2.ddecl_conversion_state_ptr)) { + if (true || (*(res2.ddecl_conversion_state_ptr)).has_been_determined_to_be_an_array(res2.indirection_level)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } + } else { + (*cr_shptr).do_replacement(m_state1); + } + } else { + int q = 7; + } + + int q = 5; + } else { + int q = 5; + } + int q = 5; + } + } + + } + } + } + +private: + Rewriter &Rewrite; + CState1& m_state1; +}; + /**********************************************************************************************************************/ class MyASTConsumer : public ASTConsumer { public: MyASTConsumer(Rewriter &R) : HandlerForSSSNativePointer(R), HandlerForSSSArrayToPointerDecay(R, m_state1), HandlerForSSSVarDecl2(R, m_state1), HandlerForSSSPointerArithmetic2(R, m_state1), HandlerForSSSMalloc2(R, m_state1), - HandlerForSSSMallocInitializer2(R, m_state1), HandlerForSSSFree2(R, m_state1), HandlerForSSSSetToNull2(R, m_state1), - HandlerForSSSMemset(R, m_state1), HandlerForSSSMemcpy(R, m_state1), HandlerForSSSConditionalInitializer(R, m_state1), - HandlerForSSSAssignment(R, m_state1), HandlerForSSSParameterPassing(R, m_state1), HandlerForSSSReturnValue(R, m_state1) + HandlerForSSSMallocInitializer2(R, m_state1), HandlerForSSSNullInitializer(R, m_state1), HandlerForSSSFree2(R, m_state1), + HandlerForSSSSetToNull2(R, m_state1), HandlerForSSSCompareWithNull2(R, m_state1), HandlerForSSSMemset(R, m_state1), HandlerForSSSMemcpy(R, m_state1), + HandlerForSSSConditionalInitializer(R, m_state1), HandlerForSSSAssignment(R, m_state1), HandlerForSSSParameterPassing(R, m_state1), + HandlerForSSSReturnValue(R, m_state1), HandlerForSSSFRead(R, m_state1), HandlerForSSSFWrite(R, m_state1) { Matcher.addMatcher(varDecl(hasType(pointerType())).bind("mcsssnativepointer"), &HandlerForSSSNativePointer); @@ -4608,6 +5785,12 @@ public: ))).bind("mcsssmallocinitializer3") )).bind("mcsssmallocinitializer1"), &HandlerForSSSMallocInitializer2); + Matcher.addMatcher(declStmt(hasDescendant( + varDecl(hasInitializer(ignoringParenCasts( + expr().bind("mcsssnullinitializer2") + ))).bind("mcsssnullinitializer3") + )).bind("mcsssnullinitializer1"), &HandlerForSSSNullInitializer); + Matcher.addMatcher( callExpr(allOf( hasAnyArgument(ignoringParenCasts( @@ -4630,6 +5813,15 @@ public: hasLHS(expr(hasType(pointerType()))) )).bind("mcssssettonull1"), &HandlerForSSSSetToNull2); + Matcher.addMatcher(binaryOperator(allOf( + anyOf(hasOperatorName("=="), hasOperatorName("!=")), + hasLHS(anyOf( + ignoringParenCasts(declRefExpr().bind("mcssscomparewithnull3")), + ignoringParenCasts(expr(hasDescendant(declRefExpr().bind("mcssscomparewithnull3")))) + )), + hasLHS(expr(hasType(pointerType()))) + )).bind("mcssscomparewithnull1"), &HandlerForSSSCompareWithNull2); + Matcher.addMatcher( callExpr(allOf( hasAnyArgument( @@ -4666,8 +5858,12 @@ public: )).bind("mcsssconditionalinitializer1"), &HandlerForSSSConditionalInitializer); Matcher.addMatcher(binaryOperator(allOf( - hasOperatorName("="), - hasLHS(hasDescendant(declRefExpr().bind("mcsssassignment2"))), + anyOf(hasOperatorName("="), hasOperatorName("=="), hasOperatorName("!="), + hasOperatorName("<"), hasOperatorName(">"), hasOperatorName("<="), hasOperatorName(">=")), + hasLHS(anyOf( + hasDescendant(declRefExpr().bind("mcsssassignment2")), + declRefExpr().bind("mcsssassignment2") + )), hasRHS(anyOf( cStyleCastExpr(hasDescendant(declRefExpr().bind("mcsssassignment3"))).bind("mcsssassignment4"), expr(hasDescendant(declRefExpr().bind("mcsssassignment3"))) @@ -4698,6 +5894,32 @@ public: hasDescendant(declRefExpr().bind("mcsssreturnvalue3")) )).bind("mcsssreturnvalue2"), &HandlerForSSSReturnValue); + Matcher.addMatcher( + callExpr(allOf( + hasAnyArgument( + ignoringParenCasts(expr(anyOf( + memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfread2")))).bind("mcsssfread3"), + declRefExpr().bind("mcsssfread2"), + hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfread2")))).bind("mcsssfread3")), + hasDescendant(declRefExpr().bind("mcsssfread2")) + )))), + argumentCountIs(4), + hasAnyArgument(hasType(pointerType())) + )).bind("mcsssfread1"), &HandlerForSSSFRead); + + Matcher.addMatcher( + callExpr(allOf( + hasAnyArgument( + ignoringParenCasts(expr(anyOf( + memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfwrite2")))).bind("mcsssfwrite3"), + declRefExpr().bind("mcsssfwrite2"), + hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfwrite2")))).bind("mcsssfwrite3")), + hasDescendant(declRefExpr().bind("mcsssfwrite2")) + )))), + argumentCountIs(4), + hasAnyArgument(hasType(pointerType())) + )).bind("mcsssfwrite1"), &HandlerForSSSFWrite); + } void HandleTranslationUnit(ASTContext &Context) override @@ -4715,14 +5937,18 @@ private: MCSSSPointerArithmetic2 HandlerForSSSPointerArithmetic2; MCSSSMalloc2 HandlerForSSSMalloc2; MCSSSMallocInitializer2 HandlerForSSSMallocInitializer2; + MCSSSNullInitializer HandlerForSSSNullInitializer; MCSSSFree2 HandlerForSSSFree2; MCSSSSetToNull2 HandlerForSSSSetToNull2; + MCSSSCompareWithNull2 HandlerForSSSCompareWithNull2; MCSSSMemset HandlerForSSSMemset; MCSSSMemcpy HandlerForSSSMemcpy; MCSSSConditionalInitializer HandlerForSSSConditionalInitializer; MCSSSAssignment HandlerForSSSAssignment; MCSSSParameterPassing HandlerForSSSParameterPassing; MCSSSReturnValue HandlerForSSSReturnValue; + MCSSSFRead HandlerForSSSFRead; + MCSSSFWrite HandlerForSSSFWrite; MatchFinder Matcher; }; |