diff options
| -rw-r--r-- | safercpp/safercpp-arr.cpp | 1369 | 
1 files changed, 1024 insertions, 345 deletions
| diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index 28419a1..05f6f27 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,11 @@ 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 +292,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) @@ -734,12 +540,15 @@ public:  		m_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT);  		//std::reverse(m_indirection_state_stack.begin(), m_indirection_state_stack.end());  	} +	bool is_an_indirect_type(size_t indirection_level = 0) const { return (indirection_level < m_indirection_state_stack.size()); }  	const DeclaratorDecl* m_ddecl_cptr = nullptr;  	CIndirectionStateStack m_indirection_state_stack;  	clang::QualType m_direct_qtype;  	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 +559,402 @@ public:  	}  }; +bool is_an_indirect_type(const CDDeclIndirection& ddecl_indirection) { +	return CDDeclConversionState(*(ddecl_indirection.m_ddecl_cptr)).is_an_indirect_type(ddecl_indirection.m_indirection_level); +} +bool is_an_indirect_type(const clang::DeclaratorDecl& ddecl) { +	return CDDeclConversionState(ddecl).is_an_indirect_type(); +} + +bool is_an_indirect_type(const QualType& QT, size_t indirection_level = 0) { +	CIndirectionStateStack m_indirection_state_stack; +	auto m_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); +	return (indirection_level < m_indirection_state_stack.size()); +} + +class CExprTextModifier { +public: +	virtual ~CExprTextModifier() {} +	virtual std::string modified_copy(const std::string& input_text, const clang::Expr* expr_ptr = nullptr) const { +		return input_text; +	} +	virtual std::string species_str() const { +		return "no op"; +	} +}; + +class CWrapExprTextModifier : public CExprTextModifier { +public: +	CWrapExprTextModifier(const std::string& prefix, const std::string& suffix) : +		m_prefix(prefix), m_suffix(suffix) {} +	virtual ~CWrapExprTextModifier() {} +	virtual std::string modified_copy(const std::string& input_text, const clang::Expr* expr_ptr = nullptr) const { +		return m_prefix + input_text + m_suffix; +	} +	virtual std::string species_str() const { +		return "wrap"; +	} +	std::string m_prefix; +	std::string m_suffix; +}; + +class CNullableAnyRandomAccessIterCastExprTextModifier : public CWrapExprTextModifier { +public: +	CNullableAnyRandomAccessIterCastExprTextModifier(const clang::QualType& qtype) : +		CWrapExprTextModifier("mse::TNullableAnyRandomAccessIterator<" + qtype.getAsString() + " >(", ")"), +		m_qtype(qtype) {} +	virtual ~CNullableAnyRandomAccessIterCastExprTextModifier() {} +	virtual std::string species_str() const { +		return "nullable any random access iter cast"; +	} +	clang::QualType m_qtype; +}; + +class CExprTextModifierStack : public std::vector<std::shared_ptr<CExprTextModifier>> { +public: +}; + +class CExprConversionState { +public: +	CExprConversionState(const clang::Expr& expr, Rewriter &Rewrite) : m_expr_cptr(&expr), Rewrite(Rewrite) { +		m_original_source_text_str = Rewrite.getRewrittenText(nice_source_range()); +		m_current_text_str = m_original_source_text_str; +	} +	virtual ~CExprConversionState() {} +	virtual void update_current_text() { +		m_current_text_str = modified_copy(m_original_source_text_str); +	} + +	clang::SourceRange source_range() const { +		clang::SourceRange retval; +		return m_expr_cptr->getSourceRange(); +	} +	clang::SourceRange nice_source_range() const { +		return ::nice_source_range(source_range(), Rewrite); +	} +	void set_parent_shptr(const std::shared_ptr<CExprConversionState>& parent_shptr) { +		m_parent_shptr = parent_shptr; +	} +	void set_childrens_parent_shptr(const std::shared_ptr<CExprConversionState>& parent_shptr) { +		for (auto& child_shptr : m_children_shptrs) { +			child_shptr->set_parent_shptr(parent_shptr); +		} +	} + +	std::string modified_copy(const std::string& input_text) const { +		std::string retval = input_text; +		for (const auto& modifier_shptr_cref : m_expr_text_modifier_stack) { +			retval = (*modifier_shptr_cref).modified_copy(retval, m_expr_cptr); +		} +		return retval; +	} + +	CExprTextModifierStack m_expr_text_modifier_stack; + +	std::shared_ptr<CExprConversionState> m_parent_shptr; +	std::vector<std::shared_ptr<CExprConversionState>> m_children_shptrs; + +	const Expr* m_expr_cptr = nullptr; +	std::string m_original_source_text_str; +	std::string m_current_text_str; +	Rewriter &Rewrite; +}; + +class CConditionalOperatorExprConversionState : public CExprConversionState { +public: +	CConditionalOperatorExprConversionState(const clang::ConditionalOperator& co_cref, Rewriter &Rewrite) : CExprConversionState(co_cref, Rewrite) { +		auto cond_ptr = co_cref.getCond(); +		auto lhs_ptr = co_cref.getLHS(); +		auto rhs_ptr = co_cref.getRHS(); +		if (cond_ptr && lhs_ptr && rhs_ptr) { +			m_cond_shptr = std::make_shared<CExprConversionState>(*cond_ptr, Rewrite); +			m_children_shptrs.push_back(m_cond_shptr); + +			m_lhs_shptr = std::make_shared<CExprConversionState>(*lhs_ptr, Rewrite); +			m_children_shptrs.push_back(m_lhs_shptr); + +			m_rhs_shptr = std::make_shared<CExprConversionState>(*rhs_ptr, Rewrite); +			m_children_shptrs.push_back(m_rhs_shptr); +		} else { +			assert(false); +			throw(""); +		} +	} +	const clang::ConditionalOperator& co_cref() const { +		return (*(static_cast<const clang::ConditionalOperator *>(m_expr_cptr))); +	} +	virtual void update_current_text() { +		if (false) { +			/* Do we need to update the kids first? */ +			m_cond_shptr->update_current_text(); +			m_lhs_shptr->update_current_text(); +			m_rhs_shptr->update_current_text(); +		} +		std::string updated_text = m_cond_shptr->m_current_text_str + " ? " +				+ m_lhs_shptr->m_current_text_str + " : " + m_rhs_shptr->m_current_text_str; +		updated_text = modified_copy(updated_text); +		m_current_text_str = updated_text; +	} + +	std::shared_ptr<CExprConversionState> m_cond_shptr; +	std::shared_ptr<CExprConversionState> m_lhs_shptr; +	std::shared_ptr<CExprConversionState> m_rhs_shptr; +}; + +template<class X, class... Args> +std::shared_ptr<X> make_expr_conversion_state_shared_ptr(Args&&... args) { +	std::shared_ptr<X> retval = std::make_shared<X>(std::forward<Args>(args)...); +	retval->set_childrens_parent_shptr(retval); +	return retval; +} + +class CExprConversionStateMap : public std::map<const clang::Expr*, std::shared_ptr<CExprConversionState>> { +public: +	typedef std::map<const clang::Expr*, std::shared_ptr<CExprConversionState>> base_class; +	iterator insert( const std::shared_ptr<CExprConversionState>& cr_shptr ) { +		iterator retval(end()); +		if (!cr_shptr) { assert(false); } else { +			value_type val((*cr_shptr).m_expr_cptr, cr_shptr); +			auto res1 = base_class::insert(val); +			retval = res1.first; +			for (auto& child_shptr_ref : (*cr_shptr).m_children_shptrs) { +				value_type val((*child_shptr_ref).m_expr_cptr, child_shptr_ref); +				auto res1 = base_class::insert(val); +			} +		} +		return retval; +	} +}; + + +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 CAssignmentTargetConstrainsSourceArray2ReplacementAction : public CArray2ReplacementAction { +public: +	CAssignmentTargetConstrainsSourceArray2ReplacementAction(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 ~CAssignmentTargetConstrainsSourceArray2ReplacementAction() {} + +	virtual void do_replacement(CState1& state1) const; + +	const CDDeclIndirection m_ddecl_indirection2; +}; + +class CAssignmentSourceConstrainsTargetArray2ReplacementAction : public CArray2ReplacementAction { +public: +	CAssignmentSourceConstrainsTargetArray2ReplacementAction(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 ~CAssignmentSourceConstrainsTargetArray2ReplacementAction() {} + +	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 @@ -763,6 +968,10 @@ public:  	/* This container holds information about each item's original type and which  	 * type it might be converted to.  */  	CDDeclConversionStateMap m_ddecl_conversion_state_map; + +	/* This container holds information about selected expressions' original text and +	 * any modifications we might have made.  */ +	CExprConversionStateMap m_expr_conversion_state_map;  };  class CDeclarationReplacementCodeItem { @@ -773,6 +982,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; @@ -780,12 +997,26 @@ static CDeclarationReplacementCodeItem generate_declaration_replacement_code(con  	QualType QT = DD->getType();  	const clang::Type* TP = QT.getTypePtr();  	auto qtype_str = QT.getAsString(); -	auto direct_qtype_str = clang::QualType::getAsString(ddcs_ref.m_direct_qtype.split()); +	auto direct_qtype_str = ddcs_ref.m_direct_qtype.getAsString();  	if ("_Bool" == direct_qtype_str) {  		direct_qtype_str = "bool";  	} else if ("const _Bool" == direct_qtype_str) {  		direct_qtype_str = "const bool";  	} +	QT.isConstQualified(); + +	auto non_const_direct_qtype = ddcs_ref.m_direct_qtype; +	non_const_direct_qtype.removeLocalConst(); +	auto non_const_direct_qtype_str = non_const_direct_qtype.getAsString(); +	if ("_Bool" == non_const_direct_qtype_str) { +		non_const_direct_qtype_str = "bool"; +	} + +	auto direct_TP = ddcs_ref.m_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 +1028,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 +1043,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 +1125,180 @@ 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) { +				direct_qtype_str = non_const_direct_qtype_str; +				if (is_char_star) { +					/* We're assuming this is a null terminated string. We'll just leave it as a +					 * char* for now. At some point we'll replace it with an mse::string or whatever. */ +					//prefix_str = prefix_str + ""; +					suffix_str = "* " + suffix_str; +					retval.m_action_species = "char*";  				} else { +					prefix_str = prefix_str + "mse::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) { +				direct_qtype_str = non_const_direct_qtype_str; +				if (is_char_star) { +					/* We're assuming this is a null terminated string. We'll just leave it as a +					 * char* for now. At some point we'll replace it with an mse::string or whatever. */ +					//prefix_str = prefix_str + ""; +					suffix_str = "* " + suffix_str; +					retval.m_action_species = "char*";  				} else { -					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) { +				direct_qtype_str = non_const_direct_qtype_str; +				std::string size_text; +				if (TP->isVariableArrayType()) { +					auto VATP = llvm::cast<const clang::VariableArrayType>(TP); +					if (!VATP) { +						assert(false); +					} else { +						auto size_expr = VATP->getSizeExpr(); +						auto SR = nice_source_range(size_expr->getSourceRange(), Rewrite); +						size_text = Rewrite.getRewrittenText(SR); +					} +				} else if (TP->isConstantArrayType()) { +					auto CATP = llvm::cast<const clang::ConstantArrayType>(TP); +					if (!CATP) { +						assert(false); +					} else { +						auto array_size = CATP->getSize(); +						size_text = array_size.toString(10, false);/*check this*/ + +						if (false) { +							auto DDSR = nice_source_range(DD->getSourceRange(), Rewrite); +							std::string array_size_expression_text; +							std::string source_text; +							if (DDSR.isValid()) { +								source_text = Rewrite.getRewrittenText(DDSR); + +								auto left_bracket_pos = source_text.find('['); +								auto right_bracket_pos = source_text.find(']'); +								if ((std::string::npos != left_bracket_pos) && (std::string::npos != right_bracket_pos) +										&& (left_bracket_pos + 1 < right_bracket_pos)) { +									auto array_size_expression_text = source_text.substr(left_bracket_pos + 1, right_bracket_pos - (left_bracket_pos + 1)); +									int q = 3; +								} else { +									int q = 7; +								}  							} else { -								int q = 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;  } @@ -1285,7 +1568,7 @@ void CMemcpyArray2ReplacementAction::do_replacement(CState1& state1) const {  	}  } -void CAssignedFromArray2ReplacementAction::do_replacement(CState1& state1) const { +void CAssignmentTargetConstrainsSourceArray2ReplacementAction::do_replacement(CState1& state1) const {  	Rewriter &Rewrite = m_Rewrite;  	const MatchFinder::MatchResult &MR = m_MR; @@ -1294,16 +1577,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,11 +1599,205 @@ void CAssignedFromArray2ReplacementAction::do_replacement(CState1& state1) const  	}  } +void CAssignmentSourceConstrainsTargetArray2ReplacementAction::do_replacement(CState1& state1) const { +	Rewriter &Rewrite = m_Rewrite; +	const MatchFinder::MatchResult &MR = m_MR; + +	auto res1 = state1.m_ddecl_conversion_state_map.insert(*(m_ddecl_indirection2.m_ddecl_cptr)); +	auto ddcs_map_iter = res1.first; +	auto& ddcs_ref = (*ddcs_map_iter).second; +	bool update_declaration_flag = res1.second; + +	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 = 7; +	} + +	if (update_declaration_flag) { +		update_declaration(*(m_ddecl_indirection2.m_ddecl_cptr), Rewrite, state1); +	} +} + +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; +			/* At the moment we only support the case where the value option expressions are +			 * just declared variables. */ +			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::TNullableAnyRandomAccessIterator<"; + +			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; +			} +			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; +			} +			auto cocs_iter = state1.m_expr_conversion_state_map.end(); +			if (lhs_needs_to_be_wrapped || rhs_needs_to_be_wrapped) { +				cocs_iter = state1.m_expr_conversion_state_map.find(CO); +				if (state1.m_expr_conversion_state_map.end() == cocs_iter) { +					auto shptr1 = make_expr_conversion_state_shared_ptr<CConditionalOperatorExprConversionState>(*CO, m_Rewrite); +					cocs_iter = state1.m_expr_conversion_state_map.insert(shptr1); +				} +			} + +			if (lhs_needs_to_be_wrapped) { +				assert(state1.m_expr_conversion_state_map.end() != cocs_iter); +				auto lhscs_iter = state1.m_expr_conversion_state_map.find(LHS); +				if (state1.m_expr_conversion_state_map.end() != lhscs_iter) { +					auto& lhscs_shptr_ref = (*lhscs_iter).second; +					bool already_wrapped_flag = false; +					if (1 <= (*lhscs_shptr_ref).m_expr_text_modifier_stack.size()) { +						auto& last_modifier_ref = (*(*lhscs_shptr_ref).m_expr_text_modifier_stack.back()); +						if ("nullable any random access iter cast" == last_modifier_ref.species_str()) { +							already_wrapped_flag = true; +						} +					} +					if (ConvertToSCPP && (!already_wrapped_flag)) { +						auto shptr1 = std::make_shared<CNullableAnyRandomAccessIterCastExprTextModifier>(LHS->getType()->getPointeeType()); +						(*lhscs_shptr_ref).m_expr_text_modifier_stack.push_back(shptr1); +						(*lhscs_shptr_ref).update_current_text(); +					} +				} +			} +			if (rhs_needs_to_be_wrapped) { +				assert(state1.m_expr_conversion_state_map.end() != cocs_iter); +				auto rhscs_iter = state1.m_expr_conversion_state_map.find(RHS); +				if (state1.m_expr_conversion_state_map.end() != rhscs_iter) { +					auto& rhscs_shptr_ref = (*rhscs_iter).second; +					bool already_wrapped_flag = false; +					if (1 <= (*rhscs_shptr_ref).m_expr_text_modifier_stack.size()) { +						auto& last_modifier_ref = (*(*rhscs_shptr_ref).m_expr_text_modifier_stack.back()); +						if ("nullable any random access iter cast" == last_modifier_ref.species_str()) { +							already_wrapped_flag = true; +						} +					} +					if (ConvertToSCPP && (!already_wrapped_flag)) { +						auto shptr1 = std::make_shared<CNullableAnyRandomAccessIterCastExprTextModifier>(RHS->getType()->getPointeeType()); +						(*rhscs_shptr_ref).m_expr_text_modifier_stack.push_back(shptr1); +						(*rhscs_shptr_ref).update_current_text(); +					} +				} +			} + +			if (m_var_DD && (true)) { +				assert(state1.m_expr_conversion_state_map.end() != cocs_iter); +				auto& cocs_shptr_ref = (*(*cocs_iter).second); +				cocs_shptr_ref.update_current_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 = " = " + cocs_shptr_ref.m_current_text_str; +			} + +		} +	} +} + +  struct CArrayInferenceInfo { +	bool is_an_indirect_type() const { +		if (nullptr != ddecl_conversion_state_ptr) { +			return (1 <= ddecl_conversion_state_ptr->m_indirection_state_stack.size()); +		} else { +			return false; +		} +	}  	bool update_declaration_flag = false;  	bool has_been_determined_to_be_an_array = false;  	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;  }; @@ -1326,7 +1808,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"; @@ -1424,6 +1910,9 @@ CArrayInferenceInfo infer_array_type_info_from_stmt(const clang::Stmt& stmt_cref  			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.ddecl_conversion_state_ptr = &ddcs_ref; +			retval.ddecl_needs_update_flag = update_declaration_flag;  		}  		retval.ddecl_cptr = expr2_DD;  	} @@ -2780,6 +3269,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 +3311,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 +3330,163 @@ 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()) { -							auto cr_shptr = std::make_shared<CAssignedFromArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); +					/* 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<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); + +								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); +								} +							} +							{ +								/* Here we're establishing the constraint in the opposite direction as well. */ +								auto cr_shptr = std::make_shared<CAssignmentSourceConstrainsTargetArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level), CDDeclIndirection(*DD, 0)); -							if (true || res2.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 (res2.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) { +						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<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); + +								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); +								} +							} +							{ +								/* Here we're establishing the constraint in the opposite direction as well. */ +								auto cr_shptr = std::make_shared<CAssignmentSourceConstrainsTargetArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level), CDDeclIndirection(*DD, 0)); + +								if (res2.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 && decl_source_range.isValid()) { -							auto cr_shptr = std::make_shared<CAssignedFromArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0), CDDeclIndirection(*(res2.ddecl_cptr) , res2.indirection_level)); +				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 (true || res2.has_been_determined_to_be_an_array) { +						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); +							}  						}  					}  				} @@ -2903,6 +3499,81 @@ private:  	CState1& m_state1;  }; +class MCSSSAssignment : public MatchFinder::MatchCallback +{ +public: +	MCSSSAssignment (Rewriter &Rewrite, CState1& state1) : +		Rewrite(Rewrite), m_state1(state1) {} + +	virtual void run(const MatchFinder::MatchResult &MR) +	{ +		const clang::BinaryOperator* BO = MR.Nodes.getNodeAs<clang::BinaryOperator>("mcsssassignment1"); +		const Expr* LHS = nullptr; +		const Expr* RHS = nullptr; +		if (BO) { +			LHS = BO->getLHS(); +			RHS = BO->getRHS(); +		} +		const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssassignment2"); + +		if ((BO != nullptr) && (LHS != nullptr) && (RHS != nullptr) && (DRE != nullptr)) +		{ +			auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); +			SourceLocation BOSL = BOSR.getBegin(); +			SourceLocation BOSLE = BOSR.getEnd(); + +			ASTContext *const ASTC = MR.Context; +			FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL); + +			SourceManager &SM = ASTC->getSourceManager(); + +			auto source_location_str = BOSL.printToString(*MR.SourceManager); +			std::string source_text; +			if (BOSL.isValid() && BOSLE.isValid()) { +				source_text = Rewrite.getRewrittenText(SourceRange(BOSL, BOSLE)); +			} else { +				return; +			} + +			if (filtered_out_by_location(MR, BOSL)) { +				return void(); +			} + +			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); +			if (ConvertToSCPP && (lhs_res2.ddecl_cptr) && (rhs_res2.ddecl_cptr) +					&& (is_an_indirect_type(LHS->getType()))) { +				{ +					/* Here we're establishing and "enforcing" the constraint that the rhs value must +					 * be of an (array) type that can be assigned to the lhs. */ +					auto cr_shptr = std::make_shared<CAssignmentTargetConstrainsSourceArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level), CDDeclIndirection(*(rhs_res2.ddecl_cptr), rhs_res2.indirection_level)); + +					if (lhs_res2.has_been_determined_to_be_an_array) { +						(*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), CDDeclIndirection(*(lhs_res2.ddecl_cptr), lhs_res2.indirection_level)); + +					if (rhs_res2.has_been_determined_to_be_an_array) { +						(*cr_shptr).do_replacement(m_state1); +					} else { +						m_state1.m_array2_contingent_replacement_map.insert(cr_shptr); +					} +				} +			} + +		} +	} + +private: +	Rewriter &Rewrite; +	CState1& m_state1; +}; +  /**********************************************************************************************************************/  class MyASTConsumer : public ASTConsumer { @@ -2910,7 +3581,8 @@ public:    MyASTConsumer(Rewriter &R) : HandlerForSSSNativePointer(R), HandlerForSSSArrayToPointerDecay(R, m_state1),  	HandlerForSSSVarDecl2(R, m_state1), HandlerForSSSPointerArithmetic2(R, m_state1), HandlerForSSSMalloc2(R, m_state1),  	HandlerForSSSMallocInitializer2(R, m_state1), HandlerForSSSFree2(R, m_state1), HandlerForSSSSetToNull2(R, m_state1), -	HandlerForSSSMemset(R, m_state1), HandlerForSSSMemcpy(R, m_state1), HandlerForSSSConditionalInitializer(R, m_state1) +	HandlerForSSSMemset(R, m_state1), HandlerForSSSMemcpy(R, m_state1), HandlerForSSSConditionalInitializer(R, m_state1), +	HandlerForSSSAssignment(R, m_state1)    {  	  Matcher.addMatcher(varDecl(hasType(pointerType())).bind("mcsssnativepointer"), &HandlerForSSSNativePointer); @@ -3021,6 +3693,12 @@ public:  	  		))).bind("mcsssconditionalinitializer3")  				)).bind("mcsssconditionalinitializer1"), &HandlerForSSSConditionalInitializer); +	  Matcher.addMatcher(binaryOperator(allOf( +	  		hasOperatorName("="), +	  		hasLHS(hasDescendant(declRefExpr().bind("mcsssassignment2"))), +	  		hasRHS(hasDescendant(declRefExpr().bind("mcsssassignment3"))) +				)).bind("mcsssassignment1"), &HandlerForSSSAssignment); +    }    void HandleTranslationUnit(ASTContext &Context) override  @@ -3043,6 +3721,7 @@ private:    MCSSSMemset HandlerForSSSMemset;    MCSSSMemcpy HandlerForSSSMemcpy;    MCSSSConditionalInitializer HandlerForSSSConditionalInitializer; +  MCSSSAssignment HandlerForSSSAssignment;    MatchFinder Matcher;  }; | 
