diff options
author | bloodstalker <thabogre@gmail.com> | 2017-04-13 09:18:08 +0000 |
---|---|---|
committer | bloodstalker <thabogre@gmail.com> | 2017-04-13 09:18:08 +0000 |
commit | d56b9279142bf498bfebe734e3e2a6d3d298bec2 (patch) | |
tree | 82b1b93eca4134629f303f00b205b930cdcdfb4a | |
parent | added a new part called how to get it (diff) | |
parent | changed to handle all levels of indirection when translating declared (diff) | |
download | mutator-d56b9279142bf498bfebe734e3e2a6d3d298bec2.tar.gz mutator-d56b9279142bf498bfebe734e3e2a6d3d298bec2.zip |
Merge branch 'master' of https://github.com/bloodstalker/mutator
-rw-r--r-- | safercpp/safercpp-arr.cpp | 2475 |
1 files changed, 1273 insertions, 1202 deletions
diff --git a/safercpp/safercpp-arr.cpp b/safercpp/safercpp-arr.cpp index b2b81dd..98e72e2 100644 --- a/safercpp/safercpp-arr.cpp +++ b/safercpp/safercpp-arr.cpp @@ -76,10 +76,27 @@ SourceRange nice_source_range(const SourceRange& sr, Rewriter &Rewrite) { bool filtered_out_by_location(const ast_matchers::MatchFinder::MatchResult &MR, SourceLocation SL) { bool retval = false; + if (Devi::IsTheMatchInSysHeader(CheckSystemHeader, MR, SL)) { retval = true; } else if (!Devi::IsTheMatchInMainFile(MainFileOnly, MR, SL)) { retval = true; + } else { + bool filename_is_invalid = false; + std::string full_path_name = MR.SourceManager->getBufferName(SL, &filename_is_invalid); + std::string filename = full_path_name; + auto last_slash_pos = full_path_name.find_last_of('/'); + if (std::string::npos != last_slash_pos) { + if (last_slash_pos + 1 < full_path_name.size()) { + filename = full_path_name.substr(last_slash_pos+1); + } else { + filename = ""; + } + } + static const std::string mse_str = "mse"; + if (0 == filename.compare(0, mse_str.size(), mse_str)) { + retval = true; + } } return retval; } @@ -118,6 +135,8 @@ static std::string with_newlines_removed(const std::string& str) { return retval; } +/* No longer used. This function extracts the text of individual declarations when multiple + * pointers are declared in the same declaration statement. */ static std::vector<std::string> f_declared_object_strings(const std::string& decl_stmt_str) { std::vector<std::string> retval; @@ -197,79 +216,98 @@ static std::vector<std::string> f_declared_object_strings(const std::string& dec class CState1; -class CDeclReplacementActionRecord { +class CReplacementAction { public: - CDeclReplacementActionRecord(Rewriter &Rewrite, const clang::DeclaratorDecl& ddecl, const std::string& replacement_text - , const std::string& action_species) -: m_Rewrite_ptr(&Rewrite), m_ddecl_cptr(&ddecl), m_replacement_text(replacement_text), m_action_species(action_species) { - } - virtual ~CDeclReplacementActionRecord() {} - clang::SourceRange source_range() { - clang::SourceRange retval = m_ddecl_cptr->getSourceRange(); - return retval; + 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) { + retval += tolower(ch); } - clang::SourceLocation start_location() { - clang::SourceLocation retval = source_range().getBegin(); + return retval; +} + +/* 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) { + /* There's probably a more efficient way to do this, but this implementation seems to work. */ + std::vector<const DeclaratorDecl*> retval; + + if (!DD) { + assert(false); return retval; } - std::string get_var_name() { - std::string retval = m_ddecl_cptr->getNameAsString(); + auto SR = nice_source_range(DD->getSourceRange(), Rewrite); + SourceLocation SL = SR.getBegin(); + + std::string source_text; + if (SR.isValid()) { + source_text = Rewrite.getRewrittenText(SR); + } else { return retval; } - const clang::DeclaratorDecl* get_ddecl_cptr() { return m_ddecl_cptr; } - std::string replacement_text() { return m_replacement_text; } - std::string action_species() { return m_action_species; } - Rewriter* m_Rewrite_ptr = nullptr; - const clang::DeclaratorDecl* m_ddecl_cptr = nullptr; - std::string m_replacement_text; - std::string m_action_species; -}; - -class CDeclReplacementActionRecordsLog : public std::vector<CDeclReplacementActionRecord> { -public: - CDeclReplacementActionRecordsLog::iterator find(const clang::DeclaratorDecl* ddecl_cptr) { - CDeclReplacementActionRecordsLog::iterator retval = (*this).end(); - CDeclReplacementActionRecordsLog::iterator iter = (*this).begin(); - for (CDeclReplacementActionRecordsLog::iterator iter = (*this).begin(); (*this).end() != iter; iter++) { - if ((*iter).get_ddecl_cptr() == ddecl_cptr) { - retval = iter; - break; + auto decl_context = DD->getDeclContext(); + if ((!decl_context) || (!SL.isValid())) { + assert(false); + retval.push_back(DD); + } else { + for (auto decl_iter = decl_context->decls_begin(); decl_iter != decl_context->decls_end(); decl_iter++) { + auto decl = (*decl_iter); + auto l_DD = dynamic_cast<const DeclaratorDecl*>(decl); + if (l_DD) { + auto DDSR = nice_source_range(l_DD->getSourceRange(), Rewrite); + SourceLocation l_SL = DDSR.getBegin(); + if (l_SL == SL) { + retval.push_back(l_DD); + } } } - return retval; } - CDeclReplacementActionRecordsLog::iterator find(const clang::SourceLocation& start_location) { - CDeclReplacementActionRecordsLog::iterator retval = (*this).end(); - for (CDeclReplacementActionRecordsLog::iterator iter = (*this).begin(); (*this).end() != iter; iter++) { - auto l_sl = (*iter).start_location(); - if ((start_location.isValid()) && (l_sl.isValid()) && (start_location == l_sl)) { - retval = iter; - break; - } - } - return retval; + if (0 == retval.size()) { + //assert(false); + int q = 7; } -}; -class CReplacementAction { + return retval; +} + +/* This class specifies a declaration and a level of "indirection"(/"dereference") relative to the declared + * object. For example, given the declaration "int **var1[5];", (*var1) and (**var1) are 1 and 2 "levels of + * indirection", respectively, relative to var1. */ +class CDDeclIndirection { public: - virtual ~CReplacementAction() {} - virtual void do_replacement(CState1& state1) const = 0; + CDDeclIndirection(const clang::DeclaratorDecl& ddecl_cref, size_t indirection_level = 0) : + m_ddecl_cptr(&ddecl_cref), m_indirection_level(indirection_level) {} + CDDeclIndirection(const CDDeclIndirection&) = default; + bool operator <(const CDDeclIndirection &rhs) const { + if (m_ddecl_cptr == rhs.m_ddecl_cptr) { + return (m_indirection_level < rhs.m_indirection_level); + } else { + return (m_ddecl_cptr < rhs.m_ddecl_cptr); + } + } + + const clang::DeclaratorDecl* m_ddecl_cptr = nullptr; + size_t m_indirection_level = 0; }; -class CDDeclReplacementAction : public CReplacementAction { +class CDDecl2ReplacementAction : public CReplacementAction { public: - CDDeclReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, - const clang::DeclaratorDecl& ddecl) : m_Rewrite(Rewrite), m_MR(MR), m_ddecl_cptr(&ddecl) { + CDDecl2ReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, + const CDDeclIndirection& ddecl_indirection) : m_Rewrite(Rewrite), m_MR(MR), m_ddecl_indirection(ddecl_indirection) { } - virtual ~CDDeclReplacementAction() {} + virtual ~CDDecl2ReplacementAction() {} virtual void do_replacement(CState1& state1) const = 0; - virtual const clang::DeclaratorDecl* get_ddecl_cptr() const { return m_ddecl_cptr; } + 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_cptr->getSourceRange(); + clang::SourceRange retval = m_ddecl_indirection.m_ddecl_cptr->getSourceRange(); return retval; } clang::SourceLocation start_location() { @@ -277,394 +315,690 @@ public: return retval; } std::string get_var_name() { - std::string retval = m_ddecl_cptr->getNameAsString(); + std::string retval = m_ddecl_indirection.m_ddecl_cptr->getNameAsString(); return retval; } Rewriter& m_Rewrite; const MatchFinder::MatchResult m_MR; - const clang::DeclaratorDecl* m_ddecl_cptr = nullptr; + CDDeclIndirection m_ddecl_indirection; }; -class CArrayReplacementAction : public CDDeclReplacementAction { +class CArray2ReplacementAction : public CDDecl2ReplacementAction { public: - using CDDeclReplacementAction::CDDeclReplacementAction; - virtual ~CArrayReplacementAction() {} + using CDDecl2ReplacementAction::CDDecl2ReplacementAction; + virtual ~CArray2ReplacementAction() {} }; -class CDynamicArrayReplacementAction : public CArrayReplacementAction { +class CDynamicArray2ReplacementAction : public CArray2ReplacementAction { public: - using CArrayReplacementAction::CArrayReplacementAction; - virtual ~CDynamicArrayReplacementAction() {} + using CArray2ReplacementAction::CArray2ReplacementAction; + virtual ~CDynamicArray2ReplacementAction() {} }; -class CSetArrayPointerToNullReplacementAction : public CDynamicArrayReplacementAction { +class CSetArrayPointerToNull2ReplacementAction : public CDynamicArray2ReplacementAction { public: - CSetArrayPointerToNullReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const clang::DeclaratorDecl& ddecl, - const BinaryOperator* BO, const DeclRefExpr* DRE, const MemberExpr* ME) -: CDynamicArrayReplacementAction(Rewrite, MR, ddecl), m_BO(BO), m_DRE(DRE), m_ME(ME) { + 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 ~CSetArrayPointerToNullReplacementAction() {} + virtual ~CSetArrayPointerToNull2ReplacementAction() {} - virtual void do_replacement(CState1& state1) const { - Rewriter &Rewrite = m_Rewrite; - const MatchFinder::MatchResult &MR = m_MR; - const BinaryOperator* BO = m_BO; - const Expr* RHS = nullptr; - const Expr* LHS = nullptr; - if (BO != nullptr) { - RHS = BO->getRHS(); - LHS = BO->getLHS(); - } - const DeclRefExpr* DRE = m_DRE; - const MemberExpr* ME = m_ME; + virtual void do_replacement(CState1& state1) const; - if ((BO != nullptr) && (RHS != nullptr) && (LHS != nullptr) && (DRE != nullptr)) - { - auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); - SourceLocation BOSL = BOSR.getBegin(); - SourceLocation BOSLE = BOSR.getEnd(); + 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; +}; - ASTContext *const ASTC = MR.Context; - FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL); +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() {} - SourceManager &SM = ASTC->getSourceManager(); + virtual void do_replacement(CState1& state1) const; - 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; - } + 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; +}; - if (filtered_out_by_location(MR, BOSL)) { - return void(); +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 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) { + auto range = base_class::equal_range(ddecl_indirection); + while (range.first != range.second) { + for (auto iter = range.first; range.second != iter; iter++) { + (*((*iter).second)).do_replacement(state1); } + base_class::erase(range.first, range.second); + range = base_class::equal_range(ddecl_indirection); + } + } +}; - Expr::NullPointerConstantKind kind = RHS->isNullPointerConstant(*ASTC, Expr::NullPointerConstantValueDependence()); - if (clang::Expr::NPCK_NotNull != kind) { - auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); - std::string lhs_source_text; - if (lhs_source_range.isValid()) { - lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); - //auto lhs_source_text_sans_ws = with_whitespace_removed(lhs_source_text); +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)); + } +}; - QualType QT; - std::string element_type_str; - clang::SourceRange decl_source_range; - std::string variable_name; - std::string bo_replacement_code; - const clang::DeclaratorDecl* DD = nullptr; +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)); + } +}; - auto decl = DRE->getDecl(); - auto VD = dynamic_cast<const VarDecl*>(decl); +class CIndirectionState { +public: + CIndirectionState(std::string original, std::string current) + : m_original(original), m_current(current) {} + CIndirectionState(const CIndirectionState& src) = default; + std::string m_original; + std::string m_current; +}; - const clang::FieldDecl* FD = nullptr; - if (nullptr != ME) { - auto member_decl = ME->getMemberDecl(); - FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); - } - if (nullptr != FD) { - DD = FD; +class CIndirectionStateStack : public std::vector<CIndirectionState> {}; - auto field_decl_source_range = nice_source_range(FD->getSourceRange(), Rewrite); - auto field_decl_source_location_str = field_decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string field_decl_source_text; - if (field_decl_source_range.isValid()) { - field_decl_source_text = Rewrite.getRewrittenText(field_decl_source_range); - decl_source_range = field_decl_source_range; - } else { - return; - } - QT = FD->getType(); - variable_name = FD->getNameAsString(); - } else if (nullptr != VD) { - DD = VD; - auto decl_source_range = nice_source_range(VD->getSourceRange(), Rewrite); +/* Given a type and an (empty) CIndirectionStateStack, this function will fill the stack with indications of + * whether each level of indirection (if any) of the type is of the pointer or the array variety. Pointers + * can, of course, function as arrays, but context is required to identify those situations. Such identification + * is not done in this function. It is done elsewhere. */ +const clang::QualType& populateQTypeIndirectionStack(CIndirectionStateStack& stack, const clang::QualType& qtype, int depth = 0) { + std::string qtype_str = qtype.getAsString(); + auto TP = qtype.getTypePtr(); - auto qualified_name = VD->getQualifiedNameAsString(); - static const std::string mse_namespace_str1 = "mse::"; - static const std::string mse_namespace_str2 = "::mse::"; - if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) - || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { - return; - } + if (TP->isArrayType()) { + auto type_class = qtype->getTypeClass(); + if (clang::Type::Decayed == type_class) { + int q = 5; + } else if (clang::Type::ConstantArray == type_class) { + int q = 5; + } - QT = VD->getType(); - variable_name = VD->getNameAsString(); - } else { - int q = 7; - } + const clang::ArrayType* ATP = TP->getAsArrayTypeUnsafe(); + if (ATP) { + clang::QualType QT = ATP->getElementType(); + auto l_TP = QT.getTypePtr(); + auto l_type_str = QT.getAsString(); - if (nullptr != DD) { - if (true) { - if (true) { - bo_replacement_code = lhs_source_text; - bo_replacement_code += ".resize(0)"; - - auto BOSR = clang::SourceRange(BOSL, BOSLE); - if (ConvertToSCPP && (BOSR.isValid())) { - auto res2 = Rewrite.ReplaceText(BOSR, bo_replacement_code); - int q = 3; - } else { - int q = 7; - } - } else { - int q = 5; - } - } + stack.push_back(CIndirectionState("native array", "native array")); + + return populateQTypeIndirectionStack(stack, QT, depth+1); + } else { + assert(false); + } + } else if (qtype->isPointerType()) { + auto type_class = qtype->getTypeClass(); + if (clang::Type::Decayed == type_class) { + int q = 5; + } else if (clang::Type::Pointer == type_class) { + int q = 5; + } + + if (llvm::isa<const clang::PointerType>(qtype)) { + auto PQT = llvm::cast<const clang::PointerType>(qtype); + if (PQT) { + int q = 5; + } else { + int q = 5; + } + } else { + int q = 5; + } + + clang::QualType QT = qtype->getPointeeType(); + auto l_type_str = QT.getAsString(); + + stack.push_back(CIndirectionState("native pointer", "native pointer")); + + return populateQTypeIndirectionStack(stack, QT, depth+1); + } + return qtype; +} + +/* Given an expression (in the form of a clang::Stmt) and an (empty) (string) stack, + * this function will fill the stack with indications of whether each level of indirection + * (if any) (in the expression) is a pointer dereference or an array subscript. */ +const clang::Expr* populateStmtIndirectionStack(std::vector<std::string>& stack, const clang::Stmt& stmt, int depth = 0) { + const clang::Expr* retval = nullptr; + const clang::Stmt* ST = &stmt; + auto stmt_class = ST->getStmtClass(); + auto stmt_class_name = ST->getStmtClassName(); + bool process_child_flag = false; + if (clang::Stmt::StmtClass::ArraySubscriptExprClass == stmt_class) { + stack.push_back("ArraySubscriptExpr"); + process_child_flag = true; + } else if (clang::Stmt::StmtClass::UnaryOperatorClass == stmt_class) { + auto UO = llvm::cast<const clang::UnaryOperator>(ST); + if (UO) { + if (clang::UnaryOperatorKind::UO_Deref == UO->getOpcode()) { + stack.push_back("Deref"); + process_child_flag = true; + } else { + auto QT = UO->getType(); + const clang::Type* TP = QT.getTypePtr(); + if (TP && TP->isPointerType()) { + if ((clang::UnaryOperatorKind::UO_PreInc == UO->getOpcode()) + || (clang::UnaryOperatorKind::UO_PostInc == UO->getOpcode()) + || (clang::UnaryOperatorKind::UO_PreDec == UO->getOpcode()) + || (clang::UnaryOperatorKind::UO_PostDec == UO->getOpcode())) { + /* Incrementing/decrementing a pointer type is pointer arithmetic and + * implies the pointer is being used as an array iterator. */ + /* To do: modify the stack entry to reflect this. */ } - int q = 5; + } + } + } else { + assert(false); + } + } else if ((clang::Stmt::StmtClass::ImplicitCastExprClass == stmt_class)) { + auto ICE = llvm::cast<const clang::ImplicitCastExpr>(ST); + if (ICE) { + auto cast_kind_name = ICE->getCastKindName(); + auto cast_kind = ICE->getCastKind(); + if ((clang::CK_FunctionToPointerDecay == cast_kind)) { + process_child_flag = false; + } else { + if ((clang::CK_ArrayToPointerDecay == cast_kind) || (clang::CK_LValueToRValue == cast_kind)) { + process_child_flag = true; } else { - int q = 5; + process_child_flag = true; } - int q = 5; } + } else { assert(false); } + } else if ((clang::Stmt::StmtClass::ParenExprClass == stmt_class)) { + process_child_flag = true; + } else if(clang::Stmt::StmtClass::DeclRefExprClass == stmt_class) { + auto DRE = llvm::cast<const clang::DeclRefExpr>(ST); + if (DRE) { + retval = DRE; + process_child_flag = true; + } else { + assert(false); + } + } else if(clang::Stmt::StmtClass::MemberExprClass == stmt_class) { + auto ME = llvm::cast<const clang::MemberExpr>(ST); + if (ME) { + retval = ME; + } else { + assert(false); } } - - const BinaryOperator* m_BO; - const DeclRefExpr* m_DRE; - const MemberExpr* m_ME; -}; - -std::string tolowerstr(const std::string& a) { - std::string retval; - for (const auto& ch : a) { - retval += tolower(ch); + if (process_child_flag) { + auto child_iter = ST->child_begin(); + if (child_iter != ST->child_end()) { + if (nullptr != (*child_iter)) { + const auto noted_stack_size = stack.size(); + auto res = populateStmtIndirectionStack(stack, *(*child_iter), depth+1); + if ((nullptr == retval) || (stack.size() > noted_stack_size)) { + retval = res; + } + } else { + assert(false); + } + } else { + int q = 5; + } } return retval; } -class CFreeDynamicArrayReplacementAction : public CDynamicArrayReplacementAction { +class CDDeclConversionState { public: - CFreeDynamicArrayReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const clang::DeclaratorDecl& ddecl, - const CallExpr* CE, const DeclRefExpr* DRE, const MemberExpr* ME) -: CDynamicArrayReplacementAction(Rewrite, MR, ddecl), m_CE(CE), m_DRE(DRE), m_ME(ME) { + CDDeclConversionState(const clang::DeclaratorDecl& ddecl) : m_ddecl_cptr(&ddecl) { + QualType QT = ddecl.getType(); + m_direct_qtype = populateQTypeIndirectionStack(m_indirection_state_stack, QT); + //std::reverse(m_indirection_state_stack.begin(), m_indirection_state_stack.end()); } - virtual ~CFreeDynamicArrayReplacementAction() {} + 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; +}; - virtual void do_replacement(CState1& state1) const { - Rewriter &Rewrite = m_Rewrite; - const MatchFinder::MatchResult &MR = m_MR; - const CallExpr* CE = m_CE; - const DeclRefExpr* DRE = m_DRE; - const MemberExpr* ME = m_ME; +class CDDeclConversionStateMap : public std::map<const clang::DeclaratorDecl*, CDDeclConversionState> { +public: + std::pair<iterator, bool> insert(const clang::DeclaratorDecl& ddecl) { + value_type item(&ddecl, CDDeclConversionState(ddecl)); + return std::map<const clang::DeclaratorDecl*, CDDeclConversionState>::insert(item); + } +}; - if ((CE != nullptr) && (DRE != nullptr)) - { - auto CESR = nice_source_range(CE->getSourceRange(), Rewrite); - SourceLocation CESL = CESR.getBegin(); - SourceLocation CESLE = CESR.getEnd(); +class CState1 { +public: + /* This container holds (potential) actions that are meant to be executed if/when + * their corresponding item is determined to be a dynamic array. */ + CDynamicArray2ReplacementActionMap m_dynamic_array2_contingent_replacement_map; - ASTContext *const ASTC = MR.Context; - FullSourceLoc FCESL = ASTC->getFullLoc(CESL); + /* This container holds (potential) actions that are meant to be executed if/when + * their corresponding item is determined to be an array (dynamic or otherwise). */ + CArray2ReplacementActionMap m_array2_contingent_replacement_map; - SourceManager &SM = ASTC->getSourceManager(); + /* This container holds information about each item's original type and which + * type it might be converted to. */ + CDDeclConversionStateMap m_ddecl_conversion_state_map; +}; - auto source_location_str = CESL.printToString(*MR.SourceManager); - std::string source_text; - if (CESL.isValid() && CESLE.isValid()) { - source_text = Rewrite.getRewrittenText(SourceRange(CESL, CESLE)); - } else { - return; - } +class CDeclarationReplacementCodeItem { +public: + std::string m_replacement_code; + std::string m_action_species; +}; +static CDeclarationReplacementCodeItem generate_declaration_replacement_code(const DeclaratorDecl* DD, Rewriter &Rewrite, CDDeclConversionStateMap& ddecl_conversion_state_map, std::string options_str = "") { + CDeclarationReplacementCodeItem retval; - if (filtered_out_by_location(MR, CESL)) { - return void(); - } + auto res1 = ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; - auto function_decl = CE->getDirectCallee(); - auto num_args = CE->getNumArgs(); - if (function_decl && (1 == num_args)) { - { - std::string function_name = function_decl->getNameAsString(); - static const std::string free_str = "free"; - auto lc_function_name = tolowerstr(function_name); - bool ends_with_free = ((lc_function_name.size() >= free_str.size()) - && (0 == lc_function_name.compare(lc_function_name.size() - free_str.size(), free_str.size(), free_str))); - if (ends_with_free) { - auto iter = CE->arg_begin(); - assert((*iter)->getType().getTypePtrOrNull()); - auto arg_source_range = nice_source_range((*iter)->getSourceRange(), Rewrite); - std::string arg_source_text; - if (arg_source_range.isValid()) { - arg_source_text = Rewrite.getRewrittenText(arg_source_range); - //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); - QualType QT; - std::string element_type_str; - clang::SourceRange decl_source_range; - std::string variable_name; - std::string ce_replacement_code; - const clang::DeclaratorDecl* DD = nullptr; + 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()); + if ("_Bool" == direct_qtype_str) { + direct_qtype_str = "bool"; + } else if ("const _Bool" == direct_qtype_str) { + direct_qtype_str = "const bool"; + } - auto decl = DRE->getDecl(); - DD = dynamic_cast<const DeclaratorDecl*>(decl); - auto VD = dynamic_cast<const VarDecl*>(decl); + clang::StorageDuration storage_duration = clang::StorageDuration::SD_Automatic; + bool has_dynamic_storage_duration = false; + bool is_a_temporary = false; + bool is_static = false; + bool is_a_function_parameter = false; + bool is_member = false; + bool is_vardecl = false; + std::string initialization_expr_str; - const clang::FieldDecl* FD = nullptr; - if (nullptr != ME) { - auto member_decl = ME->getMemberDecl(); - FD = dynamic_cast<const clang::FieldDecl*>(ME->getMemberDecl()); - } - if (nullptr != FD) { - DD = FD; - } else if (nullptr != VD) { - DD = VD; - } else { - int q = 7; - } + auto VD = dynamic_cast<const clang::VarDecl *>(DD); + if (VD) { + is_vardecl = true; + 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_a_function_parameter = (VD->isLocalVarDeclOrParm() && (!VD->isLocalVarDecl())); - if (nullptr != DD) { - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } - QT = DD->getType(); - variable_name = DD->getNameAsString(); + if (ddcs_ref.m_original_initialization_has_been_noted) { + initialization_expr_str = ddcs_ref.m_original_initialization_expr_str; + } else { + auto pInitExpr = VD->getInit(); + if (VD->hasInit() && pInitExpr) { + auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); + initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); + ddcs_ref.m_original_initialization_expr_str = initialization_expr_str; + } + ddcs_ref.m_original_initialization_has_been_noted = true; + } + } else { + auto FD = dynamic_cast<const clang::FieldDecl*>(DD); + if (FD) { + is_member = true; - auto qualified_name = DD->getQualifiedNameAsString(); - static const std::string mse_namespace_str1 = "mse::"; - static const std::string mse_namespace_str2 = "::mse::"; - if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) - || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { - return; - } + if (ddcs_ref.m_original_initialization_has_been_noted) { + initialization_expr_str = ddcs_ref.m_original_initialization_expr_str; + } else { + auto pInitExpr = FD->getInClassInitializer(); + if (FD->hasInClassInitializer() && pInitExpr) { + auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); + initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); + ddcs_ref.m_original_initialization_expr_str = initialization_expr_str; + } + ddcs_ref.m_original_initialization_has_been_noted = true; + } + } + } + ddcs_ref.m_original_initialization_has_been_noted = true; - if (true) { - ce_replacement_code = arg_source_text; - ce_replacement_code += ".resize(0)"; + std::string variable_name = DD->getNameAsString(); + std::string identifier_name_str; + auto pIdentifier = DD->getIdentifier(); + if (pIdentifier) { + identifier_name_str = pIdentifier->getName(); + } + if ("" == variable_name) { + int q = 7; + } - auto CESR = clang::SourceRange(CESL, CESLE); - if (ConvertToSCPP && (CESR.isValid())) { - auto res2 = Rewrite.ReplaceText(CESR, ce_replacement_code); - int q = 3; - } else { - int q = 7; - } - } + 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"; + } else { + suffix_str = "> " + suffix_str; + retval.m_action_species = "native pointer to TIPointerWithBundledVector"; + } + } + } else if ("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + 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; } - int q = 5; } else { int q = 5; } - 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"; + } 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 { + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "native pointer"; + } + } + } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[i].m_current) { + /* We'll just leaving it as a native pointer for now. Ultimately, this won't be the case. */ + //prefix_str = prefix_str + ""; + suffix_str = "* " + suffix_str; + retval.m_action_species = "malloc target"; + } + } + if (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; + if (("" == initializer_append_str) && ("" != initialization_expr_str)) { + initializer_append_str = " = " + initialization_expr_str; } + replacement_code += initializer_append_str; } + retval.m_replacement_code = replacement_code; + return retval; +} - const CallExpr* m_CE; - const DeclRefExpr* m_DRE; - const MemberExpr* m_ME; -}; +static void update_declaration(const DeclaratorDecl& ddecl, Rewriter &Rewrite, CState1& state1, std::string options_str = "") { + const DeclaratorDecl* DD = &ddecl; + auto SR = nice_source_range(DD->getSourceRange(), Rewrite); -static std::vector<const DeclaratorDecl*> IndividualDeclaratorDecls(const DeclaratorDecl* VD, Rewriter &Rewrite) { - std::vector<const DeclaratorDecl*> retval; + QualType QT = DD->getType(); + const clang::Type* TP = QT.getTypePtr(); + auto qtype_str = QT.getAsString(); - if (!VD) { - assert(false); - return retval; + std::string source_text; + if (SR.isValid()) { + source_text = Rewrite.getRewrittenText(SR); + if ("" == source_text) { + return; + } + } else { + return; } - auto SR = nice_source_range(VD->getSourceRange(), Rewrite); - SourceLocation SL = SR.getBegin(); - auto decl_context = VD->getDeclContext(); - if ((!decl_context) || (!SL.isValid())) { - assert(false); - retval.push_back(VD); - } else { - for (auto decl_iter = decl_context->decls_begin(); decl_iter != decl_context->decls_end(); decl_iter++) { - auto decl = (*decl_iter); - auto var_decl = dynamic_cast<const DeclaratorDecl*>(decl); - if (var_decl) { - auto VDSR = nice_source_range(var_decl->getSourceRange(), Rewrite); - SourceLocation l_SL = VDSR.getBegin(); - if (l_SL == SL) { - retval.push_back(var_decl); - } - } - } + std::string variable_name = DD->getNameAsString(); + + if (("" == variable_name) || (!TP)) { + return; } - if (0 == retval.size()) { - assert(false); + + if ((TP->isFunctionType()) || (false)) { + /* We don't handle function declarations yet. */ + return; } - return retval; -} + /* There may be multiple declarations in the same declaration statement. Replacing + * one of them requires replacing all of them together. */ + auto ddecls = IndividualDeclaratorDecls(DD, Rewrite); + if ((1 <= ddecls.size())/* && (ddecls.back() == DD)*/) { + if (2 <= ddecls.size()) { + int q = 5; + } + std::vector<std::string> action_species_list; + std::string replacement_code; + for (const auto& ddecl_cref : ddecls) { + auto res = generate_declaration_replacement_code(ddecl_cref, Rewrite, state1.m_ddecl_conversion_state_map, options_str); + action_species_list.push_back(res.m_action_species); + replacement_code += res.m_replacement_code; + replacement_code += "; \n"; + } + if (replacement_code.size() >= 3) { + replacement_code = replacement_code.substr(0, replacement_code.size() - 3); + } -class CMallocArrayReplacementAction : public CArrayReplacementAction { -public: - CMallocArrayReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR, const clang::DeclaratorDecl& ddecl, - const BinaryOperator* BO, const std::string& bo_replacement_code, const std::string& declaration_replacement_code) -: CArrayReplacementAction(Rewrite, MR, ddecl), m_BO(BO), m_DD(&ddecl), m_bo_replacement_code(bo_replacement_code), m_declaration_replacement_code(declaration_replacement_code) { + /* (Only) the source range of the last individual declaration in the declaration statement + * should encompass the whole statement. */ + auto last_ddecl = ddecls.back(); + auto last_decl_source_range = nice_source_range(last_ddecl->getSourceRange(), Rewrite); + + std::string last_decl_source_text; + if (last_decl_source_range.isValid()) { + last_decl_source_text = Rewrite.getRewrittenText(last_decl_source_range); + if ("" == last_decl_source_text) { + return; + } + } else { + return; + } + + if (ConvertToSCPP && last_decl_source_range.isValid() && (3 <= replacement_code.size())) { + auto res = Rewrite.ReplaceText(last_decl_source_range, replacement_code); + } else { + int q = 7; + } + } else { + int q = 7; } - virtual ~CMallocArrayReplacementAction() {} +} - virtual void do_replacement(CState1& state1) const; +void CSetArrayPointerToNull2ReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + const BinaryOperator* BO = m_BO; + const DeclaratorDecl* DD = m_DD; - 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; - std::string m_declaration_replacement_code; -}; + if ((BO != nullptr) && (DD != nullptr)) + { + auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } -class CDDeclReplacementActionMap : public std::multimap<const clang::DeclaratorDecl*, std::shared_ptr<CDDeclReplacementAction>> { -public: - typedef std::multimap<const clang::DeclaratorDecl*, std::shared_ptr<CDDeclReplacementAction>> base_class; - iterator insert( const std::shared_ptr<CDDeclReplacementAction>& cr_shptr ) { - iterator retval(end()); - if (!cr_shptr) { assert(false); } else { - value_type val((*cr_shptr).get_ddecl_cptr(), cr_shptr); - retval = base_class::insert(val); + if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { + + update_declaration(*DD, Rewrite, state1); + + //state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + //state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + + auto res2 = Rewrite.ReplaceText(BOSR, m_bo_replacement_code); + int q = 3; + } else { + int q = 7; } - return retval; } - void do_and_dispose_matching_replacements(CState1& state1, const clang::DeclaratorDecl& ddecl) { - auto DD = &ddecl; - auto range = base_class::equal_range(DD); - while (range.first != range.second) { - for (auto iter = range.first; range.second != iter; iter++) { - (*((*iter).second)).do_replacement(state1); - } - base_class::erase(range.first, range.second); - range = base_class::equal_range(DD); +} + +void CFreeDynamicArray2ReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + const CallExpr* CE = m_CE; + const DeclaratorDecl* DD = m_DD; + + if ((CE != nullptr) && (DD != nullptr)) + { + auto CESR = nice_source_range(CE->getSourceRange(), Rewrite); + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; } - } -}; -class CDynamicArrayReplacementActionMap : public CDDeclReplacementActionMap { -public: - iterator insert( const std::shared_ptr<CDynamicArrayReplacementAction>& cr_shptr ) { - return CDDeclReplacementActionMap::insert(static_cast<std::shared_ptr<CDDeclReplacementAction> >(cr_shptr)); - } -}; + if (ConvertToSCPP && decl_source_range.isValid() && (CESR.isValid())) { -class CArrayReplacementActionMap : public CDDeclReplacementActionMap { -public: - iterator insert( const std::shared_ptr<CArrayReplacementAction>& cr_shptr ) { - return CDDeclReplacementActionMap::insert(static_cast<std::shared_ptr<CDDeclReplacementAction> >(cr_shptr)); - } -}; + update_declaration(*DD, Rewrite, state1); -class CState1 { -public: - CDeclReplacementActionRecordsLog m_decl_replacement_action_records_log; - CDynamicArrayReplacementActionMap m_dynamic_array_contingent_replacement_map; - CArrayReplacementActionMap m_array_contingent_replacement_map; -}; + //state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + //state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + + auto res2 = Rewrite.ReplaceText(CESR, m_ce_replacement_code); + int q = 3; + } else { + int q = 7; + } + } +} -void CMallocArrayReplacementAction::do_replacement(CState1& state1) const { +void CMallocArray2ReplacementAction::do_replacement(CState1& state1) const { Rewriter &Rewrite = m_Rewrite; const MatchFinder::MatchResult &MR = m_MR; const BinaryOperator* BO = m_BO; @@ -682,24 +1016,13 @@ void CMallocArrayReplacementAction::do_replacement(CState1& state1) const { return; } - auto decls = IndividualDeclaratorDecls(DD, Rewrite); - if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { - if ((3 <= m_declaration_replacement_code.size())) { - for (const auto& decl : decls) { - auto iter = state1.m_decl_replacement_action_records_log.find(decl); - if (state1.m_decl_replacement_action_records_log.end() != iter) { - /* This declaration had already been replaced. We're just going to - * overwrite it. */ - state1.m_decl_replacement_action_records_log.erase(iter); - } - CDeclReplacementActionRecord action_record(Rewrite, *decl, m_declaration_replacement_code, "pointer targeting heap allocated array to mse vector iterator"); - state1.m_decl_replacement_action_records_log.push_back(action_record); - state1.m_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(state1, *decl); - } - auto res = Rewrite.ReplaceText(decl_source_range, m_declaration_replacement_code); - } + update_declaration(*DD, Rewrite, state1); + + //state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + //state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + auto res2 = Rewrite.ReplaceText(BOSR, m_bo_replacement_code); int q = 3; } else { @@ -708,6 +1031,42 @@ void CMallocArrayReplacementAction::do_replacement(CState1& state1) const { } } +void CMallocInitializerArray2ReplacementAction::do_replacement(CState1& state1) const { + Rewriter &Rewrite = m_Rewrite; + const MatchFinder::MatchResult &MR = m_MR; + const DeclStmt* DS = m_DS; + const DeclaratorDecl* DD = m_DD; + + if ((DS != nullptr) && (DD != nullptr)) + { + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + + auto res1 = state1.m_ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + + ddcs_ref.m_initializer_info_str = m_initializer_info_str; + + if (ConvertToSCPP && decl_source_range.isValid()) { + update_declaration(*DD, Rewrite, state1); + + //state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + //state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(state1, (*this).ddecl_indirection_cref()); + + int q = 3; + } else { + int q = 7; + } + } +} + /**********************************************************************************************************************/ class MCSSSArrayToPointerDecay : public MatchFinder::MatchCallback { @@ -812,26 +1171,28 @@ public: private: Rewriter &Rewrite; }; + /**********************************************************************************************************************/ -class MCSSSVarDecl : public MatchFinder::MatchCallback + +class MCSSSVarDecl2 : public MatchFinder::MatchCallback { public: - MCSSSVarDecl (Rewriter &Rewrite, CState1& state1) -: Rewrite(Rewrite), m_state1(state1) {} + MCSSSVarDecl2 (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) { - if ((MR.Nodes.getNodeAs<clang::VarDecl>("mcsssvardecl") != nullptr)) + const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssvardecl"); + if ((DD != nullptr)) { - const VarDecl* VD = MR.Nodes.getNodeAs<clang::VarDecl>("mcsssvardecl"); - - auto SR = nice_source_range(VD->getSourceRange(), Rewrite); + auto SR = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_range = SR; SourceLocation SL = SR.getBegin(); SourceLocation SLE = SR.getEnd(); - QualType QT = VD->getType(); - + QualType QT = DD->getType(); const clang::Type* TP = QT.getTypePtr(); + auto qtype_str = QT.getAsString(); ASTContext *const ASTC = MR.Context; FullSourceLoc FSL = ASTC->getFullLoc(SL); @@ -840,8 +1201,8 @@ public: auto source_location_str = SL.printToString(*MR.SourceManager); std::string source_text; - if (SL.isValid() && SLE.isValid()) { - source_text = Rewrite.getRewrittenText(SourceRange(SL, SLE)); + if (SR.isValid()) { + source_text = Rewrite.getRewrittenText(SR); } else { return; } @@ -850,102 +1211,28 @@ public: return void(); } - auto storage_duration = VD->getStorageDuration(); - bool has_dynamic_storage_duration = (clang::StorageDuration::SD_Dynamic == storage_duration); - bool is_a_temporary = (clang::StorageDuration::SD_FullExpression == storage_duration); - bool is_static = (clang::StorageDuration::SD_Static == storage_duration); - bool is_a_function_parameter = (VD->isLocalVarDeclOrParm() && (!VD->isLocalVarDecl())); - - auto variable_name = VD->getName(); - auto variable_name2 = VD->getNameAsString(); - std::string identifier_name_str; - auto pIdentifier = VD->getIdentifier(); - if (pIdentifier) { - identifier_name_str = pIdentifier->getName(); - } + std::string variable_name = DD->getNameAsString(); - std::string initialization_expr_str; - auto pInitExpr = VD->getInit(); - if (VD->hasInit() && pInitExpr) { - auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); - initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + int q = 5; + //return; } - if (TP->isArrayType()) { - auto ATP = static_cast<const clang::ArrayType*>(TP); - auto element_type = ATP->getElementType(); - auto elementSplitQualType = element_type.split(); - auto element_type_str = clang::QualType::getAsString(elementSplitQualType); - - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::mstd::array<"; - replacement_code += element_type_str; - replacement_code += ", "; - - if (TP->isConstantArrayType()) { - auto CATP = static_cast<const clang::ConstantArrayType*>(TP); - if (!CATP) { - assert(false); - } else { - auto array_size = CATP->getSize(); - - 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)); - - replacement_code += array_size_expression_text; - int q = 3; - } else { - int q = 7; - } - int q = 5; - } - } else if (TP->isVariableArrayType()) { - auto VATP = static_cast<const clang::VariableArrayType*>(TP); - if (!VATP) { - assert(false); - } else { - auto size_expr = VATP->getSizeExpr(); - } - } - - replacement_code += "> "; - std::string new_array_variable_name = variable_name; - new_array_variable_name += "_array"; - replacement_code += new_array_variable_name; - if ("" != initialization_expr_str) { - replacement_code += " = "; - replacement_code += initialization_expr_str; + 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; + for (size_t i = 0; (i < ddcs_ref.m_indirection_state_stack.size()); i += 1) { + if ("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); } - replacement_code += "; \n"; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "auto "; - replacement_code += variable_name; - replacement_code += " = "; - replacement_code += new_array_variable_name; - replacement_code += ".begin()"; - if (ConvertToSCPP && SL.isValid() && SLE.isValid()) { - auto res = Rewrite.ReplaceText(SourceRange(SL, SLE), replacement_code); - CDeclReplacementActionRecord action_record(Rewrite, *VD, replacement_code, "native to mse array"); - m_state1.m_decl_replacement_action_records_log.push_back(action_record); - m_state1.m_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, *VD); - int q = 3; - } else { - int q = 7; - } - m_state1.m_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, *VD); - int q = 5; - } else { - ; } + update_declaration(*DD, Rewrite, m_state1); } } @@ -959,117 +1246,20 @@ private: }; /**********************************************************************************************************************/ -class CRandomAccessIteratorFromPointerDDeclRetval { -public: - std::string m_replacement_code; - std::string m_action_species; -}; -static CRandomAccessIteratorFromPointerDDeclRetval RandomAccessIteratorFromPointerDDecl(const DeclaratorDecl* DD, Rewriter &Rewrite) { - CRandomAccessIteratorFromPointerDDeclRetval retval; - - QualType QT = DD->getType(); - - const clang::Type* TP = QT.getTypePtr(); - - clang::StorageDuration storage_duration = clang::StorageDuration::SD_Automatic; - bool has_dynamic_storage_duration = false; - bool is_a_temporary = false; - bool is_static = false; - bool is_a_function_parameter = false; - std::string initialization_expr_str; - - auto VD = dynamic_cast<const clang::VarDecl *>(DD); - if (VD) { - 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_a_function_parameter = (VD->isLocalVarDeclOrParm() && (!VD->isLocalVarDecl())); - auto pInitExpr = VD->getInit(); - if (VD->hasInit() && pInitExpr) { - auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); - initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); - } - } - - auto variable_name = DD->getNameAsString(); - std::string identifier_name_str; - auto pIdentifier = DD->getIdentifier(); - if (pIdentifier) { - identifier_name_str = pIdentifier->getName(); - } - - bool replacement_code_generated = false; - if (TP->isPointerType()) { - auto TPP = static_cast<const clang::PointerType*>(TP); - if (TPP) { - auto target_type = TPP->getPointeeType(); - - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - if (("char" != type_str) && ("const char" != type_str)) { - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::TNullableAnyRandomAccessIterator<"; - replacement_code += type_str; - replacement_code += "> "; - replacement_code += variable_name; - - if ("" != initialization_expr_str) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval.m_replacement_code = replacement_code; - retval.m_action_species = "pointer to random access iterator"; - replacement_code_generated = true; - } else { - int q = 3; - } - } else { - assert(false); - int q = 1; - } - } - - if (!replacement_code_generated) { - auto splitQualType = QT.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += type_str; - replacement_code += " "; - replacement_code += variable_name; - - if ("" != initialization_expr_str) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval.m_replacement_code = replacement_code; - retval.m_action_species = "char*"; - replacement_code_generated = true; - } - return retval; -} - -class MCSSSPointerArithmetic : public MatchFinder::MatchCallback +class MCSSSPointerArithmetic2 : public MatchFinder::MatchCallback { public: - MCSSSPointerArithmetic (Rewriter &Rewrite, CState1& state1) + MCSSSPointerArithmetic2 (Rewriter &Rewrite, CState1& state1) : Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) { const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcssspointerarithmetic"); const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcssspointerarithmetic2"); + const Expr* E = MR.Nodes.getNodeAs<clang::Expr>("mcssspointerarithmetic3"); - if (DRE != nullptr) + if ((DRE != nullptr) && (E != nullptr)) { const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcssspointerarithmetic"); @@ -1094,7 +1284,6 @@ public: return; } - if (filtered_out_by_location(MR, SL)) { return void(); } @@ -1133,42 +1322,83 @@ public: return; } - auto iter = m_state1.m_decl_replacement_action_records_log.find(DD); - if (m_state1.m_decl_replacement_action_records_log.end() != iter) { - /* This variable declaration has already been processed. Probably. */ - 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; - auto var_decls = IndividualDeclaratorDecls(DD, Rewrite); - if ((1 <= var_decls.size()) && (var_decls.back() == DD)) { - std::vector<std::string> action_species_list; - std::string replacement_code; - for (const auto& var_decl : var_decls) { - auto res = RandomAccessIteratorFromPointerDDecl(var_decl, Rewrite); - action_species_list.push_back(res.m_action_species); - replacement_code += res.m_replacement_code; - replacement_code += "; \n"; - } - if (replacement_code.size() >= 3) { - replacement_code = replacement_code.substr(0, replacement_code.size() - 3); - } + const clang::Type* TP = QT.getTypePtr(); + auto type_str = QT.getAsString(); - if (ConvertToSCPP && decl_source_range.isValid() && (3 <= replacement_code.size())) { - auto res = Rewrite.ReplaceText(decl_source_range, replacement_code); + auto expr_SR = nice_source_range(E->getSourceRange(), Rewrite); + std::string expr_source_location_str; + std::string expr_source_text; + if (expr_SR.isValid()) { + expr_source_location_str = expr_SR.getBegin().printToString(*MR.SourceManager); + expr_source_text = Rewrite.getRewrittenText(expr_SR); + } else { + int q = 3; + } - for (auto var_decl : var_decls) { - assert(1 <= action_species_list.size()); - CDeclReplacementActionRecord action_record(Rewrite, *var_decl, replacement_code, action_species_list.front()); - action_species_list.erase(action_species_list.begin()); - m_state1.m_decl_replacement_action_records_log.push_back(action_record); - m_state1.m_array_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, *var_decl); + std::vector<std::string> stmt_indirection_stack; + const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, *E); + std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); + stmt_indirection_stack.push_back("pointer arithmetic"); + if (expr2) { + std::string expr2_stmt_class_name; + expr2_stmt_class_name = expr2->getStmtClassName(); + const DeclaratorDecl* expr2_DD = nullptr; + if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { + auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); + if (expr2_DRE) { + auto expr2_decl = expr2_DRE->getDecl(); + expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); + } else { assert(false); } + } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { + auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); + if (expr2_ME) { + auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); + if (expr2_FD) { + expr2_DD = expr2_FD; + } else { assert(false); } + } else { assert(false); } + } + if (expr2_DD) { + auto expr2_QT = expr2_DD->getType(); + const clang::Type* expr2_TP = expr2_QT.getTypePtr(); + auto expr2_type_str = clang::QualType::getAsString(expr2_QT.split()); + std::string expr2_variable_name = expr2_DD->getNameAsString(); + if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { + 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 (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; + update_declaration_flag = true; + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } + } else if ("malloc target" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + update_declaration_flag = true; + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } + } + } + } else { + int q = 5; } - int q = 3; - } else { - int q = 7; } + int q = 5; } else { - int q = 7; + int q = 5; + } + + if (update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); } } } @@ -1181,356 +1411,24 @@ private: /**********************************************************************************************************************/ -class CIndirectionState { -public: - CIndirectionState(std::string original, std::string current) - : m_original(original), m_current(current) {} - CIndirectionState(const CIndirectionState& src) = default; - std::string m_original; - std::string m_current; -}; - -std::vector<CIndirectionState>& populateTypeIndirectionStack(std::vector<CIndirectionState>& stack, const clang::Type& type, int depth = 0) { - auto TP = &type; - if (TP->isArrayType()) { - const clang::ArrayType* ATP = TP->getAsArrayTypeUnsafe(); - if (ATP) { - auto QT = ATP->getElementType(); - auto l_TP = QT.getTypePtr(); - auto type_str = clang::QualType::getAsString(QT.split()); - - stack.push_back(CIndirectionState("native array", "native array")); - - return populateTypeIndirectionStack(stack, *l_TP, depth+1); - } else { - assert(false); - } - } else if (TP->isPointerType()) { - auto PTP = static_cast<const clang::PointerType*>(TP); - if (PTP) { - auto QT = PTP->getPointeeType(); - auto l_TP = QT.getTypePtr(); - auto type_str = clang::QualType::getAsString(QT.split()); - - stack.push_back(CIndirectionState("native pointer", "native pointer")); - - return populateTypeIndirectionStack(stack, *l_TP, depth+1); - } else { - assert(false); - } - } - return stack; -} - -std::vector<std::string>& populateStmtIndirectionStack(std::vector<std::string>& stack, const clang::Stmt& stmt, int depth = 0) { - const clang::Stmt* ST = &stmt; - auto stmt_class = ST->getStmtClass(); - if (clang::Stmt::StmtClass::ArraySubscriptExprClass == stmt_class) { - auto ASE = static_cast<const clang::ArraySubscriptExpr*>(ST); - auto BE = ASE->getBase(); - stack.push_back("ArraySubscriptExpr"); - } else if (clang::Stmt::StmtClass::UnaryOperatorClass == stmt_class) { - auto UO = static_cast<const clang::UnaryOperator*>(ST); - if (UO) { - if (clang::UnaryOperatorKind::UO_Deref == UO->getOpcode()) { - stack.push_back("Deref"); - } - } else { - assert(false); - } - } else if(clang::Stmt::StmtClass::DeclRefExprClass == stmt_class) { - auto DRE = static_cast<const clang::DeclRefExpr*>(ST); - if (DRE) { - ; - } else { - assert(false); - } - } else if(clang::Stmt::StmtClass::MemberExprClass == stmt_class) { - auto ME = static_cast<const clang::MemberExpr*>(ST); - if (ME) { - ; - } else { - assert(false); - } - } - auto child_iter = ST->child_begin(); - if (child_iter != ST->child_end()) { - return populateStmtIndirectionStack(stack, *(*child_iter), depth+1); - } else { - return stack; - } -} - -static std::string IPointerFromPointerDecl(const DeclaratorDecl* DD, Rewriter &Rewrite, const std::string& notes_str = "") { - std::string retval; - - assert(DD); - auto DDSR = nice_source_range(DD->getSourceRange(), Rewrite); - std::string decl_source_text = Rewrite.getRewrittenText(DDSR); - - QualType QT = DD->getType(); - - const clang::Type* TP = QT.getTypePtr(); - - auto type_str = clang::QualType::getAsString(QT.split()); - clang::StorageDuration storage_duration = clang::StorageDuration::SD_Automatic; - bool has_dynamic_storage_duration = false; - bool is_a_temporary = false; - bool is_static = false; - bool is_a_function_parameter = false; - std::string initialization_expr_str; - - auto FD = dynamic_cast<const clang::FieldDecl *>(DD); - auto VD = dynamic_cast<const clang::VarDecl *>(DD); - if (VD) { - 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_a_function_parameter = (VD->isLocalVarDeclOrParm() && (!VD->isLocalVarDecl())); - - auto pInitExpr = VD->getInit(); - if (VD->hasInit() && pInitExpr) { - auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); - initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); - } - } else if (FD) { - /* Just placeholder code for now. Haven't thought about this case yet. */ - auto pInitExpr = FD->getInClassInitializer(); - if (FD->hasInClassInitializer() && pInitExpr) { - auto init_expr_source_range = nice_source_range(pInitExpr->getSourceRange(), Rewrite); - initialization_expr_str = Rewrite.getRewrittenText(init_expr_source_range); - } - } - - auto variable_name = DD->getNameAsString(); - std::string identifier_name_str; - auto pIdentifier = DD->getIdentifier(); - if (pIdentifier) { - identifier_name_str = pIdentifier->getName(); - } - - bool replacement_code_generated = false; - if ("array element" == notes_str) { - if (TP->isArrayType()) { - std::string array_size_str; - bool invalid_flag = false; - size_t array_size_str_start_index = decl_source_text.size(); - size_t array_size_str_end_index = 0; - for (size_t index1 = 0; index1 < decl_source_text.size(); index1 += 1) { - if ('[' == decl_source_text[index1]) { - array_size_str_start_index = index1 + 1; - break; - } - } - if (array_size_str_start_index >= decl_source_text.size()) { - invalid_flag = true; - } - for (size_t index1 = decl_source_text.size(); index1 > 1; index1 -= 1) { - if (']' == decl_source_text[index1 - 1]) { - array_size_str_end_index = index1 - 1; - break; - } - } - if (array_size_str_end_index == 0) { - invalid_flag = true; - } - if (invalid_flag || (array_size_str_start_index >= array_size_str_end_index)) { - invalid_flag = true; - } else { - array_size_str = decl_source_text.substr(array_size_str_start_index, array_size_str_end_index - array_size_str_start_index); - - const clang::ArrayType* ATP = TP->getAsArrayTypeUnsafe(); - if (ATP) { - QT = ATP->getElementType(); - TP = QT.getTypePtr(); - type_str = clang::QualType::getAsString(QT.split()); - } else { - assert(false); - } - - auto TPP = static_cast<const clang::PointerType*>(TP); - if (TPP) { - auto target_type = TPP->getPointeeType(); - - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - if (("char" != type_str) && ("const char" != type_str)) { - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::mstd::array<mse::TIPointerWithBundledVector<"; - replacement_code += type_str; - replacement_code += ">, "; - replacement_code += array_size_str; - replacement_code += "> "; - replacement_code += variable_name; - - if (("" != initialization_expr_str) && false) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval = replacement_code; - replacement_code_generated = true; - } - } - } - } else if (TP->isPointerType()) { - - auto PTP = static_cast<const clang::PointerType*>(TP); - if (PTP) { - QT = PTP->getPointeeType(); - TP = QT.getTypePtr(); - type_str = clang::QualType::getAsString(QT.split()); - } else { - assert(false); - } - - auto TPP = static_cast<const clang::PointerType*>(TP); - if (TPP) { - auto target_type = TPP->getPointeeType(); - - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - if (("char" != type_str) && ("const char" != type_str)) { - - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::TIPointerWithBundledVector<mse::TIPointerWithBundledVector<"; - replacement_code += type_str; - replacement_code += "> "; - replacement_code += "> "; - replacement_code += variable_name; - - if (("" != initialization_expr_str) && false) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval = replacement_code; - replacement_code_generated = true; - } - } - } else { - assert(false); - } - } else if ("dereference" == notes_str) { - if (TP->isPointerType()) { - auto PTP = static_cast<const clang::PointerType*>(TP); - if (PTP) { - QT = PTP->getPointeeType(); - TP = QT.getTypePtr(); - type_str = clang::QualType::getAsString(QT.split()); - } else { - assert(false); - } - - auto TPP = static_cast<const clang::PointerType*>(TP); - if (TPP) { - auto target_type = TPP->getPointeeType(); - - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - if (("char" != type_str) && ("const char" != type_str)) { - - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::TAnyPointer<mse::TIPointerWithBundledVector<"; - replacement_code += type_str; - replacement_code += "> "; - replacement_code += "> "; - replacement_code += variable_name; - - if (("" != initialization_expr_str) && false) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval = replacement_code; - replacement_code_generated = true; - } - } - } else { - assert(false); - } - } else if (TP->isPointerType()) { - auto TPP = static_cast<const clang::PointerType*>(TP); - if (TPP) { - auto target_type = TPP->getPointeeType(); - - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - if (("char" != type_str) && ("const char" != type_str)) { - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += "mse::TIPointerWithBundledVector<"; - replacement_code += type_str; - replacement_code += "> "; - replacement_code += variable_name; - - if (("" != initialization_expr_str) && false) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval = replacement_code; - replacement_code_generated = true; - } else { - int q = 3; - } - } else { - assert(false); - int q = 1; - } - } - - if (!replacement_code_generated) { - auto splitQualType = QT.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - - std::string replacement_code; - if (is_static) { - replacement_code += "static "; - } - replacement_code += type_str; - replacement_code += " "; - replacement_code += variable_name; - - if ("" != initialization_expr_str) { - replacement_code += " = "; - replacement_code += initialization_expr_str; - } - retval = replacement_code; - retval = decl_source_text; - replacement_code_generated = true; - } - return retval; -} - -class MCSSSMalloc : public MatchFinder::MatchCallback +class MCSSSMalloc2 : public MatchFinder::MatchCallback { public: - MCSSSMalloc (Rewriter &Rewrite, CState1& state1) + MCSSSMalloc2 (Rewriter &Rewrite, CState1& state1) : Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) { const BinaryOperator* BO = MR.Nodes.getNodeAs<clang::BinaryOperator>("mcsssmalloc1"); + const Expr* LHS = nullptr; + if (BO != nullptr) { + LHS = BO->getLHS(); + } const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssmalloc2"); const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssmalloc3"); const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcsssmalloc4"); - const ArraySubscriptExpr* ASE = MR.Nodes.getNodeAs<clang::ArraySubscriptExpr>("mcsssmalloc5"); - const UnaryOperator* UO = MR.Nodes.getNodeAs<clang::UnaryOperator>("mcsssmalloc6"); - if ((BO != nullptr) && (CE != nullptr) && (DRE != nullptr)) + if ((BO != nullptr) && (LHS != nullptr) && (CE != nullptr) && (DRE != nullptr)) { auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite); SourceLocation BOSL = BOSR.getBegin(); @@ -1635,18 +1533,11 @@ public: QualType QT; std::string element_type_str; clang::SourceRange decl_source_range; - std::string declaration_replacement_code; std::string variable_name; std::string bo_replacement_code; const clang::DeclaratorDecl* DD = nullptr; - auto LHS = BO->getLHS(); auto lhs_QT = LHS->getType(); - auto lhs_children = LHS->children(); - for (const auto& child : lhs_children) { - auto stmt_class = child->getStmtClass(); - clang::Stmt::StmtClass a; - } auto decl = DRE->getDecl(); DD = dynamic_cast<const DeclaratorDecl*>(decl); @@ -1675,7 +1566,6 @@ public: return; } QT = DD->getType(); - const clang::Type* TP = QT.getTypePtr(); variable_name = DD->getNameAsString(); auto qualified_name = DD->getQualifiedNameAsString(); @@ -1686,81 +1576,126 @@ public: return; } - std::string notes_str; - if (ASE != nullptr) { - notes_str = "array element"; - if (TP->isArrayType()) { - const clang::ArrayType* ATP = TP->getAsArrayTypeUnsafe(); - if (ATP) { - QT = ATP->getElementType(); - TP = QT.getTypePtr(); - //type_str = clang::QualType::getAsString(QT.split()); - } else { - assert(false); - } - } else if (TP->isPointerType()) { - auto PTP = static_cast<const clang::PointerType*>(TP); - if (PTP) { - QT = PTP->getPointeeType(); - TP = QT.getTypePtr(); - //type_str = clang::QualType::getAsString(QT.split()); - } else { - assert(false); - } + 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; + + const clang::Type* TP = QT.getTypePtr(); + auto type_str = QT.getAsString(); + + auto expr_SR = nice_source_range(LHS->getSourceRange(), Rewrite); + std::string expr_source_location_str; + std::string expr_source_text; + if (expr_SR.isValid()) { + expr_source_location_str = expr_SR.getBegin().printToString(*MR.SourceManager); + expr_source_text = Rewrite.getRewrittenText(expr_SR); + } else { + int q = 3; + } + + std::vector<std::string> stmt_indirection_stack; + const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, *LHS); + std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); + stmt_indirection_stack.push_back("malloc target"); + bool lhs_has_been_determined_to_be_an_array = false; + size_t indirection_level = 0; + if (expr2) { + std::string expr2_stmt_class_name; + expr2_stmt_class_name = expr2->getStmtClassName(); + const DeclaratorDecl* expr2_DD = nullptr; + if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { + auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); + if (expr2_DRE) { + auto expr2_decl = expr2_DRE->getDecl(); + expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); + } else { assert(false); } + } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { + auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); + if (expr2_ME) { + auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); + if (expr2_FD) { + expr2_DD = expr2_FD; + } else { assert(false); } + } else { assert(false); } } - } else if (UO != nullptr) { - notes_str = "dereference"; - if (TP->isPointerType()) { - auto PTP = static_cast<const clang::PointerType*>(TP); - if (PTP) { - QT = PTP->getPointeeType(); - TP = QT.getTypePtr(); - //type_str = clang::QualType::getAsString(QT.split()); + if (expr2_DD) { + auto expr2_QT = expr2_DD->getType(); + const clang::Type* expr2_TP = expr2_QT.getTypePtr(); + auto expr2_type_str = clang::QualType::getAsString(expr2_QT.split()); + std::string expr2_variable_name = expr2_DD->getNameAsString(); + if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { + 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 (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; + update_declaration_flag = true; + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } else if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "malloc target"; + indirection_level = i; + } + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + update_declaration_flag = true; + lhs_has_been_determined_to_be_an_array = true; + indirection_level = i; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } + } else { + assert(!(("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) + && (("malloc target" == stmt_indirection_stack[i])))); + } + } } else { - assert(false); + int q = 5; } } - } - auto decls = IndividualDeclaratorDecls(DD, Rewrite); - if ((1 <= decls.size()) && (decls.back() == DD)) { - for (const auto& decl : decls) { - declaration_replacement_code += IPointerFromPointerDecl(decl, Rewrite, notes_str); - declaration_replacement_code += "; \n"; - } - if (declaration_replacement_code.size() >= 3) { - declaration_replacement_code = declaration_replacement_code.substr(0, declaration_replacement_code.size() - 3); - } + int q = 5; } else { - int q = 7; + int q = 5; } - if (TP->isArrayType()) { - auto ATP = static_cast<const clang::ArrayType*>(TP); + if (update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + + const clang::Type* lhs_TP = lhs_QT.getTypePtr(); + auto lhs_type_str = clang::QualType::getAsString(lhs_QT.split()); + + std::string lhs_element_type_str; + if (lhs_TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(lhs_TP); assert(nullptr != ATP); auto element_type = ATP->getElementType(); auto elementSplitQualType = element_type.split(); - element_type_str = clang::QualType::getAsString(elementSplitQualType); - } else if (TP->isPointerType()) { - auto TPP = static_cast<const clang::PointerType*>(TP); + auto type_str = clang::QualType::getAsString(elementSplitQualType); + if (("char" != type_str) && ("const char" != type_str)) { + lhs_element_type_str = type_str; + } + } else if (lhs_TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(lhs_TP); assert(nullptr != TPP); auto target_type = TPP->getPointeeType(); auto splitQualType = target_type.split(); auto type_str = clang::QualType::getAsString(splitQualType); if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; + lhs_element_type_str = type_str; } } - if ("" != element_type_str) { + if ("" != lhs_element_type_str) { num_elements_text = "("; num_elements_text += arg_source_text; num_elements_text += ") / sizeof("; - num_elements_text += element_type_str; + num_elements_text += lhs_element_type_str; num_elements_text += ")"; - auto lhs = BO->getLHS(); - auto lhs_source_range = nice_source_range(lhs->getSourceRange(), Rewrite); + auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); - bo_replacement_code += lhs_source_text; + bo_replacement_code += "(" + lhs_source_text + ")"; bo_replacement_code += ".resize("; bo_replacement_code += num_elements_text; bo_replacement_code += ")"; @@ -1775,22 +1710,12 @@ public: auto BOSR = clang::SourceRange(BOSL, BOSLE); if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { - auto cr_shptr = std::make_shared<CMallocArrayReplacementAction>(Rewrite, MR, *DD, BO, bo_replacement_code, declaration_replacement_code); - - bool already_determined_to_be_an_array = false; - for (const auto& decl : decls) { - auto iter = m_state1.m_decl_replacement_action_records_log.find(decl); - if (m_state1.m_decl_replacement_action_records_log.end() != iter) { - if (("pointer to random access iterator" == (*iter).action_species()) - || ("pointer targeting heap allocated array to mse vector iterator" == (*iter).action_species())) { - already_determined_to_be_an_array = true; - } - } - } - if (already_determined_to_be_an_array) { + auto cr_shptr = std::make_shared<CMallocArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, indirection_level), BO, bo_replacement_code); + + if (lhs_has_been_determined_to_be_an_array) { (*cr_shptr).do_replacement(m_state1); } else { - m_state1.m_array_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } } else { int q = 7; @@ -1815,11 +1740,11 @@ private: CState1& m_state1; }; -class MCSSSMallocInitializer : public MatchFinder::MatchCallback +class MCSSSMallocInitializer2 : public MatchFinder::MatchCallback { public: - MCSSSMallocInitializer (Rewriter &Rewrite, CState1& state1) -: Rewrite(Rewrite), m_state1(state1) {} + MCSSSMallocInitializer2 (Rewriter &Rewrite, CState1& state1) : + Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) { @@ -1873,6 +1798,8 @@ public: if (arg_source_range.isValid()) { arg_source_text = Rewrite.getRewrittenText(arg_source_range); //auto arg_source_text_sans_ws = with_whitespace_removed(arg_source_text); + + bool asterisk_found = false; auto sizeof_start_index = arg_source_text.find("sizeof("); if (std::string::npos != sizeof_start_index) { auto sizeof_end_index = arg_source_text.find(")", sizeof_start_index); @@ -1884,7 +1811,6 @@ public: after_str = arg_source_text.substr(sizeof_end_index + 1); } - bool asterisk_found = false; auto index = before_str.size() - 1; while (0 <= index) { if ('*' == before_str[index]) { @@ -1914,115 +1840,109 @@ public: after_str = after_str.substr(index2 + 1); } } - if (asterisk_found) { - /* The argument is in the form "something * sizeof(something_else)" or - * "sizeof(something) * something_else". So we're just going to assume that - * this is an instance of an array being allocated. */ - std::string num_elements_text = before_str + after_str; - QualType QT; - std::string element_type_str; - clang::SourceRange decl_source_range; - std::string declaration_replacement_code; - std::string variable_name; - - if (nullptr != DD) { - auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } - QT = DD->getType(); - variable_name = DD->getNameAsString(); - - auto qualified_name = DD->getQualifiedNameAsString(); - static const std::string mse_namespace_str1 = "mse::"; - static const std::string mse_namespace_str2 = "::mse::"; - if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) - || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { - return; - } + } + } + if (true || asterisk_found) { + /* The argument is in the form "something * sizeof(something_else)" or + * "sizeof(something) * something_else". So we're just going to assume that + * this is an instance of an array being allocated. */ + std::string num_elements_text/* = before_str + after_str*/; + QualType QT; + std::string element_type_str; + clang::SourceRange decl_source_range; + std::string variable_name; + std::string declaration_replacement_code; - auto decls = IndividualDeclaratorDecls(DD, Rewrite); - if ((1 <= decls.size()) && (decls.back() == DD)) { - for (const auto& decl : decls) { - declaration_replacement_code += IPointerFromPointerDecl(decl, Rewrite); - declaration_replacement_code += "("; - declaration_replacement_code += num_elements_text; - declaration_replacement_code += "); \n"; - } - if (declaration_replacement_code.size() >= 3) { - declaration_replacement_code = declaration_replacement_code.substr(0, declaration_replacement_code.size() - 3); - } - } else { - int q = 7; - } + if (nullptr != DD) { + auto decl_source_range = nice_source_range(DD->getSourceRange(), Rewrite); + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + QT = DD->getType(); + variable_name = DD->getNameAsString(); - const clang::Type* TP = QT.getTypePtr(); - - if (TP->isArrayType()) { - auto ATP = static_cast<const clang::ArrayType*>(TP); - assert(nullptr != ATP); - auto element_type = ATP->getElementType(); - auto elementSplitQualType = element_type.split(); - element_type_str = clang::QualType::getAsString(elementSplitQualType); - } else if (TP->isPointerType()) { - auto TPP = static_cast<const clang::PointerType*>(TP); - assert(nullptr != TPP); - auto target_type = TPP->getPointeeType(); - auto splitQualType = target_type.split(); - auto type_str = clang::QualType::getAsString(splitQualType); - if (("char" != type_str) && ("const char" != type_str)) { - element_type_str = type_str; - } - } - if ("" != element_type_str) { - auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); - std::string decl_source_text; - if (decl_source_range.isValid()) { - decl_source_text = Rewrite.getRewrittenText(decl_source_range); - } else { - return; - } + auto qualified_name = DD->getQualifiedNameAsString(); + static const std::string mse_namespace_str1 = "mse::"; + static const std::string mse_namespace_str2 = "::mse::"; + if ((0 == qualified_name.compare(0, mse_namespace_str1.size(), mse_namespace_str1)) + || (0 == qualified_name.compare(0, mse_namespace_str2.size(), mse_namespace_str2))) { + return; + } - auto DSSR = clang::SourceRange(DSSL, DSSLE); - if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { - if ((3 <= declaration_replacement_code.size())) { - bool already_replaced_flag = false; - size_t replacement_text_length = 0; - for (const auto& decl : decls) { - auto iter = m_state1.m_decl_replacement_action_records_log.find(decl); - if (m_state1.m_decl_replacement_action_records_log.end() != iter) { - /* This declaration had already been replaced. We'll need to "undo" - * the replacement. */ - already_replaced_flag = true; - if ((*iter).replacement_text().size() > replacement_text_length) { - replacement_text_length = (*iter).replacement_text().size(); - } - m_state1.m_decl_replacement_action_records_log.erase(iter); - } - - CDeclReplacementActionRecord action_record(Rewrite, *decl, declaration_replacement_code, "pointer targeting heap allocated array to mse vector iterator"); - m_state1.m_decl_replacement_action_records_log.push_back(action_record); - m_state1.m_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, *decl); - } - auto adj_decl_source_range = decl_source_range; - if (already_replaced_flag) { - adj_decl_source_range = clang::SourceRange(decl_source_range.getBegin(), decl_source_range.getBegin().getLocWithOffset(replacement_text_length)); - } - auto res = Rewrite.ReplaceText(decl_source_range, declaration_replacement_code); - } - int q = 3; - } else { - int q = 7; - } + auto res1 = (*this).m_state1.m_ddecl_conversion_state_map.insert(*DD); + auto ddcs_map_iter = res1.first; + auto& ddcs_ref = (*ddcs_map_iter).second; + bool update_declaration_flag = res1.second; + + bool lhs_has_been_determined_to_be_an_array = false; + if ("native pointer" == ddcs_ref.m_indirection_state_stack[0].m_current) { + ddcs_ref.m_indirection_state_stack[0].m_current = "malloc target"; + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[0].m_current) { + ddcs_ref.m_indirection_state_stack[0].m_current = "dynamic array"; + lhs_has_been_determined_to_be_an_array = true; + //update_declaration_flag = true; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, 0)); + } else { + assert("native array" != ddcs_ref.m_indirection_state_stack[0].m_current); + } + + const clang::Type* TP = QT.getTypePtr(); + auto lhs_type_str = QT.getAsString(); + + if (TP->isArrayType()) { + auto ATP = llvm::cast<const clang::ArrayType>(TP); + assert(nullptr != ATP); + auto element_type = ATP->getElementType(); + auto elementSplitQualType = element_type.split(); + element_type_str = clang::QualType::getAsString(elementSplitQualType); + } else if (TP->isPointerType()) { + auto TPP = llvm::cast<const clang::PointerType>(TP); + assert(nullptr != TPP); + auto target_type = TPP->getPointeeType(); + auto splitQualType = target_type.split(); + auto type_str = clang::QualType::getAsString(splitQualType); + if (("char" != type_str) && ("const char" != type_str)) { + element_type_str = type_str; + } + } + if ("" != element_type_str) { + num_elements_text = "("; + num_elements_text += arg_source_text; + num_elements_text += ") / sizeof("; + num_elements_text += element_type_str; + num_elements_text += ")"; + + std::string initializer_info_str = "(" + num_elements_text + ")"; + + auto decl_source_location_str = decl_source_range.getBegin().printToString(*MR.SourceManager); + std::string decl_source_text; + if (decl_source_range.isValid()) { + decl_source_text = Rewrite.getRewrittenText(decl_source_range); + } else { + return; + } + + auto DSSR = clang::SourceRange(DSSL, DSSLE); + if (ConvertToSCPP && decl_source_range.isValid() && (DSSR.isValid())) { + auto cr_shptr = std::make_shared<CMallocInitializerArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, 0/*indirection_level*/), DS, initializer_info_str); + + if (lhs_has_been_determined_to_be_an_array) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } + + int q = 3; + } else { + int q = 7; } - int q = 5; } } + int q = 5; } } else { int q = 5; @@ -2040,10 +1960,10 @@ private: CState1& m_state1; }; -class MCSSSFree : public MatchFinder::MatchCallback +class MCSSSFree2 : public MatchFinder::MatchCallback { public: - MCSSSFree (Rewriter &Rewrite, CState1& state1) + MCSSSFree2 (Rewriter &Rewrite, CState1& state1) : Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) @@ -2136,23 +2056,106 @@ public: return; } - auto iter = m_state1.m_decl_replacement_action_records_log.find(DD/*decl_source_range.getBegin()*/); - if (m_state1.m_decl_replacement_action_records_log.end() != iter) { - if ("pointer targeting heap allocated array to mse vector iterator" == (*iter).action_species()) { - ce_replacement_code = arg_source_text; - ce_replacement_code += ".resize(0)"; + 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; - auto CESR = clang::SourceRange(CESL, CESLE); - if (ConvertToSCPP && (CESR.isValid())) { - auto res2 = Rewrite.ReplaceText(CESR, ce_replacement_code); - int q = 3; + const clang::Type* TP = QT.getTypePtr(); + auto type_str = QT.getAsString(); + + auto expr_SR = nice_source_range(CE->getSourceRange(), Rewrite); + std::string expr_source_location_str; + std::string expr_source_text; + if (expr_SR.isValid()) { + expr_source_location_str = expr_SR.getBegin().printToString(*MR.SourceManager); + expr_source_text = Rewrite.getRewrittenText(expr_SR); + } else { + int q = 3; + } + + std::vector<std::string> stmt_indirection_stack; + const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, *CE); + std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); + stmt_indirection_stack.push_back("malloc target"); + bool lhs_has_been_determined_to_be_an_array = false; + size_t indirection_level = 0; + if (expr2) { + std::string expr2_stmt_class_name; + expr2_stmt_class_name = expr2->getStmtClassName(); + const DeclaratorDecl* expr2_DD = nullptr; + if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { + auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); + if (expr2_DRE) { + auto expr2_decl = expr2_DRE->getDecl(); + expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); + } else { assert(false); } + } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { + auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); + if (expr2_ME) { + auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); + if (expr2_FD) { + expr2_DD = expr2_FD; + } else { assert(false); } + } else { assert(false); } + } + if (expr2_DD) { + auto expr2_QT = expr2_DD->getType(); + const clang::Type* expr2_TP = expr2_QT.getTypePtr(); + auto expr2_type_str = clang::QualType::getAsString(expr2_QT.split()); + std::string expr2_variable_name = expr2_DD->getNameAsString(); + if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { + 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 (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; + update_declaration_flag = true; + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } else if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "malloc target"; + indirection_level = i; + } + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + update_declaration_flag = true; + lhs_has_been_determined_to_be_an_array = true; + indirection_level = i; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } + } else { + assert(!(("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) + && (("malloc target" == stmt_indirection_stack[i])))); + } + } } else { - int q = 7; + int q = 5; } } + int q = 5; + } else { + int q = 5; + } + + if (update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + + ce_replacement_code = "(" + arg_source_text + ")"; + ce_replacement_code += ".resize(0)"; + + if (ConvertToSCPP && decl_source_range.isValid() && (CESR.isValid())) { + auto cr_shptr = std::make_shared<CFreeDynamicArray2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, indirection_level), CE, ce_replacement_code); + + if (lhs_has_been_determined_to_be_an_array) { + (*cr_shptr).do_replacement(m_state1); + } else { + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); + } } else { - auto cr_shptr = std::make_shared<CFreeDynamicArrayReplacementAction>(Rewrite, MR, *DD, CE, DRE, ME); - m_state1.m_dynamic_array_contingent_replacement_map.insert(cr_shptr); + int q = 7; } } int q = 5; @@ -2172,10 +2175,10 @@ private: CState1& m_state1; }; -class MCSSSSetToNull : public MatchFinder::MatchCallback +class MCSSSSetToNull2 : public MatchFinder::MatchCallback { public: - MCSSSSetToNull (Rewriter &Rewrite, CState1& state1) + MCSSSSetToNull2 (Rewriter &Rewrite, CState1& state1) : Rewrite(Rewrite), m_state1(state1) {} virtual void run(const MatchFinder::MatchResult &MR) @@ -2265,29 +2268,108 @@ public: return; } - if ((DD->getType() == LHS->getType())) { - auto iter = m_state1.m_decl_replacement_action_records_log.find(DD/*decl_source_range.getBegin()*/); - if ((m_state1.m_decl_replacement_action_records_log.end() != iter) - && ("pointer targeting heap allocated array to mse vector iterator" == (*iter).action_species()) - && ((*iter).get_ddecl_cptr()->getType() == LHS->getType())) { - if (true) { - bo_replacement_code = lhs_source_text; - bo_replacement_code += ".resize(0)"; - - auto BOSR = clang::SourceRange(BOSL, BOSLE); - if (ConvertToSCPP && (BOSR.isValid())) { - auto res2 = Rewrite.ReplaceText(BOSR, bo_replacement_code); - int q = 3; - } else { - int q = 7; + 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; + + const clang::Type* TP = QT.getTypePtr(); + auto type_str = QT.getAsString(); + + auto expr_SR = nice_source_range(LHS->getSourceRange(), Rewrite); + std::string expr_source_location_str; + std::string expr_source_text; + if (expr_SR.isValid()) { + expr_source_location_str = expr_SR.getBegin().printToString(*MR.SourceManager); + expr_source_text = Rewrite.getRewrittenText(expr_SR); + } else { + int q = 3; + } + + std::vector<std::string> stmt_indirection_stack; + const clang::Expr* expr2 = populateStmtIndirectionStack(stmt_indirection_stack, *LHS); + std::reverse(stmt_indirection_stack.begin(), stmt_indirection_stack.end()); + stmt_indirection_stack.push_back("malloc target"); + bool lhs_has_been_determined_to_be_an_array = false; + size_t indirection_level = 0; + if (expr2) { + std::string expr2_stmt_class_name; + expr2_stmt_class_name = expr2->getStmtClassName(); + const DeclaratorDecl* expr2_DD = nullptr; + if (clang::Stmt::StmtClass::DeclRefExprClass == expr2->getStmtClass()) { + auto expr2_DRE = llvm::cast<const clang::DeclRefExpr>(expr2); + if (expr2_DRE) { + auto expr2_decl = expr2_DRE->getDecl(); + expr2_DD = dynamic_cast<const DeclaratorDecl*>(expr2_decl); + } else { assert(false); } + } else if (clang::Stmt::StmtClass::MemberExprClass == expr2->getStmtClass()) { + auto expr2_ME = llvm::cast<const clang::MemberExpr>(expr2); + if (expr2_ME) { + auto expr2_FD = dynamic_cast<const clang::FieldDecl*>(expr2_ME->getMemberDecl()); + if (expr2_FD) { + expr2_DD = expr2_FD; + } else { assert(false); } + } else { assert(false); } + } + if (expr2_DD) { + auto expr2_QT = expr2_DD->getType(); + const clang::Type* expr2_TP = expr2_QT.getTypePtr(); + auto expr2_type_str = clang::QualType::getAsString(expr2_QT.split()); + std::string expr2_variable_name = expr2_DD->getNameAsString(); + if ((expr2_QT == QT) && (expr2_variable_name == variable_name)) { + 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 (("ArraySubscriptExpr" == stmt_indirection_stack[i]) + || ("pointer arithmetic" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "inferred array"; + update_declaration_flag = true; + m_state1.m_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } else if (("malloc target" == stmt_indirection_stack[i])) { + //ddcs_ref.m_indirection_state_stack[i].m_current = "malloc target"; + indirection_level = i; + } + } else if ("inferred array" == ddcs_ref.m_indirection_state_stack[i].m_current) { + if (("malloc target" == stmt_indirection_stack[i])) { + ddcs_ref.m_indirection_state_stack[i].m_current = "dynamic array"; + update_declaration_flag = true; + lhs_has_been_determined_to_be_an_array = true; + indirection_level = i; + m_state1.m_dynamic_array2_contingent_replacement_map.do_and_dispose_matching_replacements(m_state1, CDDeclIndirection(*DD, i)); + } + } else { + assert(!(("native array" == ddcs_ref.m_indirection_state_stack[i].m_current) + && (("malloc target" == stmt_indirection_stack[i])))); + } } } else { int q = 5; } + } + int q = 5; + } else { + int q = 5; + } + + if (update_declaration_flag) { + update_declaration(*DD, Rewrite, m_state1); + } + + auto lhs_source_range = nice_source_range(LHS->getSourceRange(), Rewrite); + auto lhs_source_text = Rewrite.getRewrittenText(lhs_source_range); + bo_replacement_code += "(" + lhs_source_text + ")"; + bo_replacement_code += ".resize(0)"; + + if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.isValid())) { + auto cr_shptr = std::make_shared<CSetArrayPointerToNull2ReplacementAction>(Rewrite, MR, CDDeclIndirection(*DD, indirection_level), BO, bo_replacement_code); + + if (lhs_has_been_determined_to_be_an_array) { + (*cr_shptr).do_replacement(m_state1); } else { - auto cr_shptr = std::make_shared<CSetArrayPointerToNullReplacementAction>(Rewrite, MR, *DD, BO, DRE, ME); - m_state1.m_dynamic_array_contingent_replacement_map.insert(cr_shptr); + m_state1.m_dynamic_array2_contingent_replacement_map.insert(cr_shptr); } + } else { + int q = 7; } } int q = 5; @@ -2309,63 +2391,52 @@ private: class MyASTConsumer : public ASTConsumer { public: - MyASTConsumer(Rewriter &R) : HandlerForSSSNativePointer(R), HandlerForSSSArrayToPointerDecay(R, m_state1), \ - HandlerForSSSVarDecl(R, m_state1), HandlerForSSSPointerArithmetic(R, m_state1), \ - HandlerForSSSMalloc(R, m_state1), HandlerForSSSMallocInitializer(R, m_state1), \ - HandlerForSSSFree(R, m_state1), HandlerForSSSSetToNull(R, m_state1) + 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) { Matcher.addMatcher(varDecl(hasType(pointerType())).bind("mcsssnativepointer"), &HandlerForSSSNativePointer); Matcher.addMatcher(castExpr(allOf(hasCastKind(CK_ArrayToPointerDecay), unless(hasParent(arraySubscriptExpr())))).bind("mcsssarraytopointerdecay"), &HandlerForSSSArrayToPointerDecay); - Matcher.addMatcher(varDecl().bind("mcsssvardecl"), &HandlerForSSSVarDecl); - - Matcher.addMatcher(declRefExpr(allOf(hasParent(expr(anyOf( \ - unaryOperator(hasOperatorName("++")), unaryOperator(hasOperatorName("--")), \ - binaryOperator(hasOperatorName("+=")), binaryOperator(hasOperatorName("-=")), \ - hasParent(expr(anyOf( \ - binaryOperator(hasOperatorName("+")), binaryOperator(hasOperatorName("+=")), \ - binaryOperator(hasOperatorName("-")), binaryOperator(hasOperatorName("-=")), \ - binaryOperator(hasOperatorName("<=")), binaryOperator(hasOperatorName("<")), \ - binaryOperator(hasOperatorName(">=")), binaryOperator(hasOperatorName(">")), \ - arraySubscriptExpr(), clang::ast_matchers::castExpr(hasParent(arraySubscriptExpr())) \ - )))))), to(declaratorDecl(hasType(pointerType()))))).bind("mcssspointerarithmetic"), &HandlerForSSSPointerArithmetic); - - Matcher.addMatcher(memberExpr(allOf(hasDescendant(declRefExpr().bind("mcssspointerarithmetic")), hasParent(expr(anyOf( \ - unaryOperator(hasOperatorName("++")), unaryOperator(hasOperatorName("--")), \ - binaryOperator(hasOperatorName("+=")), binaryOperator(hasOperatorName("-=")), \ - hasParent(expr(anyOf( \ - binaryOperator(hasOperatorName("+")), binaryOperator(hasOperatorName("+=")), \ - binaryOperator(hasOperatorName("-")), binaryOperator(hasOperatorName("-=")), \ - binaryOperator(hasOperatorName("<=")), binaryOperator(hasOperatorName("<")), \ - binaryOperator(hasOperatorName(">=")), binaryOperator(hasOperatorName(">")), \ - arraySubscriptExpr(), clang::ast_matchers::castExpr(hasParent(arraySubscriptExpr())) \ - )))))), member(hasType(pointerType())))).bind("mcssspointerarithmetic2"), &HandlerForSSSPointerArithmetic); + Matcher.addMatcher(clang::ast_matchers::declaratorDecl().bind("mcsssvardecl"), &HandlerForSSSVarDecl2); + + Matcher.addMatcher(expr(allOf( + hasParent(expr(anyOf( \ + unaryOperator(hasOperatorName("++")), unaryOperator(hasOperatorName("--")), \ + binaryOperator(hasOperatorName("+=")), binaryOperator(hasOperatorName("-=")), + castExpr(hasParent(expr(anyOf( + binaryOperator(hasOperatorName("+")), binaryOperator(hasOperatorName("+=")), + binaryOperator(hasOperatorName("-")), binaryOperator(hasOperatorName("-=")), + binaryOperator(hasOperatorName("<=")), binaryOperator(hasOperatorName("<")), + binaryOperator(hasOperatorName(">=")), binaryOperator(hasOperatorName(">")), + arraySubscriptExpr()/*, clang::ast_matchers::castExpr(hasParent(arraySubscriptExpr()))*/ + ))))))), + hasType(pointerType()), + anyOf( + memberExpr(expr(hasDescendant(declRefExpr().bind("mcssspointerarithmetic")))).bind("mcssspointerarithmetic2"), + declRefExpr().bind("mcssspointerarithmetic"), + hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcssspointerarithmetic")))).bind("mcssspointerarithmetic2")), + hasDescendant(declRefExpr().bind("mcssspointerarithmetic")) + ) + )).bind("mcssspointerarithmetic3"), &HandlerForSSSPointerArithmetic2); Matcher.addMatcher(binaryOperator(allOf( hasOperatorName("="), hasRHS( anyOf( cStyleCastExpr(has(callExpr().bind("mcsssmalloc2"))), - callExpr().bind("mcsssmalloc2") + callExpr().bind("mcsssmalloc2") ) ), hasLHS(anyOf( - unaryOperator(allOf(hasOperatorName("*"), hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")))).bind("mcsssmalloc6"), - unaryOperator(allOf(hasOperatorName("*"), hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc6"), - arraySubscriptExpr(expr(hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")))).bind("mcsssmalloc5"), - arraySubscriptExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc5"), memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4"), declRefExpr().bind("mcsssmalloc3"), - hasDescendant(unaryOperator(allOf(hasOperatorName("*"), hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")))).bind("mcsssmalloc6")), - hasDescendant(unaryOperator(allOf(hasOperatorName("*"), hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc6")), - hasDescendant(arraySubscriptExpr(expr(hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")))).bind("mcsssmalloc5")), - hasDescendant(arraySubscriptExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc5")), hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")), hasDescendant(declRefExpr().bind("mcsssmalloc3")) )), hasLHS(expr(hasType(pointerType()))) - )).bind("mcsssmalloc1"), &HandlerForSSSMalloc); + )).bind("mcsssmalloc1"), &HandlerForSSSMalloc2); Matcher.addMatcher(declStmt(hasDescendant( varDecl(hasInitializer(ignoringImpCasts( @@ -2374,7 +2445,7 @@ public: callExpr().bind("mcsssmallocinitializer2") ) ))).bind("mcsssmallocinitializer3") - )).bind("mcsssmallocinitializer1"), &HandlerForSSSMallocInitializer); + )).bind("mcsssmallocinitializer1"), &HandlerForSSSMallocInitializer2); Matcher.addMatcher( callExpr(allOf( @@ -2386,7 +2457,7 @@ public: ))), argumentCountIs(1), hasAnyArgument(hasType(pointerType())) - )).bind("mcsssfree1"), &HandlerForSSSFree); + )).bind("mcsssfree1"), &HandlerForSSSFree2); Matcher.addMatcher(binaryOperator(allOf( hasOperatorName("="), @@ -2396,7 +2467,7 @@ public: hasDescendant(declRefExpr().bind("mcssssettonull3")) )), hasLHS(expr(hasType(pointerType()))) - )).bind("mcssssettonull1"), &HandlerForSSSSetToNull); + )).bind("mcssssettonull1"), &HandlerForSSSSetToNull2); } void HandleTranslationUnit(ASTContext &Context) override @@ -2410,12 +2481,12 @@ private: MCSSSNativePointer HandlerForSSSNativePointer; MCSSSArrayToPointerDecay HandlerForSSSArrayToPointerDecay; - MCSSSVarDecl HandlerForSSSVarDecl; - MCSSSPointerArithmetic HandlerForSSSPointerArithmetic; - MCSSSMalloc HandlerForSSSMalloc; - MCSSSMallocInitializer HandlerForSSSMallocInitializer; - MCSSSFree HandlerForSSSFree; - MCSSSSetToNull HandlerForSSSSetToNull; + MCSSSVarDecl2 HandlerForSSSVarDecl2; + MCSSSPointerArithmetic2 HandlerForSSSPointerArithmetic2; + MCSSSMalloc2 HandlerForSSSMalloc2; + MCSSSMallocInitializer2 HandlerForSSSMallocInitializer2; + MCSSSFree2 HandlerForSSSFree2; + MCSSSSetToNull2 HandlerForSSSSetToNull2; MatchFinder Matcher; }; |