diff options
author | user1 <user1@ubuntu> | 2017-04-21 16:13:32 +0000 |
---|---|---|
committer | user1 <user1@ubuntu> | 2017-04-21 16:13:32 +0000 |
commit | ce7141d73cef8142becf46d6e157a4bd40dfd29b (patch) | |
tree | dd430ef6793a7e271215b58c34c55aea4465eb75 /safercpp | |
parent | Merge branch 'master' of https://github.com/bloodstalker/mutator (diff) | |
download | mutator-ce7141d73cef8142becf46d6e157a4bd40dfd29b.tar.gz mutator-ce7141d73cef8142becf46d6e157a4bd40dfd29b.zip |
added handling of conditional initializers
Diffstat (limited to 'safercpp')
-rw-r--r-- | safercpp/safercpp-arr.cpp | 984 |
1 files changed, 646 insertions, 338 deletions
diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index 28419a1..750d393 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -214,14 +214,6 @@ static std::vector<std::string> f_declared_object_strings(const std::string& dec return retval; } -class CState1; - -class CReplacementAction { -public: - virtual ~CReplacementAction() {} - virtual void do_replacement(CState1& state1) const = 0; -}; - std::string tolowerstr(const std::string& a) { std::string retval; for (const auto& ch : a) { @@ -230,6 +222,10 @@ std::string tolowerstr(const std::string& a) { return retval; } +bool string_begins_with(const std::string& s1, const std::string& prefix) { + return (0 == s1.compare(0, prefix.length(), prefix)); +} + /* This function returns a list of individual declarations contained in the same declaration statement * as the given declaration. (eg.: "int a, b = 3, *c;" ) */ static std::vector<const DeclaratorDecl*> IndividualDeclaratorDecls(const DeclaratorDecl* DD, Rewriter &Rewrite) { @@ -295,197 +291,6 @@ public: size_t m_indirection_level = 0; }; -class CDDecl2ReplacementAction : public CReplacementAction { -public: - CDDecl2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, - const CDDeclIndirection& ddecl_indirection) : m_Rewrite(Rewrite), m_MR(MR), m_ddecl_indirection(ddecl_indirection) {} - virtual ~CDDecl2ReplacementAction() {} - - virtual void do_replacement(CState1& state1) const = 0; - virtual const clang::DeclaratorDecl* get_ddecl_cptr() const { return m_ddecl_indirection.m_ddecl_cptr; } - virtual const CDDeclIndirection& ddecl_indirection_cref() const { return m_ddecl_indirection; } - - clang::SourceRange source_range() { - clang::SourceRange retval = m_ddecl_indirection.m_ddecl_cptr->getSourceRange(); - return retval; - } - clang::SourceLocation start_location() { - clang::SourceLocation retval = source_range().getBegin(); - return retval; - } - std::string get_var_name() { - std::string retval = m_ddecl_indirection.m_ddecl_cptr->getNameAsString(); - return retval; - } - - Rewriter& m_Rewrite; - const MatchFinder::MatchResult m_MR; - CDDeclIndirection m_ddecl_indirection; -}; - -class CArray2ReplacementAction : public CDDecl2ReplacementAction { -public: - using CDDecl2ReplacementAction::CDDecl2ReplacementAction; - virtual ~CArray2ReplacementAction() {} -}; - -class CMemsetArray2ReplacementAction : public CArray2ReplacementAction { -public: - CMemsetArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, - const CallExpr* CE, const std::string& ce_replacement_code) : - CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), - m_ce_replacement_code(ce_replacement_code) {} - virtual ~CMemsetArray2ReplacementAction() {} - - virtual void do_replacement(CState1& state1) const; - - const CallExpr* m_CE = nullptr; - //const DeclRefExpr* m_DRE = nullptr; - //const MemberExpr* m_ME = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_ce_replacement_code; -}; - -class CMemcpyArray2ReplacementAction : public CArray2ReplacementAction { -public: - CMemcpyArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, - const CallExpr* CE, const std::string& ce_replacement_code) : - CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), - m_ce_replacement_code(ce_replacement_code) {} - virtual ~CMemcpyArray2ReplacementAction() {} - - virtual void do_replacement(CState1& state1) const; - - const CallExpr* m_CE = nullptr; - //const DeclRefExpr* m_DRE = nullptr; - //const MemberExpr* m_ME = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_ce_replacement_code; -}; - -class CAssignedFromArray2ReplacementAction : public CArray2ReplacementAction { -public: - CAssignedFromArray2ReplacementAction(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 ~CAssignedFromArray2ReplacementAction() {} - - 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; - iterator insert( const std::shared_ptr<CDDecl2ReplacementAction>& cr_shptr ) { - iterator retval(end()); - if (!cr_shptr) { assert(false); } else { - value_type val((*cr_shptr).ddecl_indirection_cref(), cr_shptr); - retval = base_class::insert(val); - } - return retval; - } - void do_and_dispose_matching_replacements(CState1& state1, const CDDeclIndirection& ddecl_indirection) { - /* The base class map may be modified during loop iterations. Maybe. */ - auto iter = base_class::find(ddecl_indirection); - while (base_class::end() != iter) { - (*((*iter).second)).do_replacement(state1); - base_class::erase(iter); - - iter = base_class::find(ddecl_indirection); - } - } -}; - -class CDynamicArray2ReplacementAction : public CArray2ReplacementAction { -public: - using CArray2ReplacementAction::CArray2ReplacementAction; - virtual ~CDynamicArray2ReplacementAction() {} -}; - -class CMallocArray2ReplacementAction : public CDynamicArray2ReplacementAction { -public: - CMallocArray2ReplacementAction(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 ~CMallocArray2ReplacementAction() {} - - virtual void do_replacement(CState1& state1) const; - - const BinaryOperator* m_BO = nullptr; - //const CallExpr* m_CE = nullptr; - //const DeclRefExpr* m_DRE = nullptr; - //const MemberExpr* m_ME = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_bo_replacement_code; -}; - -class CMallocInitializerArray2ReplacementAction : public CDynamicArray2ReplacementAction { -public: - CMallocInitializerArray2ReplacementAction(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 void do_replacement(CState1& state1) const; - - const DeclStmt* m_DS = nullptr; - //const CallExpr* m_CE = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_initializer_info_str; -}; - -class CFreeDynamicArray2ReplacementAction : public CDynamicArray2ReplacementAction { -public: - CFreeDynamicArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, - const CallExpr* CE, const std::string& ce_replacement_code) : - CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), - m_ce_replacement_code(ce_replacement_code) {} - virtual ~CFreeDynamicArray2ReplacementAction() {} - - virtual void do_replacement(CState1& state1) const; - - const CallExpr* m_CE = nullptr; - //const DeclRefExpr* m_DRE = nullptr; - //const MemberExpr* m_ME = nullptr; - const DeclaratorDecl* m_DD = nullptr; - std::string m_ce_replacement_code; -}; - -class CSetArrayPointerToNull2ReplacementAction : 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() {} - - 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; -}; - -class CDynamicArray2ReplacementActionMap : public CDDecl2ReplacementActionMap { -public: - iterator insert( const std::shared_ptr<CDynamicArray2ReplacementAction>& cr_shptr ) { - return CDDecl2ReplacementActionMap::insert(static_cast<std::shared_ptr<CDDecl2ReplacementAction> >(cr_shptr)); - } -}; - -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 CIndirectionState { public: CIndirectionState(std::string original, std::string current) @@ -740,6 +545,8 @@ public: std::string m_initializer_info_str; bool m_original_initialization_has_been_noted = false; std::string m_original_initialization_expr_str; + bool m_original_source_text_has_been_noted = false; + std::string m_original_source_text_str; }; class CDDeclConversionStateMap : public std::map<const clang::DeclaratorDecl*, CDDeclConversionState> { @@ -750,6 +557,223 @@ public: } }; + +class CState1; + +class CReplacementAction { +public: + virtual ~CReplacementAction() {} + virtual void do_replacement(CState1& state1) const = 0; +}; + +class CDDecl2ReplacementAction : public CReplacementAction { +public: + CDDecl2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, + const CDDeclIndirection& ddecl_indirection) : m_Rewrite(Rewrite), m_MR(MR), m_ddecl_indirection(ddecl_indirection) {} + virtual ~CDDecl2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const = 0; + virtual const clang::DeclaratorDecl* get_ddecl_cptr() const { return m_ddecl_indirection.m_ddecl_cptr; } + virtual const CDDeclIndirection& ddecl_indirection_cref() const { return m_ddecl_indirection; } + + clang::SourceRange source_range() { + clang::SourceRange retval = m_ddecl_indirection.m_ddecl_cptr->getSourceRange(); + return retval; + } + clang::SourceLocation start_location() { + clang::SourceLocation retval = source_range().getBegin(); + return retval; + } + std::string get_var_name() { + std::string retval = m_ddecl_indirection.m_ddecl_cptr->getNameAsString(); + return retval; + } + + Rewriter& m_Rewrite; + const MatchFinder::MatchResult m_MR; + CDDeclIndirection m_ddecl_indirection; +}; + +class CArray2ReplacementAction : public CDDecl2ReplacementAction { +public: + using CDDecl2ReplacementAction::CDDecl2ReplacementAction; + virtual ~CArray2ReplacementAction() {} +}; + +class CMemsetArray2ReplacementAction : public CArray2ReplacementAction { +public: + CMemsetArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const CallExpr* CE, const std::string& ce_replacement_code) : + CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), + m_ce_replacement_code(ce_replacement_code) {} + virtual ~CMemsetArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const CallExpr* m_CE = nullptr; + //const DeclRefExpr* m_DRE = nullptr; + //const MemberExpr* m_ME = nullptr; + const DeclaratorDecl* m_DD = nullptr; + std::string m_ce_replacement_code; +}; + +class CMemcpyArray2ReplacementAction : public CArray2ReplacementAction { +public: + CMemcpyArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const CallExpr* CE, const std::string& ce_replacement_code) : + CArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), + m_ce_replacement_code(ce_replacement_code) {} + virtual ~CMemcpyArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const CallExpr* m_CE = nullptr; + //const DeclRefExpr* m_DRE = nullptr; + //const MemberExpr* m_ME = nullptr; + const DeclaratorDecl* m_DD = nullptr; + std::string m_ce_replacement_code; +}; + +class CAssignedFromArray2ReplacementAction : public CArray2ReplacementAction { +public: + CAssignedFromArray2ReplacementAction(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 ~CAssignedFromArray2ReplacementAction() {} + + 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; + iterator insert( const std::shared_ptr<CDDecl2ReplacementAction>& cr_shptr ) { + iterator retval(end()); + if (!cr_shptr) { assert(false); } else { + value_type val((*cr_shptr).ddecl_indirection_cref(), cr_shptr); + retval = base_class::insert(val); + } + return retval; + } + void do_and_dispose_matching_replacements(CState1& state1, const CDDeclIndirection& ddecl_indirection) { + /* The base class map may be modified during loop iterations. Maybe. */ + auto iter = base_class::find(ddecl_indirection); + while (base_class::end() != iter) { + (*((*iter).second)).do_replacement(state1); + base_class::erase(iter); + + iter = base_class::find(ddecl_indirection); + } + } +}; + +class CDynamicArray2ReplacementAction : public CArray2ReplacementAction { +public: + using CArray2ReplacementAction::CArray2ReplacementAction; + virtual ~CDynamicArray2ReplacementAction() {} +}; + +class CMallocArray2ReplacementAction : public CDynamicArray2ReplacementAction { +public: + CMallocArray2ReplacementAction(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 ~CMallocArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const BinaryOperator* m_BO = nullptr; + //const CallExpr* m_CE = nullptr; + //const DeclRefExpr* m_DRE = nullptr; + //const MemberExpr* m_ME = nullptr; + const DeclaratorDecl* m_DD = nullptr; + std::string m_bo_replacement_code; +}; + +class CMallocInitializerArray2ReplacementAction : public CDynamicArray2ReplacementAction { +public: + CMallocInitializerArray2ReplacementAction(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 void do_replacement(CState1& state1) const; + + const DeclStmt* m_DS = nullptr; + //const CallExpr* m_CE = nullptr; + const DeclaratorDecl* m_DD = nullptr; + std::string m_initializer_info_str; +}; + +class CFreeDynamicArray2ReplacementAction : public CDynamicArray2ReplacementAction { +public: + CFreeDynamicArray2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const CallExpr* CE, const std::string& ce_replacement_code) : + CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CE(CE), m_DD(ddecl_indirection.m_ddecl_cptr), + m_ce_replacement_code(ce_replacement_code) {} + virtual ~CFreeDynamicArray2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const CallExpr* m_CE = nullptr; + //const DeclRefExpr* m_DRE = nullptr; + //const MemberExpr* m_ME = nullptr; + const DeclaratorDecl* m_DD = nullptr; + std::string m_ce_replacement_code; +}; + +class CSetArrayPointerToNull2ReplacementAction : 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() {} + + 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; +}; + +/* This class represents and "enforces" the constraint that the lhs and rhs + * values of a conditional operator must be the same type. */ +class CConditionalOperatorReconciliation2ReplacementAction : public CDynamicArray2ReplacementAction { +public: + CConditionalOperatorReconciliation2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const CDDeclIndirection& ddecl_indirection, + const clang::ConditionalOperator* CO, const DeclaratorDecl* lhs_DD, const DeclaratorDecl* rhs_DD, const DeclaratorDecl* var_DD = nullptr) : + CDynamicArray2ReplacementAction(Rewrite, MR, ddecl_indirection), m_CO(CO), m_lhs_DD(lhs_DD), m_rhs_DD(rhs_DD), m_var_DD(var_DD) {} + virtual ~CConditionalOperatorReconciliation2ReplacementAction() {} + + virtual void do_replacement(CState1& state1) const; + + const clang::ConditionalOperator* m_CO = nullptr; + const DeclaratorDecl* m_lhs_DD = nullptr; + const DeclaratorDecl* m_rhs_DD = nullptr; + const DeclaratorDecl* m_var_DD = nullptr; +}; + +class CDynamicArray2ReplacementActionMap : public CDDecl2ReplacementActionMap { +public: + iterator insert( const std::shared_ptr<CDynamicArray2ReplacementAction>& cr_shptr ) { + return CDDecl2ReplacementActionMap::insert(static_cast<std::shared_ptr<CDDecl2ReplacementAction> >(cr_shptr)); + } +}; + +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 { public: /* This container holds (potential) actions that are meant to be executed if/when @@ -773,6 +797,14 @@ public: static CDeclarationReplacementCodeItem generate_declaration_replacement_code(const DeclaratorDecl* DD, Rewriter &Rewrite, CDDeclConversionStateMap& ddecl_conversion_state_map, std::string options_str = "") { CDeclarationReplacementCodeItem retval; + if (!DD) { + return retval; + } + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + if (!(decl_source_range.isValid())) { + return retval; + } + auto res1 = ddecl_conversion_state_map.insert(*DD); auto ddcs_map_iter = res1.first; auto& ddcs_ref = (*ddcs_map_iter).second; @@ -786,6 +818,11 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } else if ("const _Bool" == direct_qtype_str) { direct_qtype_str = "const bool"; } + auto direct_TP = ddcs_ref.m_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; @@ -797,6 +834,13 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con int q = 7; } + if (!(ddcs_ref.m_original_source_text_has_been_noted)) { + ddcs_ref.m_original_source_text_str = Rewrite.getRewrittenText(decl_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; bool has_dynamic_storage_duration = false; bool is_a_temporary = false; @@ -805,14 +849,21 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con bool is_member = false; bool is_vardecl = false; std::string initialization_expr_str; + bool is_function = DD->isFunctionOrFunctionTemplate(); auto VD = dynamic_cast<const clang::VarDecl *>(DD); if (VD) { is_vardecl = true; + storage_class = VD->getStorageClass(); + is_extern = (clang::StorageClass::SC_Extern == storage_class); storage_duration = VD->getStorageDuration(); has_dynamic_storage_duration = (clang::StorageDuration::SD_Dynamic == storage_duration); is_a_temporary = (clang::StorageDuration::SD_FullExpression == storage_duration); - is_static = (clang::StorageDuration::SD_Static == storage_duration); + //is_static = (clang::StorageDuration::SD_Static == storage_duration); + is_static = (clang::StorageClass::SC_Static == storage_class); + if ((clang::StorageDuration::SD_Static == storage_duration) && (!is_static)) { + int q = 5; + } is_a_function_parameter = (VD->isLocalVarDeclOrParm() && (!VD->isLocalVarDecl())); if (ddcs_ref.m_original_initialization_has_been_noted) { @@ -880,142 +931,177 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con } ddcs_ref.m_original_initialization_has_been_noted = true; + bool changed_from_original = false; std::string replacement_code; std::string prefix_str; std::string suffix_str; - for (size_t i = 0; i < ddcs_ref.m_indirection_state_stack.size(); i += 1) { - bool is_char_star = 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; - } - 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 { - 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) { - 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"; + 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 { + prefix_str = prefix_str + "mse::TNullableAnyRandomAccessIterator<"; suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer to TIPointerWithBundledVector"; + retval.m_action_species = "native pointer to TNullableAnyRandomAccessIterator"; } - } - } else if ("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) { - std::string size_text; - if (TP->isVariableArrayType()) { - auto VATP = llvm::cast<const clang::VariableArrayType>(TP); - if (!VATP) { - assert(false); + } else if ("dynamic 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 { - auto size_expr = VATP->getSizeExpr(); - auto SR = nice_source_range(size_expr->getSourceRange(), Rewrite); - size_text = Rewrite.getRewrittenText(SR); + 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 (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 if ("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + 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 = 7; + int q = 5; } - } else { - int q = 5; } } } - } - 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"; + 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 { - prefix_str = prefix_str + "mse::TIteratorWithBundledArray<"; - suffix_str = ", " + size_text + "> " + suffix_str; - retval.m_action_species = "native array to TIteratorWithBundledArray"; + 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 (false/*for now*/) { - prefix_str = prefix_str + "mse::TAnyPointer<"; - suffix_str = "> " + suffix_str; - retval.m_action_species = "native pointer to TAnyPointer"; - } else { + } 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 = "native pointer"; + 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"; } - } 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 (is_static) { - replacement_code += "static "; - } - replacement_code += prefix_str + direct_qtype_str + suffix_str; - replacement_code += " "; - replacement_code += variable_name; - if (std::string::npos == options_str.find("[no-initializer]")) { - std::string initializer_append_str = ddcs_ref.m_initializer_info_str; + bool discard_initializer_option_flag = (std::string::npos != options_str.find("[discard-initializer]")); + std::string initializer_append_str; + if (!discard_initializer_option_flag) { + initializer_append_str = ddcs_ref.m_initializer_info_str; if (("" == initializer_append_str) && ("" != initialization_expr_str)) { initializer_append_str = " = " + initialization_expr_str; } + } + + if (("" != prefix_str) || ("" != suffix_str)) { + changed_from_original = true; + } else if (("" != ddcs_ref.m_initializer_info_str) || + (discard_initializer_option_flag)) { + changed_from_original = true; + } else if (2 <= IndividualDeclaratorDecls(DD, Rewrite).size()) { + /* There is more than one declaration in the declaration statement. We split + * them so that each has their own separate declaration statement. This counts + * as a change from the original source code. */ + 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 "; + } + 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; return retval; } @@ -1294,16 +1380,21 @@ void CAssignedFromArray2ReplacementAction::do_replacement(CState1& state1) const auto& ddcs_ref = (*ddcs_map_iter).second; bool update_declaration_flag = res1.second; - 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; - 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; - state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, m_ddecl_indirection2); + 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; + 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; + 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 = 3; + } } else { - int q = 3; + int q = 7; } if (update_declaration_flag) { @@ -1311,6 +1402,136 @@ void CAssignedFromArray2ReplacementAction::do_replacement(CState1& state1) const } } +void CConditionalOperatorReconciliation2ReplacementAction::do_replacement(CState1& state1) const { + const clang::ConditionalOperator* CO = m_CO; + const Expr* COND = nullptr; + const Expr* LHS = nullptr; + const Expr* RHS = nullptr; + if (CO) { + COND = CO->getCond(); + LHS = CO->getLHS(); + RHS = CO->getRHS(); + } + const DeclaratorDecl* lhs_DD = m_lhs_DD; + const DeclaratorDecl* rhs_DD = m_rhs_DD; + if ((COND != nullptr) && (LHS != nullptr) && (RHS != nullptr) && (lhs_DD != nullptr) && (rhs_DD != nullptr)) { + bool lhs_is_array = false; + bool lhs_is_dynamic_array = false; + bool lhs_is_native_array = false; + + auto COSR = nice_source_range(CO->getSourceRange(), (*this).m_Rewrite); + auto cond_SR = nice_source_range(COND->getSourceRange(), (*this).m_Rewrite); + auto lhs_SR = nice_source_range(LHS->getSourceRange(), (*this).m_Rewrite); + auto rhs_SR = nice_source_range(RHS->getSourceRange(), (*this).m_Rewrite); + if ((COSR.isValid()) && (cond_SR.isValid()) && (lhs_SR.isValid()) && (rhs_SR.isValid())) { + auto res1 = state1.m_ddecl_conversion_state_map.insert(*lhs_DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + if (1 <= ddcs_ref.m_indirection_state_stack.size()) { + if ("dynamic array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + lhs_is_dynamic_array = true; + lhs_is_array = true; + } else if ("native array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + lhs_is_native_array = true; + lhs_is_array = true; + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + lhs_is_array = true; + } + } else { + int q = 3; + } + } + + bool rhs_is_array = false; + bool rhs_is_dynamic_array = false; + bool rhs_is_native_array = false; + { + auto res1 = state1.m_ddecl_conversion_state_map.insert(*rhs_DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + if (1 <= ddcs_ref.m_indirection_state_stack.size()) { + if ("dynamic array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + rhs_is_dynamic_array = true; + rhs_is_array = true; + } else if ("native array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + rhs_is_native_array = true; + rhs_is_array = true; + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + rhs_is_array = true; + } + } else { + int q = 3; + } + } + if (lhs_is_array && rhs_is_array) { + if (m_var_DD) { + update_declaration(*m_var_DD, (*this).m_Rewrite, state1); + } + + std::string CO_prior_text = (*this).m_Rewrite.getRewrittenText(COSR); + std::string CO_replacement_text; + + std::string cond_prior_text = (*this).m_Rewrite.getRewrittenText(cond_SR); + std::string cond_replacement_text = cond_prior_text; + + std::string lhs_prior_text = (*this).m_Rewrite.getRewrittenText(lhs_SR); + std::string lhs_replacement_text = lhs_prior_text; + + std::string rhs_prior_text = (*this).m_Rewrite.getRewrittenText(rhs_SR); + std::string rhs_replacement_text = rhs_prior_text; + static const std::string ara_iter_prefix = "mse::TAnyRandomAccessIterator<"; + + bool lhs_needs_to_be_wrapped = false; + if ((lhs_is_dynamic_array && (!rhs_is_dynamic_array)) || (lhs_is_native_array && (!rhs_is_native_array))) { + lhs_needs_to_be_wrapped = true; + } + if (lhs_needs_to_be_wrapped) { + if (!string_begins_with(lhs_prior_text, ara_iter_prefix)) { + std::string lhs_base_type_str = lhs_DD->getType().getAsString(); + std::string lhs_replacement_text = ara_iter_prefix + lhs_base_type_str + " >(" + lhs_prior_text + ")"; + if (ConvertToSCPP) { + auto res2 = (*this).m_Rewrite.ReplaceText(lhs_SR, lhs_replacement_text); + + CO_replacement_text = (*this).m_Rewrite.getRewrittenText(COSR); + int q = 3; + } + } + } + + bool rhs_needs_to_be_wrapped = false; + if ((rhs_is_dynamic_array && (!lhs_is_dynamic_array)) || (rhs_is_native_array && (!lhs_is_native_array))) { + rhs_needs_to_be_wrapped = true; + } + if (rhs_needs_to_be_wrapped) { + if (!string_begins_with(rhs_prior_text, ara_iter_prefix)) { + std::string rhs_base_type_str = rhs_DD->getType().getAsString(); + std::string rhs_replacement_text = ara_iter_prefix + rhs_base_type_str + " >(" + rhs_prior_text + ")"; + if (ConvertToSCPP) { + auto res2 = (*this).m_Rewrite.ReplaceText(rhs_SR, rhs_replacement_text); + + auto possibly_truncated_CO_replacement_text = (*this).m_Rewrite.getRewrittenText(COSR); + std::string cond_text = (*this).m_Rewrite.getRewrittenText(cond_SR); + std::string CO_replacement_text2 = cond_text + " ? " + lhs_replacement_text + " : " + rhs_replacement_text; + + CO_replacement_text = possibly_truncated_CO_replacement_text; + int q = 3; + } + } + } + + if (m_var_DD && ("" != CO_replacement_text)) { + auto res1 = state1.m_ddecl_conversion_state_map.insert(*m_var_DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + + ddcs_ref.m_initializer_info_str = " = " + CO_replacement_text; + } + + } + } +} + + struct CArrayInferenceInfo { bool update_declaration_flag = false; bool has_been_determined_to_be_an_array = false; @@ -1326,7 +1547,11 @@ CArrayInferenceInfo infer_array_type_info_from_stmt_indirection_stack(CDDeclConv 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 ("native pointer" == ddcs_ref.m_indirection_state_stack[i].m_current) { + 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"; @@ -2780,6 +3005,7 @@ private: CState1& m_state1; }; +/* This class addresses the initialized declarations in the form "type var = cond ? lhs : rhs;". */ class MCSSSConditionalInitializer : public MatchFinder::MatchCallback { public: @@ -2821,11 +3047,6 @@ public: return void(); } - if (std::string::npos != source_location_str.find("73")) { - walkTheAST1(*LHS); - int q = 5; - } - 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; @@ -2845,52 +3066,139 @@ public: 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; + std::string var_current_state_str; + { + auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + if (1 <= ddcs_ref.m_indirection_state_stack.size()) { + var_current_state_str = ddcs_ref.m_indirection_state_stack[0].m_current; + } else { + int q = 7; + } + } + bool var_has_been_determined_to_be_an_array = false; + if (("inferred array" == var_current_state_str) || + ("dynamic array" == var_current_state_str) || + ("native array" == var_current_state_str)) { + if ("native array" == var_current_state_str) { + assert(false); /* right? */ + } + var_has_been_determined_to_be_an_array = true; + } + + auto lhs_res2 = infer_array_type_info_from_stmt(*LHS, "", (*this).m_state1); + auto rhs_res2 = infer_array_type_info_from_stmt(*RHS, "", (*this).m_state1); + bool lhs_qualifies = false; + bool rhs_qualifies = false; { - auto res2 = infer_array_type_info_from_stmt(*LHS, "", (*this).m_state1); + auto& res2 = lhs_res2; if (res2.ddecl_cptr && res2.declaration_expr_cptr) { std::string variable_name = res2.ddecl_cptr->getNameAsString(); auto QT = res2.ddecl_cptr->getType(); auto LHS_QT = LHS->getType(); - if (QT == LHS_QT) { - - if (ConvertToSCPP && decl_source_range.isValid()) { + /* Currently we only support the case where the value expressions are direct + * references to declared variables. */ + if ((QT == LHS_QT)/* && (1 == res2.indirection_level)*/) { + lhs_qualifies = true; + if (ConvertToSCPP) { + /* Here we're establishing and "enforcing" the constraint that the lhs value must + * be of an (array) type that can be assigned to the target variable. */ auto cr_shptr = std::make_shared<CAssignedFromArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); - if (true || res2.has_been_determined_to_be_an_array) { + if (var_has_been_determined_to_be_an_array) { (*cr_shptr).do_replacement(m_state1); } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); } - } else { - int q = 7; } } } } { - auto res2 = infer_array_type_info_from_stmt(*RHS, "", (*this).m_state1); + auto& res2 = rhs_res2; if (res2.ddecl_cptr && res2.declaration_expr_cptr) { std::string variable_name = res2.ddecl_cptr->getNameAsString(); auto QT = res2.ddecl_cptr->getType(); auto RHS_QT = RHS->getType(); + /* Currently we only support the case where the value expressions are direct + * references to declared variables. */ if (QT == RHS_QT) { - - if (ConvertToSCPP && decl_source_range.isValid()) { + rhs_qualifies = true; + if (ConvertToSCPP) { + /* Here we're establishing and "enforcing" the constraint that the rhs value must + * be of an (array) type that can be assigned to the target variable. */ auto cr_shptr = std::make_shared<CAssignedFromArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); - if (true || res2.has_been_determined_to_be_an_array) { + if (var_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 (lhs_qualifies && rhs_qualifies) { + std::string lhs_current_state_str; + { + auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*(lhs_res2.ddecl_cptr)); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + if (1 <= ddcs_ref.m_indirection_state_stack.size()) { + lhs_current_state_str = ddcs_ref.m_indirection_state_stack[0].m_current; + } else { + int q = 7; + } + } + std::string rhs_current_state_str; + { + auto res1 = m_state1.m_ddecl_conversion_state_map.insert(*(rhs_res2.ddecl_cptr)); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + if (1 <= ddcs_ref.m_indirection_state_stack.size()) { + rhs_current_state_str = ddcs_ref.m_indirection_state_stack[0].m_current; + } else { + int q = 7; + } + } + + if (ConvertToSCPP) { + /* Here we're establishing and "enforcing" the constraint that the lhs and rhs + * values of the conditional operator must be the same type. */ + { + auto cr_shptr = std::make_shared<CConditionalOperatorReconciliation2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*lhs_res2.ddecl_cptr, 0), CO, lhs_res2.ddecl_cptr, rhs_res2.ddecl_cptr, DD); + + if ("dynamic array" == lhs_current_state_str) { + (*cr_shptr).do_replacement(m_state1); + } else if ("native array" == lhs_current_state_str) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + if ("inferred array" == lhs_current_state_str) { (*cr_shptr).do_replacement(m_state1); } else { m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); } + } + } + { + auto cr_shptr = std::make_shared<CConditionalOperatorReconciliation2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*rhs_res2.ddecl_cptr, 0), CO, lhs_res2.ddecl_cptr, rhs_res2.ddecl_cptr, DD); + + if ("dynamic array" == rhs_current_state_str) { + (*cr_shptr).do_replacement(m_state1); + } else if ("native array" == rhs_current_state_str) { + (*cr_shptr).do_replacement(m_state1); } else { - int q = 7; + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + if ("inferred array" == rhs_current_state_str) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); + } } } } |