aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--safercpp/safercpp-arr.cpp1369
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;
};