diff options
-rw-r--r-- | safercpp/safercpp-arr.cpp | 970 |
1 files changed, 794 insertions, 176 deletions
diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index f02b9ed..c057188 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -294,11 +294,15 @@ public: class CIndirectionState { public: - CIndirectionState(std::string original, std::string current) - : m_original(original), m_current(current) {} + 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 CIndirectionState& src) = default; std::string m_original; std::string m_current; + + bool m_current_is_function_type = false; + std::vector<std::string> m_params_original; + std::vector<std::string> m_params_current; }; class CIndirectionStateStack : public std::vector<CIndirectionState> {}; @@ -307,7 +311,42 @@ class CIndirectionStateStack : public std::vector<CIndirectionState> {}; * whether each level of indirection (if any) of the type is of the pointer or the array variety. Pointers * 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. */ -const clang::QualType& populateQTypeIndirectionStack(CIndirectionStateStack& stack, const clang::QualType& qtype, int depth = 0) { +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(); + 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 (FNQT) { + auto num_params = FNQT->getNumParams(); + } else { + assert(false); + } + } else { + assert(false); + } + int q = 5; + } + + if (llvm::isa<const clang::FunctionType>(qtype)) { + auto FNQT = llvm::cast<const clang::FunctionType>(qtype); + if (FNQT) { + current_is_function_type = true; + qtype = FNQT->getReturnType(); + } else { + assert(false); + } + } else { + int q = 5; + } + } + std::string qtype_str = qtype.getAsString(); auto TP = qtype.getTypePtr(); @@ -428,6 +467,8 @@ const clang::Expr* populateStmtIndirectionStack(std::vector<std::string>& stack, } 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) { @@ -553,6 +594,10 @@ class CDDeclConversionState { public: CDDeclConversionState(const clang::DeclaratorDecl& ddecl) : m_ddecl_cptr(&ddecl) { QualType QT = ddecl.getType(); + assert(ddecl.isFunctionOrFunctionTemplate() == QT->isFunctionType()); + if (QT->isFunctionType()) { + m_is_a_function = true; + } m_original_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); m_current_direct_qtype = m_original_direct_qtype; //std::reverse(m_indirection_state_stack.begin(), m_indirection_state_stack.end()); @@ -569,6 +614,17 @@ public: } return retval; } + bool has_been_determined_to_be_a_dynamic_array(size_t indirection_level = 0) const { + bool retval = false; + assert((0 == indirection_level) || (m_indirection_state_stack.size() > indirection_level)); + if (m_indirection_state_stack.size() > indirection_level) { + const auto& current_state = m_indirection_state_stack[indirection_level].m_current; + if ("dynamic array" == current_state) { + retval = true; + } + } + return retval; + } const DeclaratorDecl* m_ddecl_cptr = nullptr; CIndirectionStateStack m_indirection_state_stack; clang::QualType m_original_direct_qtype; @@ -578,11 +634,19 @@ public: std::string m_original_initialization_expr_str; bool m_original_source_text_has_been_noted = false; std::string m_original_source_text_str; + + bool m_is_a_function = false; + std::vector<const clang::ParmVarDecl*> m_original_function_parameter_decl_cptrs; + std::string m_function_return_type_original_source_text_str; }; class CDDeclConversionStateMap : public std::map<const clang::DeclaratorDecl*, CDDeclConversionState> { public: std::pair<iterator, bool> insert(const clang::DeclaratorDecl& ddecl) { + std::string variable_name = ddecl.getNameAsString(); + if ("bitlen" == variable_name) { + int q = 5; + } value_type item(&ddecl, CDDeclConversionState(ddecl)); return std::map<const clang::DeclaratorDecl*, CDDeclConversionState>::insert(item); } @@ -856,6 +920,18 @@ public: const CDDeclIndirection m_ddecl_indirection2; }; +class CSameTypeArray2ReplacementAction : public CArray2ReplacementAction { +public: + CSameTypeArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const CDDeclIndirection& ddecl_indirection2) : + CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_ddecl_indirection2(ddecl_indirection2) {} + virtual ~CSameTypeArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const CDDeclIndirection m_ddecl_indirection2; +}; + class CDDecl2ReplacementActionMap : public std::multimap<CDDeclIndirection, std::shared_ptr<CDDecl2ReplacementAction>> { public: typedef std::multimap<CDDeclIndirection, std::shared_ptr<CDDecl2ReplacementAction>> base_class; @@ -988,7 +1064,7 @@ class CState1 { public: /* This container holds (potential) actions that are meant to be executed if/when * their corresponding item is determined to be a dynamic array. */ - CDynamicArray2ReplacementActionMap m_dynamic_array2_contingent_replacement_map; + CArray2ReplacementActionMap m_dynamic_array2_contingent_replacement_map; /* This container holds (potential) actions that are meant to be executed if/when * their corresponding item is determined to be an array (dynamic or otherwise). */ @@ -1008,7 +1084,9 @@ public: std::string m_replacement_code; std::string m_action_species; }; -static CDeclarationReplacementCodeItem generate_declaration_replacement_code(const DeclaratorDecl* DD, Rewriter &Rewrite, CDDeclConversionStateMap& ddecl_conversion_state_map, std::string options_str = "") { + +static CDeclarationReplacementCodeItem generate_declaration_replacement_code(const DeclaratorDecl* DD, + Rewriter &Rewrite, CDDeclConversionStateMap& ddecl_conversion_state_map, std::string options_str = "") { CDeclarationReplacementCodeItem retval; if (!DD) { @@ -1024,6 +1102,18 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con auto& ddcs_ref = (*ddcs_map_iter).second; QualType QT = DD->getType(); + + const clang::FunctionDecl* FND = nullptr; + bool type_is_function_type = false; + assert(DD->isFunctionOrFunctionTemplate() == QT->isFunctionType()); + if (QT->isFunctionType()) { + FND = dynamic_cast<const clang::FunctionDecl*>(DD); + if (FND) { + type_is_function_type = true; + QT = FND->getReturnType(); + } + } + const clang::Type* TP = QT.getTypePtr(); auto qtype_str = QT.getAsString(); auto direct_qtype_str = ddcs_ref.m_current_direct_qtype.getAsString(); @@ -1054,10 +1144,24 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } if ("" == variable_name) { int q = 7; + } else if ("LODEPNG_VERSION_STRING" == 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; } @@ -1169,7 +1273,6 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con is_function_pointer = true; } if ("inferred 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. */ @@ -1177,6 +1280,7 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con 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"; @@ -1310,21 +1414,30 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con changed_from_original = true; } - if (changed_from_original) { - if (is_extern) { - if ("" == ddcs_ref.m_original_initialization_expr_str) { - replacement_code += "extern "; - } - } else if (is_static) { - replacement_code += "static "; + if (FND) { + assert(type_is_function_type); + if (changed_from_original) { + replacement_code += prefix_str + non_const_direct_qtype_str + suffix_str; + } else { + replacement_code = ddcs_ref.m_function_return_type_original_source_text_str; } - replacement_code += prefix_str + direct_qtype_str + suffix_str; - replacement_code += " "; - replacement_code += variable_name; - - replacement_code += initializer_append_str; } else { - replacement_code = ddcs_ref.m_original_source_text_str; + if (changed_from_original) { + if (is_extern) { + if ("" == ddcs_ref.m_original_initialization_expr_str) { + replacement_code += "extern "; + } + } else if (is_static) { + replacement_code += "static "; + } + replacement_code += prefix_str + direct_qtype_str + suffix_str; + replacement_code += " "; + replacement_code += variable_name; + + replacement_code += initializer_append_str; + } else { + replacement_code = ddcs_ref.m_original_source_text_str; + } } retval.m_replacement_code = replacement_code; @@ -1355,52 +1468,66 @@ static void update_declaration(const DeclaratorDecl& ddecl, Rewriter &Rewrite, C return; } + assert(ddecl.isFunctionOrFunctionTemplate() == QT->isFunctionType()); if ((TP->isFunctionType()) || (false)) { - /* We don't handle function declarations yet. */ - return; - } + const clang::FunctionDecl* FND = dynamic_cast<const clang::FunctionDecl*>(DD); + if (FND) { + auto return_type_source_range = nice_source_range(FND->getReturnTypeSourceRange(), Rewrite); + if (!(return_type_source_range.isValid())) { + return; + } + auto res = generate_declaration_replacement_code(&ddecl, Rewrite, state1.m_ddecl_conversion_state_map, options_str); - /* There may be multiple declarations in the same declaration statement. Replacing - * one of them requires replacing all of them together. */ - auto ddecls = IndividualDeclaratorDecls(DD, Rewrite); - if ((1 <= ddecls.size())/* && (ddecls.back() == DD)*/) { - if (2 <= ddecls.size()) { - int q = 5; - } - std::vector<std::string> action_species_list; - std::string replacement_code; - for (const auto& ddecl_cref : ddecls) { - auto res = generate_declaration_replacement_code(ddecl_cref, Rewrite, state1.m_ddecl_conversion_state_map, options_str); - action_species_list.push_back(res.m_action_species); - replacement_code += res.m_replacement_code; - replacement_code += "; \n"; - } - if (replacement_code.size() >= 3) { - replacement_code = replacement_code.substr(0, replacement_code.size() - 3); + if (ConvertToSCPP && return_type_source_range.isValid() && (1 <= res.m_replacement_code.size())) { + auto res2 = Rewrite.ReplaceText(return_type_source_range, res.m_replacement_code); + } else { + int q = 7; + } } + } else { - /* (Only) the source range of the last individual declaration in the declaration statement - * should encompass the whole statement. */ - auto last_ddecl = ddecls.back(); - auto last_decl_source_range = nice_source_range(last_ddecl->getSourceRange(), Rewrite); + /* There may be multiple declarations in the same declaration statement. Replacing + * one of them requires replacing all of them together. */ + auto ddecls = IndividualDeclaratorDecls(DD, Rewrite); + if ((1 <= ddecls.size())/* && (ddecls.back() == DD)*/) { + if (2 <= ddecls.size()) { + int q = 5; + } + std::vector<std::string> action_species_list; + std::string replacement_code; + for (const auto& ddecl_cref : ddecls) { + auto res = generate_declaration_replacement_code(ddecl_cref, Rewrite, state1.m_ddecl_conversion_state_map, options_str); + action_species_list.push_back(res.m_action_species); + replacement_code += res.m_replacement_code; + replacement_code += "; \n"; + } + if (replacement_code.size() >= 3) { + replacement_code = replacement_code.substr(0, replacement_code.size() - 3); + } + + /* (Only) the source range of the last individual declaration in the declaration statement + * should encompass the whole statement. */ + auto last_ddecl = ddecls.back(); + auto last_decl_source_range = nice_source_range(last_ddecl->getSourceRange(), Rewrite); - std::string last_decl_source_text; - if (last_decl_source_range.isValid()) { - last_decl_source_text = Rewrite.getRewrittenText(last_decl_source_range); - if ("" == last_decl_source_text) { + std::string last_decl_source_text; + if (last_decl_source_range.isValid()) { + last_decl_source_text = Rewrite.getRewrittenText(last_decl_source_range); + if ("" == last_decl_source_text) { + return; + } + } else { return; } - } else { - return; - } - if (ConvertToSCPP && last_decl_source_range.isValid() && (3 <= replacement_code.size())) { - auto res = Rewrite.ReplaceText(last_decl_source_range, replacement_code); + if (ConvertToSCPP && last_decl_source_range.isValid() && (3 <= replacement_code.size())) { + auto res2 = Rewrite.ReplaceText(last_decl_source_range, replacement_code); + } else { + int q = 7; + } } else { int q = 7; } - } else { - int q = 7; } } @@ -1580,24 +1707,27 @@ void CMemcpyArray2ReplacementAction::do_replacement(CState1& state1) const { const CallExpr* CE = m_CE; const DeclaratorDecl* DD = m_DD; - if ((CE != nullptr) && (DD != nullptr)) + if (CE != nullptr) { auto CESR = nice_source_range(CE->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() && (CESR.isValid())) { + if (ConvertToSCPP && (CESR.isValid())) { + auto res2 = Rewrite.ReplaceText(CESR, m_ce_replacement_code); - update_declaration(*DD, Rewrite, state1); + if (DD != nullptr) { + 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; + } - auto res2 = Rewrite.ReplaceText(CESR, m_ce_replacement_code); - int q = 3; + if (decl_source_range.isValid()) { + update_declaration(*DD, Rewrite, state1); + } + } } else { int q = 7; } @@ -1616,11 +1746,11 @@ void CAssignmentTargetConstrainsSourceArray2ReplacementAction::do_replacement(CS if (ddcs_ref.m_indirection_state_stack.size() >= m_ddecl_indirection2.m_indirection_level) { if ("native pointer" == ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current) { ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current = "inferred array"; - update_declaration_flag = true; + update_declaration_flag |= true; state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current) { ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current = "dynamic array"; - update_declaration_flag = true; + 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 { @@ -1647,11 +1777,11 @@ void CAssignmentSourceConstrainsTargetArray2ReplacementAction::do_replacement(CS if (ddcs_ref.m_indirection_state_stack.size() >= m_ddecl_indirection2.m_indirection_level) { if ("native pointer" == ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current) { ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current = "inferred array"; - update_declaration_flag = true; + update_declaration_flag |= true; state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current) { ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current = "dynamic array"; - update_declaration_flag = true; + 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 { @@ -1666,6 +1796,139 @@ void CAssignmentSourceConstrainsTargetArray2ReplacementAction::do_replacement(CS } } +void CSameTypeArray2ReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + + auto lhs_res1 = state1.m_ddecl_conversion_state_map.insert(*(m_ddecl_indirection2.m_ddecl_cptr)); + auto lhs_ddcs_map_iter = lhs_res1.first; + auto& lhs_ddcs_ref = (*lhs_ddcs_map_iter).second; + bool lhs_update_declaration_flag = lhs_res1.second; + + auto rhs_res1 = state1.m_ddecl_conversion_state_map.insert(*(m_ddecl_indirection.m_ddecl_cptr)); + auto rhs_ddcs_map_iter = rhs_res1.first; + auto& rhs_ddcs_ref = (*rhs_ddcs_map_iter).second; + bool rhs_update_declaration_flag = rhs_res1.second; + + if ((lhs_ddcs_ref.m_indirection_state_stack.size() >= m_ddecl_indirection2.m_indirection_level) && + (rhs_ddcs_ref.m_indirection_state_stack.size() >= m_ddecl_indirection.m_indirection_level)){ + auto& lhs_current_ref = lhs_ddcs_ref.m_indirection_state_stack[m_ddecl_indirection2.m_indirection_level].m_current; + auto& rhs_current_ref = rhs_ddcs_ref.m_indirection_state_stack[m_ddecl_indirection.m_indirection_level].m_current; + + if ("native pointer" == lhs_current_ref) { + if ("native pointer" == rhs_current_ref) { + } else if ("malloc target" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_update_declaration_flag |= true; + } else if ("inferred array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + } else if ("dynamic array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_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 if ("native array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + } + } else if ("malloc target" == lhs_current_ref) { + if ("native pointer" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + } else if ("malloc target" == rhs_current_ref) { + } else if ("inferred array" == rhs_current_ref) { + lhs_current_ref = "dynamic array"; + lhs_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); + + rhs_current_ref = "dynamic array"; + rhs_update_declaration_flag |= true; + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("dynamic array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_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 if ("native array" == rhs_current_ref) { + // could be a problem + int q = 7; + } + } else if ("inferred array" == lhs_current_ref) { + if ("native pointer" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("malloc target" == rhs_current_ref) { + lhs_current_ref = "dynamic array"; + lhs_update_declaration_flag |= true; + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + + rhs_current_ref = "dynamic array"; + rhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("inferred array" == rhs_current_ref) { + } else if ("dynamic array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_update_declaration_flag |= true; + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + } else if ("native array" == rhs_current_ref) { + lhs_current_ref = rhs_current_ref; + lhs_update_declaration_flag |= true; + } + } else if ("dynamic array" == lhs_current_ref) { + if ("native pointer" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("malloc target" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("inferred array" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("dynamic array" == rhs_current_ref) { + } else if ("native array" == rhs_current_ref) { + // could be a problem + int q = 7; + } + } else if ("native array" == lhs_current_ref) { + if ("native pointer" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection); + } else if ("malloc target" == rhs_current_ref) { + // could be a problem + int q = 7; + } else if ("inferred array" == rhs_current_ref) { + rhs_current_ref = lhs_current_ref; + rhs_update_declaration_flag |= true; + } else if ("dynamic array" == rhs_current_ref) { + // could be a problem + int q = 7; + } else if ("native array" == rhs_current_ref) { + } + } + } else { + int q = 7; + } + + if (lhs_update_declaration_flag) { + update_declaration(*(m_ddecl_indirection2.m_ddecl_cptr), Rewrite, state1); + } + if (rhs_update_declaration_flag) { + update_declaration(*(m_ddecl_indirection.m_ddecl_cptr), Rewrite, state1); + } +} + void CConditionalOperatorReconciliation2ReplacementAction::do_replacement(CState1& state1) const { const clang::ConditionalOperator* CO = m_CO; const Expr* COND = nullptr; @@ -1820,6 +2083,104 @@ void CConditionalOperatorReconciliation2ReplacementAction::do_replacement(CState } +struct CLeadingAddressofOperatorInfo { + bool leading_addressof_operator_detected = false; + const clang::Expr* without_leading_addressof_operator_expr_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; + + 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) { @@ -1833,7 +2194,6 @@ struct CArrayInferenceInfo { size_t indirection_level = 0; const DeclaratorDecl* ddecl_cptr = nullptr; CDDeclConversionState* ddecl_conversion_state_ptr = nullptr; - bool ddecl_needs_update_flag = false; const clang::Expr* declaration_expr_cptr = nullptr; }; CArrayInferenceInfo infer_array_type_info_from_stmt_indirection_stack(CDDeclConversionState& ddcs_ref, @@ -1908,6 +2268,7 @@ CArrayInferenceInfo infer_array_type_info_from_stmt(const clang::Stmt& 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; @@ -1931,23 +2292,23 @@ CArrayInferenceInfo infer_array_type_info_from_stmt(const clang::Stmt& stmt_cref auto expr2_type_str = expr2_QT.getAsString(); std::string expr2_variable_name = expr2_DD->getNameAsString(); - if (nullptr == DD) { - DD = expr2_DD; + if (nullptr == l_DD) { + l_DD = expr2_DD; } - auto res1 = state1_ref.m_ddecl_conversion_state_map.insert(*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 = (*DD).getType(); - std::string variable_name = (*DD).getNameAsString(); + 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_needs_update_flag = update_declaration_flag; } retval.ddecl_cptr = expr2_DD; } @@ -3204,11 +3565,10 @@ public: arg_source_text3 = Rewrite.getRewrittenText(arg_source_range3); QualType QT; - std::string element_type_str; clang::SourceRange decl_source_range; std::string variable_name; - std::string ce_replacement_code; const clang::DeclaratorDecl* DD = nullptr; + CArrayInferenceInfo res2; auto decl = DRE->getDecl(); DD = dynamic_cast<const DeclaratorDecl*>(decl); @@ -3228,7 +3588,7 @@ public: } if (nullptr != DD) { - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + 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()) { @@ -3248,12 +3608,63 @@ public: return; } - auto res2 = infer_array_type_info_from_stmt(*(*(CE->arg_begin())), "memset/cpy target", (*this).m_state1, DD); + 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)->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 elementSplitQualType = element_type.split(); + auto type_str = clang::QualType::getAsString(elementSplitQualType); + 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 splitQualType = target_type.split(); + auto type_str = clang::QualType::getAsString(splitQualType); + 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 = "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 (ConvertToSCPP && (CESR.isValid()) && ("" != ce_replacement_code)) { + auto cr_shptr = std::make_shared<CMemcpyArray2ReplacementAction>(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; @@ -3358,6 +3769,13 @@ public: bool lhs_qualifies = false; bool rhs_qualifies = false; + if (lhs_res2.ddecl_cptr && lhs_res2.update_declaration_flag) { + update_declaration(*(lhs_res2.ddecl_cptr), Rewrite, m_state1); + } + if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { + update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); + } + { auto& res2 = lhs_res2; if (res2.ddecl_cptr && res2.declaration_expr_cptr) { @@ -3552,6 +3970,13 @@ public: bool rhs_is_an_indirect_type = is_an_indirect_type(RHS->getType()); assert(lhs_is_an_indirect_type == rhs_is_an_indirect_type); + if (lhs_res2.ddecl_cptr && lhs_res2.update_declaration_flag) { + update_declaration(*(lhs_res2.ddecl_cptr), Rewrite, m_state1); + } + if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { + 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 = RHS->getType(); @@ -3677,120 +4102,305 @@ public: int q = 5; } - auto function_decl = CE->getDirectCallee(); + auto function_decl1 = CE->getDirectCallee(); auto num_args = CE->getNumArgs(); - if (function_decl) { - std::string function_name = function_decl->getNameAsString(); - if (string_begins_with(function_name, "__builtin_")) { + if (function_decl1) { + std::string function_name = function_decl1->getNameAsString(); + auto lc_function_name = tolowerstr(function_name); + + static const std::string free_str = "free"; + bool ends_with_free = ((lc_function_name.size() >= free_str.size()) + && (0 == lc_function_name.compare(lc_function_name.size() - free_str.size(), free_str.size(), free_str))); + + static const std::string alloc_str = "alloc"; + static const std::string realloc_str = "realloc"; + 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 begins_with__builtin_ = string_begins_with(function_name, "__builtin_"); + bool is_memcpy = ("memcpy" == function_name); + bool is_memset = ("memset" == function_name); + + if (ends_with_free || ends_with_alloc || ends_with_realloc || is_memcpy || is_memset || begins_with__builtin_) { + return void(); + } + if ("lodepng_deflate" == function_name) { + int q = 5; + } + if ("deflate" == function_name) { int q = 5; } - auto param_iter = function_decl->param_begin(); - auto arg_iter = CE->arg_begin(); - for (; (arg_iter != CE->arg_end()) && (param_iter != function_decl->param_end()); - arg_iter++, param_iter++) { - assert((*arg_iter)->getType().getTypePtrOrNull()); - 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 param_VD = (*param_iter)->getDefinition(); - auto arg_EX = (*arg_iter); - - if ((nullptr != param_VD) && (nullptr != arg_EX) && arg_source_range.isValid()) { - bool lhs_is_an_indirect_type = is_an_indirect_type(param_VD->getType()); - auto rhs_res2 = infer_array_type_info_from_stmt(*arg_EX, "", (*this).m_state1); - bool rhs_is_an_indirect_type = is_an_indirect_type(arg_EX->getType()); - assert(lhs_is_an_indirect_type == rhs_is_an_indirect_type); - - 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); - } + auto function_decls_range = function_decl1->redecls(); + + for (const auto& function_decl : function_decls_range) { + auto param_iter = function_decl->param_begin(); + auto arg_iter = CE->arg_begin(); + for (; (arg_iter != CE->arg_end()) && (param_iter != function_decl->param_end()); + arg_iter++, param_iter++) { + assert((*arg_iter)->getType().getTypePtrOrNull()); + 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); + } - update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); + auto param_VD = (*param_iter)->getDefinition(); + auto arg_EX = (*arg_iter); + + if ((nullptr != param_VD) && (nullptr != arg_EX) && arg_source_range.isValid()) { + bool lhs_is_an_indirect_type = is_an_indirect_type(param_VD->getType()); + bool rhs_is_an_indirect_type = is_an_indirect_type(arg_EX->getType()); + assert(lhs_is_an_indirect_type == rhs_is_an_indirect_type); + + 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) { + arg_EX = rhs_res3.without_leading_addressof_operator_expr_cptr; + lhs_indirection_level_adjustment = 1; + } + auto rhs_res2 = infer_array_type_info_from_stmt(*arg_EX, "", (*this).m_state1); + + if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { + 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 { - if (ConvertToSCPP) { - //(*rhs_res2.ddecl_conversion_state_ptr).m_current_direct_qtype = direct_rhs_qtype; - } + int q = 7; } } else { int q = 7; } - } else { - int q = 7; } - } - auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*param_VD); - auto ddcs_map_iter = res1.first; - auto& ddcs_ref = (*ddcs_map_iter).second; - bool update_declaration_flag = res1.second; - - if (ConvertToSCPP && (rhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { - for (size_t i = 0; (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) { - { - /* 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(*param_VD, i), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); - - if (ddcs_ref.has_been_determined_to_be_an_array(i)) { - (*cr_shptr).do_replacement(m_state1); - } else { - m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); - } + auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*param_VD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; + + if (ddcs_ref.m_ddecl_cptr && update_declaration_flag) { + update_declaration(*(ddcs_ref.m_ddecl_cptr), Rewrite, m_state1); + } + + if (ConvertToSCPP && (rhs_res2.ddecl_conversion_state_ptr) && lhs_is_an_indirect_type) { + 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); } - { - /* 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(*param_VD, i)); - 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); - } else { - m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + 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. */ + std::shared_ptr<CArray2ReplacementAction> cr_shptr; + if (1 > (i + lhs_indirection_level_adjustment)) { + cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*param_VD, i + lhs_indirection_level_adjustment), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i)); + } else { + cr_shptr = std::make_shared<CSameTypeArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*param_VD, 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(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. */ + 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(*param_VD, i + lhs_indirection_level_adjustment)); + } else { + /* This is actually redundant since we decided to make CSameTypeArray2ReplacementAction + * apply the constraint in both directions already. But the redundancy doesn't hurt. */ + cr_shptr = std::make_shared<CSameTypeArray2ReplacementAction>(Rewrite, MR, + CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level + i), CDDeclIndirection(*param_VD, 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); + } } } } + } else { + int q = 5; } - } else { int q = 5; } - int q = 5; + } + + } + } + } + +private: + Rewriter &Rewrite; + CState1& m_state1; +}; + +class MCSSSReturnValue : public MatchFinder::MatchCallback +{ +public: + MCSSSReturnValue (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} + + virtual void run(const MatchFinder::MatchResult &MR) + { + const clang::FunctionDecl* FND = MR.Nodes.getNodeAs<clang::FunctionDecl>("mcsssreturnvalue1"); + const clang::ReturnStmt* RS = MR.Nodes.getNodeAs<clang::ReturnStmt>("mcsssreturnvalue2"); + const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssreturnvalue3"); + + if ((FND != nullptr) && (DRE != nullptr) && (RS != nullptr)) + { + auto FNDSR = nice_source_range(FND->getSourceRange(), Rewrite); + SourceLocation FNDSL = FNDSR.getBegin(); + SourceLocation FNDSLE = FNDSR.getEnd(); + + ASTContext *const ASTC = MR.Context; + FullSourceLoc FFNDSL = ASTC->getFullLoc(FNDSL); + + SourceManager &SM = ASTC->getSourceManager(); + + auto source_location_str = FNDSL.printToString(*MR.SourceManager); + std::string source_text; + if (FNDSL.isValid() && FNDSLE.isValid()) { + source_text = Rewrite.getRewrittenText(SourceRange(FNDSL, FNDSLE)); + } else { + return; + } + + if (filtered_out_by_location(MR, FNDSL)) { + return void(); + } + + auto function_decl1 = FND; + auto num_params = FND->getNumParams(); + if (function_decl1) { + std::string function_name = function_decl1->getNameAsString(); + auto lc_function_name = tolowerstr(function_name); + + static const std::string free_str = "free"; + bool ends_with_free = ((lc_function_name.size() >= free_str.size()) + && (0 == lc_function_name.compare(lc_function_name.size() - free_str.size(), free_str.size(), free_str))); + + static const std::string alloc_str = "alloc"; + static const std::string realloc_str = "realloc"; + 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 begins_with__builtin_ = string_begins_with(function_name, "__builtin_"); + + if (ends_with_free || ends_with_alloc || ends_with_realloc || begins_with__builtin_) { + 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()); + if (rhs_res2.ddecl_cptr && rhs_res2.update_declaration_flag) { + update_declaration(*(rhs_res2.ddecl_cptr), Rewrite, m_state1); + } + + auto function_decls_range = function_decl1->redecls(); + for (const auto& function_decl : function_decls_range) { + auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*function_decl); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; + bool lhs_is_an_indirect_type = is_an_indirect_type(function_decl->getReturnType()); + assert(lhs_is_an_indirect_type == rhs_is_an_indirect_type); + + if (ddcs_ref.m_ddecl_cptr && update_declaration_flag) { + update_declaration(*(ddcs_ref.m_ddecl_cptr), Rewrite, m_state1); + } + + 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) { + { + /* 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)); + + if (ddcs_ref.has_been_determined_to_be_an_array(0 + i)) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_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)); + + 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); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } + } + } + } } } @@ -3810,7 +4420,7 @@ public: 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) + HandlerForSSSAssignment(R, m_state1), HandlerForSSSParameterPassing(R, m_state1), HandlerForSSSReturnValue(R, m_state1) { Matcher.addMatcher(varDecl(hasType(pointerType())).bind("mcsssnativepointer"), &HandlerForSSSNativePointer); @@ -3935,11 +4545,13 @@ public: hasAnyArgument(anyOf( cStyleCastExpr(anyOf( memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssparameterpassing2")))).bind("mcsssparameterpassing3"), + declRefExpr().bind("mcsssparameterpassing2"), hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssparameterpassing2")))).bind("mcsssparameterpassing3")), hasDescendant(declRefExpr().bind("mcsssparameterpassing2")) )).bind("mcsssparameterpassing4"), expr(anyOf( memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssparameterpassing2")))).bind("mcsssparameterpassing3"), + declRefExpr().bind("mcsssparameterpassing2"), hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssparameterpassing2")))).bind("mcsssparameterpassing3")), hasDescendant(declRefExpr().bind("mcsssparameterpassing2")) )) @@ -3947,6 +4559,11 @@ public: hasAnyArgument(hasType(pointerType())) )).bind("mcsssparameterpassing1"), &HandlerForSSSParameterPassing); + Matcher.addMatcher(returnStmt(allOf( + hasAncestor(functionDecl().bind("mcsssreturnvalue1")), + hasDescendant(declRefExpr().bind("mcsssreturnvalue3")) + )).bind("mcsssreturnvalue2"), &HandlerForSSSReturnValue); + } void HandleTranslationUnit(ASTContext &Context) override @@ -3971,6 +4588,7 @@ private: MCSSSConditionalInitializer HandlerForSSSConditionalInitializer; MCSSSAssignment HandlerForSSSAssignment; MCSSSParameterPassing HandlerForSSSParameterPassing; + MCSSSReturnValue HandlerForSSSReturnValue; MatchFinder Matcher; }; |