aboutsummaryrefslogblamecommitdiffstats
path: root/safercpp/safercpp-arr.cpp
blob: 0b0b6a3f479a08ca54032bdd598219b93e3d59e5 (plain) (tree)





























                                                                                                                        




                    






















                                                                                                                        




                                                                                                                                                                                                         
                                                                                                                        
 




















                                                                                                    




































































































































































































































                                                                                                                                                                                                                              


                                                                             













                                                                                   
                                                       




                                                                                                                                 
                                                                                                    






















                                                                                                            
                                                                                                                          











                                                                                                                                                    
                                                                                                                    







































































                                                                                                                                               


                                                                             













                                                                                   
                                                       














                                                                                                                                                            
                                                                                                                        




























                                                                                                                            
                                                                                                                                    


























































































                                                                                                                                                               


                                                                 











                                                                       
                                           




                                    
         
                            


























                                                                                                                        


                                                                 





                                                                     

                                                                       



                 
                                           




                                    
         
                                          






























                                                                                                                        


                                                                 

















                                                                       



                                             
















                                                                                                   
                                                                                                        























































































































                                                                                                                                                         
                                                                                                
























                                                                                     
                                                                                       

















































                                                                                                                  

                                                               









                                                                                                                         

                                                                                           



























                                                                                                    


                                                                    


















                                                                       
                                             

















                                                                                  
                                                                                            
































































                                                                                                                                                        
                                                                                         























                                                                                                
                                                                                                





                                                                                     
                                                                                                





























                                                                                     
                                                                         


















































                                                                                             


                                                                     













                                                                           
                                               




                                                 











                                                                                                                                                     
                                                  



                                                                                                                












































































                                                                                                                                             
                                                                                                                                                    


















































                                                                                                                                                                                                 
                                                                                                                                            



















































































                                                                                                                                                                                                                                                    


                                                                     













                                                                           
                                               




                                                 











                                                                                                                                                     
                                                  



                                                                                                                
























































                                                                                                                                             
                                                                                                                                                    




















                                                                                                                                                                               
                                                                                                                                                         








































































































                                                                                                                                                                                                                                                    


                                                                     













                                                                           
                                               














                                                                                                                                                    
                                                                                                                




























                                                                                                                    
                                                                                                                            









































































                                                                                                                                                              


                                                                     













                                                                           
                                               




                                                                                                                         
                                                                                            





























                                                                                                    
                                                                                                            

























































                                                                                                                                                           



                                                                                                                        



                                                                                                              
   










































































                                                                                                                                                                                                







                                                           











                                                            

                      
 




                                                                                                                        






                                                     








                                                                                                 



                                                     













                                                                                                                        
/***************************************************Project Mutator****************************************************/
//-*-c++-*-
/*first line intentionally left blank.*/
/*the source code for SaferCPP's automatic refactoring of C/C++ arrays.*/
/*Copyright (C) 2017 Noah L.,Farzad Sadeghi

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
/*code structure inspired by Eli Bendersky's tutorial on Rewriters.*/
/**********************************************************************************************************************/
/**********************************************************************************************************************/
/*included modules*/
/*Project Headers*/
#include "safercpp-arr.h"
#include "../mutator_aux.h"
/*Standard headers*/
#include <string>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <locale>
/*Clang Headers*/
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Lex/Lexer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
/*LLVM Headers*/
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Function.h"
/**********************************************************************************************************************/
/*used namespaces*/
using namespace llvm;
using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::driver;
using namespace clang::tooling;
/**********************************************************************************************************************/
static llvm::cl::OptionCategory MatcherSampleCategory("TBD");

cl::opt<bool> CheckSystemHeader("SysHeader", cl::desc("safercpp will run through System Headers"), cl::init(false), cl::cat(MatcherSampleCategory), cl::ZeroOrMore);
cl::opt<bool> MainFileOnly("MainOnly", cl::desc("safercpp will only report the results that reside in the main file"), cl::init(false), cl::cat(MatcherSampleCategory), cl::ZeroOrMore);
cl::opt<bool> SafeSubset("SafeSubset", cl::desc("safercpp will check for elements outside of the (memory) safe subset of the language"), cl::init(true), cl::cat(MatcherSampleCategory), cl::ZeroOrMore);
cl::opt<bool> ConvertToSCPP("ConvertToSCPP", cl::desc("safercpp will translate the source to a (memory) safe subset of the language"), cl::init(false), cl::cat(MatcherSampleCategory), cl::ZeroOrMore);
/**********************************************************************************************************************/

SourceRange nice_source_range(const SourceRange& sr, Rewriter &Rewrite) {
    SourceLocation SL = sr.getBegin();
    SourceLocation SLE = sr.getEnd();
    if (SL.isMacroID() || SLE.isMacroID()) {
    	int q = 5;
    }
    SL = Devi::SourceLocationHasMacro(SL, Rewrite, "start");
    SLE = Devi::SourceLocationHasMacro(SLE, Rewrite, "end");
    return SourceRange(SL, SLE);
}

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;
	}
	return retval;
}

static std::string with_whitespace_removed(const std::string& str) {
	std::string retval = str;
	retval.erase(std::remove_if(retval.begin(), retval.end(), isspace), retval.end());
	return retval;
}

static std::string with_newlines_removed(const std::string& str) {
	std::string retval = str;
	auto riter1 = retval.rbegin();
	while (retval.rend() != riter1) {
		if ('\n' == *riter1) {
			auto riter2 = riter1;
			riter2++;
			retval.erase(riter1.base()--);
			while (retval.rend() != riter2) {
				/* look for and remove 'continued on the next line' backslash if present. */
				if ('\\' == (*riter2)) {
					riter1++;
					retval.erase(riter2.base()--);
					break;
				} else if (!std::isspace(*riter2)) {
					break;
				}

				riter2++;
			}
		}

		riter1++;
	}

	return retval;
}

static std::vector<std::string> f_declared_object_strings(const std::string& decl_stmt_str) {
	std::vector<std::string> retval;

	auto nice_decl_stmt_str = with_newlines_removed(decl_stmt_str);
	auto semicolon_position = std::string::npos;
	for (size_t pos = 3; pos < nice_decl_stmt_str.size(); pos += 1) {
		if (';' == nice_decl_stmt_str[pos]) {
			semicolon_position = pos;
		}
	}
	if (std::string::npos == semicolon_position) {
		assert(false);
		return retval;
	}

	std::vector<size_t> delimiter_positions;
	for (size_t pos = 3; ((pos < nice_decl_stmt_str.size()) && (pos < semicolon_position)); pos += 1) {
		if (',' == nice_decl_stmt_str[pos]) {
			delimiter_positions.push_back(pos);
		}
	}

	delimiter_positions.push_back(semicolon_position);
	auto first_delimiter_pos = delimiter_positions[0];

	{
		auto pos1 = first_delimiter_pos - 1;
		auto pos2 = pos1;
		bool nonspace_found = false;
		while ((2 <= pos1) && (!nonspace_found)) {
			if (!std::isspace(nice_decl_stmt_str[pos1])) {
				pos2 = pos1 + 1;
				nonspace_found = true;
			}

			pos1 -= 1;
		}
		if (!nonspace_found) {
			assert(false);
			return retval;
		}

		bool space_found = false;
		while ((1 <= pos1) && (!space_found)) {
			if (std::isspace(nice_decl_stmt_str[pos1])) {
				space_found = true;
			}

			pos1 -= 1;
		}
		if (!space_found) {
			assert(false);
			return retval;
		}

		pos1 += 2;
		std::string first_declaration_string = nice_decl_stmt_str.substr(pos1, pos2 - pos1);
		retval.push_back(first_declaration_string);
	}

	{
		size_t delimiter_index = 0;
		while (delimiter_positions.size() > (delimiter_index + 1)) {
			if (!(delimiter_positions[delimiter_index] + 1 < delimiter_positions[(delimiter_index + 1)])) {
				//assert(false);
			} else {
				std::string declaration_string = nice_decl_stmt_str.substr(delimiter_positions[delimiter_index] + 1, delimiter_positions[(delimiter_index + 1)] - (delimiter_positions[delimiter_index] + 1));
				retval.push_back(declaration_string);
			}

			delimiter_index += 1;
		}
	}

	return retval;
}

class CDeclReplacementActionRecord {
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;
	}
	clang::SourceLocation start_location() {
		clang::SourceLocation retval = source_range().getBegin();
		return retval;
	}
	std::string get_var_name() {
		std::string retval = m_ddecl_cptr->getNameAsString();
		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;
			}
		}
		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;
	}
};

class CReplacementAction {
public:
	virtual ~CReplacementAction() {}
	virtual void do_replacement() const = 0;
};

class CDDeclReplacementAction : public CReplacementAction {
public:
	CDDeclReplacementAction(Rewriter &Rewrite, const MatchFinder::MatchResult &MR,
			const clang::DeclaratorDecl& ddecl) : m_Rewrite(Rewrite), m_MR(MR), m_ddecl_cptr(&ddecl) {
	}
	virtual ~CDDeclReplacementAction() {}

	virtual void do_replacement() const = 0;
	virtual const clang::DeclaratorDecl* get_ddecl_cptr() const { return m_ddecl_cptr; }

	clang::SourceRange source_range() {
		clang::SourceRange retval = m_ddecl_cptr->getSourceRange();
		return retval;
	}
	clang::SourceLocation start_location() {
		clang::SourceLocation retval = source_range().getBegin();
		return retval;
	}
	std::string get_var_name() {
		std::string retval = m_ddecl_cptr->getNameAsString();
		return retval;
	}

	Rewriter& m_Rewrite;
	const MatchFinder::MatchResult m_MR;
	const clang::DeclaratorDecl* m_ddecl_cptr = nullptr;
};

class CDynamicArrayReplacementAction : public CDDeclReplacementAction {
public:
	using CDDeclReplacementAction::CDDeclReplacementAction;
	virtual ~CDynamicArrayReplacementAction() {}
};

class CSetArrayPointerToNullReplacementAction : public CDynamicArrayReplacementAction {
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) {
	}
	virtual ~CSetArrayPointerToNullReplacementAction() {}

	virtual void do_replacement() 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;

		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();

	        ASTContext *const ASTC = MR.Context;
	        FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL);

	        SourceManager &SM = ASTC->getSourceManager();

	        auto source_location_str = BOSL.printToString(*MR.SourceManager);
	        std::string source_text;
	        if (BOSL.isValid() && BOSLE.isValid()) {
	      	  source_text = Rewrite.getRewrittenText(SourceRange(BOSL, BOSLE));
	        } else {
	      	  return;
	        }

	      if (filtered_out_by_location(MR, BOSL)) {
	        return void();
	      }

	      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);

				  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;

				  auto decl = DRE->getDecl();
				  auto VD = dynamic_cast<const VarDecl*>(decl);

				  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;

					  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);

					  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;
					  }

					  QT = VD->getType();
					  variable_name = VD->getNameAsString();
				  } else {
					  int q = 7;
				  }

				  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;
						  }
					  }
				  }
				  int q = 5;
			  } else {
				  int q = 5;
			  }
			  int q = 5;
	      }
	    }
	}

	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);
	}
	return retval;
}

class CFreeDynamicArrayReplacementAction : public CDynamicArrayReplacementAction {
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) {
	}
	virtual ~CFreeDynamicArrayReplacementAction() {}

	virtual void do_replacement() 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;

		if ((CE != nullptr) && (DRE != nullptr))
	    {
	        auto CESR = nice_source_range(CE->getSourceRange(), Rewrite);
	        SourceLocation CESL = CESR.getBegin();
	        SourceLocation CESLE = CESR.getEnd();

	        ASTContext *const ASTC = MR.Context;
	        FullSourceLoc FCESL = ASTC->getFullLoc(CESL);

	        SourceManager &SM = ASTC->getSourceManager();

	        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;
	        }

	      if (filtered_out_by_location(MR, CESL)) {
	        return void();
	      }

	      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;

						  auto decl = DRE->getDecl();
						  DD = dynamic_cast<const DeclaratorDecl*>(decl);
						  auto VD = dynamic_cast<const VarDecl*>(decl);

						  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;
						  }

						  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) {
								  ce_replacement_code = arg_source_text;
								  ce_replacement_code += ".resize(0)";

								  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;
								  }
							  }
						  }
						  int q = 5;
					  } else {
						  int q = 5;
					  }
					  int q = 5;
				  }
	    	  }

	      }
	    }
	}

	const CallExpr* m_CE;
	const DeclRefExpr* m_DRE;
	const MemberExpr* m_ME;
};

class CDynamicArrayReplacementActionMap : public std::multimap<const clang::DeclaratorDecl*, std::shared_ptr<CDynamicArrayReplacementAction>> {
public:
	typedef std::multimap<const clang::DeclaratorDecl*, std::shared_ptr<CDynamicArrayReplacementAction>> base_class;
	iterator insert( const std::shared_ptr<CDynamicArrayReplacementAction>& 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);
		}
		return retval;
	}
	void do_and_dispose_matching_replacements(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();
			}
			base_class::erase(range.first, range.second);
			range = base_class::equal_range(DD);
		}
	}
};

class CState1 {
public:
	CDeclReplacementActionRecordsLog m_decl_replacement_action_records_log;
	CDynamicArrayReplacementActionMap m_dynamic_array_contingent_replacement_map;
};

/**********************************************************************************************************************/
class MCSSSArrayToPointerDecay : public MatchFinder::MatchCallback
{
public:
	MCSSSArrayToPointerDecay (Rewriter &Rewrite, CState1& state1)
		: Rewrite(Rewrite), m_state1(state1) {}

  virtual void run(const MatchFinder::MatchResult &MR)
  {
    if (/*SafeSubset && */(MR.Nodes.getNodeAs<clang::CastExpr>("mcsssarraytopointerdecay") != nullptr))
    {
      const CastExpr* CE = MR.Nodes.getNodeAs<clang::CastExpr>("mcsssarraytopointerdecay");

      auto SR = nice_source_range(CE->getSourceRange(), Rewrite);
      SourceLocation SL = SR.getBegin();
      SourceLocation SLE = SR.getEnd();

      ASTContext *const ASTC = MR.Context;
      FullSourceLoc FSL = ASTC->getFullLoc(SL);

      auto source_location_str = SL.printToString(*MR.SourceManager);
      std::string source_text;
      if (SL.isValid() && SLE.isValid()) {
    	  source_text = Rewrite.getRewrittenText(SourceRange(SL, SLE));
      } else {
    	  return;
      }

      if (filtered_out_by_location(MR, SL))
      {
        /*intentionally left blank*/
      }
      else
      {
        {
        	if (false) {
				  std::cout << "sss1.2:" << "array to pointer decay:";
				  std::cout << SL.printToString(*MR.SourceManager) << ":" << std::endl;

				  //XMLDocOut.XMLAddNode(MR.Context, SL, "sss1.2", "array to pointer decay: ");
				  //JSONDocOUT.JSONAddElement(MR.Context, SL, "sss1.2", "array to pointer decay: ");
			}
        }
      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};
/**********************************************************************************************************************/
class MCSSSNativePointer : public MatchFinder::MatchCallback
{
public:
	MCSSSNativePointer (Rewriter &Rewrite) : Rewrite(Rewrite) {}

  virtual void run(const MatchFinder::MatchResult &MR)
  {
    if (SafeSubset && (MR.Nodes.getNodeAs<clang::VarDecl>("mcsssnativepointer") != nullptr))
    {
      const VarDecl *VD = MR.Nodes.getNodeAs<clang::VarDecl>("mcsssnativepointer");

      auto SR = nice_source_range(VD->getSourceRange(), Rewrite);
      SourceLocation SL = SR.getBegin();
      SourceLocation SLE = SR.getEnd();

      ASTContext* const ASTC = MR.Context;
      FullSourceLoc FSL = ASTC->getFullLoc(SL);

      auto source_location_str = SL.printToString(*MR.SourceManager);
      std::string source_text;
      if (SL.isValid() && SLE.isValid()) {
    	  source_text = Rewrite.getRewrittenText(SourceRange(SL, SLE));
      } else {
    	  return;
      }

      if (filtered_out_by_location(MR, SL))
      {
        /*intentionally left blank*/
      }
      else
      {
        {
        	if (false && SafeSubset) {
			  std::cout << "sss1.1:" << "native pointer:";
			  std::cout << SL.printToString(*MR.SourceManager) << ":" << std::endl;

			  //XMLDocOut.XMLAddNode(MR.Context, SL, "sss1.1", "native pointer: ");
			  //JSONDocOUT.JSONAddElement(MR.Context, SL, "sss1.1", "native pointer: ");
        	}
        }
      }
    }
  }

  virtual void onEndOfTranslationUnit()
  {
  }

private:
  Rewriter &Rewrite;
};
/**********************************************************************************************************************/
class MCSSSVarDecl : public MatchFinder::MatchCallback
{
public:
	MCSSSVarDecl (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 VarDecl* VD = MR.Nodes.getNodeAs<clang::VarDecl>("mcsssvardecl");

      auto SR = nice_source_range(VD->getSourceRange(), Rewrite);
      SourceLocation SL = SR.getBegin();
      SourceLocation SLE = SR.getEnd();

      QualType QT = VD->getType();

      const clang::Type* TP = QT.getTypePtr();

      ASTContext *const ASTC = MR.Context;
      FullSourceLoc FSL = ASTC->getFullLoc(SL);

      SourceManager &SM = ASTC->getSourceManager();

      auto source_location_str = SL.printToString(*MR.SourceManager);
      std::string source_text;
      if (SL.isValid() && SLE.isValid()) {
    	  source_text = Rewrite.getRewrittenText(SourceRange(SL, SLE));
      } else {
    	  return;
      }

      if (filtered_out_by_location(MR, SL)) {
        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 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);
	  }

	  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;
    	  }
    	  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(*VD);
        	  int q = 3;
          } else {
        	  int q = 7;
          }
          m_state1.m_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(*VD);
    	  int q = 5;
      } else {
    	  ;
      }

    }
  }

  virtual void onEndOfTranslationUnit()
  {
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};

/**********************************************************************************************************************/
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;
}

static std::vector<const DeclaratorDecl*> IndividualDeclaratorDecls(const DeclaratorDecl* VD, Rewriter &Rewrite) {
	std::vector<const DeclaratorDecl*> retval;

	if (!VD) {
		assert(false);
		return retval;
	}
    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);
				}
			}
		}
	}
	if (0 == retval.size()) {
		assert(false);
	}

	return retval;
}

class MCSSSPointerArithmetic : public MatchFinder::MatchCallback
{
public:
	MCSSSPointerArithmetic (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");

    if (DRE != nullptr)
    {
        const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcssspointerarithmetic");

        auto SR = nice_source_range(DRE->getSourceRange(), Rewrite);
        SourceLocation SL = SR.getBegin();
        SourceLocation SLE = SR.getEnd();

        QualType QT = DRE->getType();

        const clang::Type* TP = QT.getTypePtr();

        ASTContext *const ASTC = MR.Context;
        FullSourceLoc FSL = ASTC->getFullLoc(SL);

        SourceManager &SM = ASTC->getSourceManager();

        auto source_location_str = SL.printToString(*MR.SourceManager);
        std::string source_text;
        if (SL.isValid() && SLE.isValid()) {
      	  source_text = Rewrite.getRewrittenText(SourceRange(SL, SLE));
        } else {
      	  return;
        }


      if (filtered_out_by_location(MR, SL)) {
        return void();
      }

      auto decl = DRE->getDecl();
      auto DD = dynamic_cast<const DeclaratorDecl*>(decl);

	  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;
	  }

      if (!DD) {
    	  return;
      } else {
		  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();
		  std::string 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;
		  }

          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 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);
        	  }

        	  if (ConvertToSCPP && decl_source_range.isValid() && (3 <= replacement_code.size())) {
            	  auto res = Rewrite.ReplaceText(decl_source_range, replacement_code);

            	  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_dynamic_array_contingent_replacement_map.do_and_dispose_matching_replacements(*var_decl);
            	  }
            	  int q = 3;
              } else {
            	  int q = 7;
              }
          } else {
        	  int q = 7;
          }
      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};

/**********************************************************************************************************************/
static std::string IPointerFromPointerDecl(const DeclaratorDecl* DD, Rewriter &Rewrite) {
	std::string 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 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 (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;
		  replacement_code_generated = true;
	}
	return retval;
}

class MCSSSMalloc : public MatchFinder::MatchCallback
{
public:
	MCSSSMalloc (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 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");

	if ((BO != nullptr) && (CE != nullptr) && (DRE != nullptr))
    {
        auto BOSR = nice_source_range(BO->getSourceRange(), Rewrite);
        SourceLocation BOSL = BOSR.getBegin();
        SourceLocation BOSLE = BOSR.getEnd();

        ASTContext *const ASTC = MR.Context;
        FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL);

        SourceManager &SM = ASTC->getSourceManager();

        auto source_location_str = BOSL.printToString(*MR.SourceManager);
        std::string source_text;
        if (BOSL.isValid() && BOSLE.isValid()) {
      	  source_text = Rewrite.getRewrittenText(SourceRange(BOSL, BOSLE));
        } else {
      	  return;
        }

      if (filtered_out_by_location(MR, BOSL)) {
        return void();
      }

      auto function_decl = CE->getDirectCallee();
      auto num_args = CE->getNumArgs();
      if (function_decl && ((1 == num_args) || (2 == num_args))) {
		  std::string function_name = function_decl->getNameAsString();
		  static const std::string alloc_str = "alloc";
		  static const std::string realloc_str = "realloc";
		  auto lc_function_name = tolowerstr(function_name);
		  bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size())
				  && (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str)));
		  bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size())
				  && (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str)));
		  bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args));
		  if (still_potentially_valid1) {
			  auto iter = CE->arg_begin();
			  if (ends_with_realloc) {
				  iter++;
			  }
			  {
				  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);
					  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);
						  if (std::string::npos != sizeof_end_index) {
							  assert(sizeof_end_index > sizeof_start_index);
							  std::string before_str = arg_source_text.substr(0, sizeof_start_index);
							  std::string after_str;
							  if (sizeof_end_index + 1 < arg_source_text.size()) {
								  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]) {
									  asterisk_found = true;
								  }
								  if (!std::isspace(before_str[index])) {
									  break;
								  }

								  index -= 1;
							  }
							  if (asterisk_found) {
								  before_str = before_str.substr(0, index);
							  } else {
								  size_t index2 = 0;
								  while (after_str.size() > index2) {
									  if ('*' == after_str[index2]) {
										  asterisk_found = true;
									  }
									  if (!std::isspace(after_str[index2])) {
										  break;
									  }

									  index2 += 1;
								  }
								  if (asterisk_found) {
									  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;
				            	  std::string bo_replacement_code;
				            	  const clang::DeclaratorDecl* DD = nullptr;


								  auto decl = DRE->getDecl();
								  DD = dynamic_cast<const DeclaratorDecl*>(decl);
								  auto VD = dynamic_cast<const VarDecl*>(decl);

								  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;
								  }

					        	  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;
									  }

							          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 += "; \n";
							        	  }
							        	  if (declaration_replacement_code.size() >= 3) {
							        		  declaration_replacement_code = declaration_replacement_code.substr(0, declaration_replacement_code.size() - 3);
							        	  }
							          } else {
							        	  int q = 7;
							          }

									  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 lhs = BO->getLHS();
						            	  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(";
						            	  bo_replacement_code += num_elements_text;
						            	  bo_replacement_code += ")";

						                  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 BOSR = clang::SourceRange(BOSL, BOSLE);
							        	  if (ConvertToSCPP && decl_source_range.isValid() && (BOSR.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;
											        	  auto replacement_text = (*iter).replacement_text();
											        	  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(*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 adj_decl_source_text = Rewrite.getRewrittenText(adj_decl_source_range);
								            	  auto res = Rewrite.ReplaceText(decl_source_range, declaration_replacement_code);
							        		  }
							            	  auto res2 = Rewrite.ReplaceText(BOSR, bo_replacement_code);
							            	  int q = 3;
							              } else {
							            	  int q = 7;
							              }
					        		  }
					        	  }
								  int q = 5;
							  }
						  }
					  }
				  } else {
					  int q = 5;
				  }
				  int q = 5;
			  }
    	  }

      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};

class MCSSSMallocInitializer : public MatchFinder::MatchCallback
{
public:
	MCSSSMallocInitializer (Rewriter &Rewrite, CState1& state1)
		: Rewrite(Rewrite), m_state1(state1) {}

  virtual void run(const MatchFinder::MatchResult &MR)
  {
	const DeclStmt* DS = MR.Nodes.getNodeAs<clang::DeclStmt>("mcsssmallocinitializer1");
	const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssmallocinitializer2");
	const DeclaratorDecl* DD = MR.Nodes.getNodeAs<clang::DeclaratorDecl>("mcsssmallocinitializer3");

	if ((DS != nullptr) && (CE != nullptr) && (DD != nullptr))
    {
        auto DSSR = nice_source_range(DS->getSourceRange(), Rewrite);
        SourceLocation DSSL = DSSR.getBegin();
        SourceLocation DSSLE = DSSR.getEnd();

        ASTContext *const ASTC = MR.Context;
        FullSourceLoc FDSSL = ASTC->getFullLoc(DSSL);

        SourceManager &SM = ASTC->getSourceManager();

        auto source_location_str = DSSL.printToString(*MR.SourceManager);
        std::string source_text;
        if (DSSL.isValid() && DSSLE.isValid()) {
      	  source_text = Rewrite.getRewrittenText(SourceRange(DSSL, DSSLE));
        } else {
      	  return;
        }

      if (filtered_out_by_location(MR, DSSL)) {
        return void();
      }

      auto function_decl = CE->getDirectCallee();
      auto num_args = CE->getNumArgs();
      if (function_decl && ((1 == num_args) || (2 == num_args))) {
		  std::string function_name = function_decl->getNameAsString();
		  static const std::string alloc_str = "alloc";
		  static const std::string realloc_str = "realloc";
		  auto lc_function_name = tolowerstr(function_name);
		  bool ends_with_alloc = ((lc_function_name.size() >= alloc_str.size())
				  && (0 == lc_function_name.compare(lc_function_name.size() - alloc_str.size(), alloc_str.size(), alloc_str)));
		  bool ends_with_realloc = (ends_with_alloc && (lc_function_name.size() >= realloc_str.size())
				  && (0 == lc_function_name.compare(lc_function_name.size() - realloc_str.size(), realloc_str.size(), realloc_str)));
		  bool still_potentially_valid1 = (ends_with_alloc && (1 == num_args)) || (ends_with_realloc && (2 == num_args));
		  if (still_potentially_valid1) {
			  auto iter = CE->arg_begin();
			  if (ends_with_realloc) {
				  iter++;
			  }
			  {
				  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);
					  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);
						  if (std::string::npos != sizeof_end_index) {
							  assert(sizeof_end_index > sizeof_start_index);
							  std::string before_str = arg_source_text.substr(0, sizeof_start_index);
							  std::string after_str;
							  if (sizeof_end_index + 1 < arg_source_text.size()) {
								  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]) {
									  asterisk_found = true;
								  }
								  if (!std::isspace(before_str[index])) {
									  break;
								  }

								  index -= 1;
							  }
							  if (asterisk_found) {
								  before_str = before_str.substr(0, index);
							  } else {
								  size_t index2 = 0;
								  while (after_str.size() > index2) {
									  if ('*' == after_str[index2]) {
										  asterisk_found = true;
									  }
									  if (!std::isspace(after_str[index2])) {
										  break;
									  }

									  index2 += 1;
								  }
								  if (asterisk_found) {
									  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;
									  }

							          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;
							          }

									  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 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(*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;
							              }
					        		  }
					        	  }
								  int q = 5;
							  }
						  }
					  }
				  } else {
					  int q = 5;
				  }
				  int q = 5;
			  }
    	  }

      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};

class MCSSSFree : public MatchFinder::MatchCallback
{
public:
	MCSSSFree (Rewriter &Rewrite, CState1& state1)
		: Rewrite(Rewrite), m_state1(state1) {}

  virtual void run(const MatchFinder::MatchResult &MR)
  {
	const CallExpr* CE = MR.Nodes.getNodeAs<clang::CallExpr>("mcsssfree1");
	const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcsssfree2");
	const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcsssfree3");

	if ((CE != nullptr) && (DRE != nullptr))
    {
        auto CESR = nice_source_range(CE->getSourceRange(), Rewrite);
        SourceLocation CESL = CESR.getBegin();
        SourceLocation CESLE = CESR.getEnd();

        ASTContext *const ASTC = MR.Context;
        FullSourceLoc FCESL = ASTC->getFullLoc(CESL);

        SourceManager &SM = ASTC->getSourceManager();

        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;
        }

      if (filtered_out_by_location(MR, CESL)) {
        return void();
      }

      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;

					  auto decl = DRE->getDecl();
					  DD = dynamic_cast<const DeclaratorDecl*>(decl);
					  auto VD = dynamic_cast<const VarDecl*>(decl);

					  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;
					  }

					  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;
						  }

						  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 CESR = clang::SourceRange(CESL, CESLE);
								  if (ConvertToSCPP && (CESR.isValid())) {
									  auto res2 = Rewrite.ReplaceText(CESR, ce_replacement_code);
									  int q = 3;
								  } else {
									  int q = 7;
								  }
							  }
						  } 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 = 5;
				  } else {
					  int q = 5;
				  }
				  int q = 5;
			  }
    	  }

      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};

class MCSSSSetToNull : public MatchFinder::MatchCallback
{
public:
	MCSSSSetToNull (Rewriter &Rewrite, CState1& state1)
		: Rewrite(Rewrite), m_state1(state1) {}

  virtual void run(const MatchFinder::MatchResult &MR)
  {
	const BinaryOperator* BO = MR.Nodes.getNodeAs<clang::BinaryOperator>("mcssssettonull1");
	const Expr* RHS = nullptr;
	const Expr* LHS = nullptr;
	if (BO != nullptr) {
		RHS = BO->getRHS();
		LHS = BO->getLHS();
	}
	const DeclRefExpr* DRE = MR.Nodes.getNodeAs<clang::DeclRefExpr>("mcssssettonull3");
	const MemberExpr* ME = MR.Nodes.getNodeAs<clang::MemberExpr>("mcssssettonull4");

	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();

        ASTContext *const ASTC = MR.Context;
        FullSourceLoc FBOSL = ASTC->getFullLoc(BOSL);

        SourceManager &SM = ASTC->getSourceManager();

        auto source_location_str = BOSL.printToString(*MR.SourceManager);
        std::string source_text;
        if (BOSL.isValid() && BOSLE.isValid()) {
      	  source_text = Rewrite.getRewrittenText(SourceRange(BOSL, BOSLE));
        } else {
      	  return;
        }

      if (filtered_out_by_location(MR, BOSL)) {
        return void();
      }

      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);

			  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;

			  auto decl = DRE->getDecl();
			  DD = dynamic_cast<const DeclaratorDecl*>(decl);
			  auto VD = dynamic_cast<const VarDecl*>(decl);

			  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;
			  }

			  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 ((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;
							  }
						  } else {
							  int q = 5;
						  }
					  } 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);
					  }
				  }
			  }
			  int q = 5;
		  } else {
			  int q = 5;
		  }
		  int q = 5;
      }
    }
  }

private:
  Rewriter &Rewrite;
  CState1& m_state1;
};


/**********************************************************************************************************************/
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)
  {
	  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(binaryOperator(allOf(
	  		hasOperatorName("="),
	  		hasRHS(
	  				anyOf(
	  						cStyleCastExpr(has(callExpr().bind("mcsssmalloc2"))),
								callExpr().bind("mcsssmalloc2")
	  				)
				),
	  		hasLHS(anyOf(
	  				memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4"),
	  				hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssmalloc3")))).bind("mcsssmalloc4")),
						hasDescendant(declRefExpr().bind("mcsssmalloc3")),
						declRefExpr().bind("mcsssmalloc3")
				)),
	  		hasLHS(expr(hasType(pointerType())))
				)).bind("mcsssmalloc1"), &HandlerForSSSMalloc);

	  Matcher.addMatcher(declStmt(hasDescendant(
	  		varDecl(hasInitializer(ignoringImpCasts(
					anyOf(
							cStyleCastExpr(has(callExpr().bind("mcsssmallocinitializer2"))),
							callExpr().bind("mcsssmallocinitializer2")
					)
	  		))).bind("mcsssmallocinitializer3")
				)).bind("mcsssmallocinitializer1"), &HandlerForSSSMallocInitializer);

	  Matcher.addMatcher(
	  		callExpr(allOf(
	  				hasAnyArgument(
	  				expr(anyOf(
								memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfree2")))).bind("mcsssfree3"),
								hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcsssfree2")))).bind("mcsssfree3")),
								hasDescendant(declRefExpr().bind("mcsssfree2"))
						))),
						argumentCountIs(1),
						hasAnyArgument(hasType(pointerType()))
	  		)).bind("mcsssfree1"), &HandlerForSSSFree);

	  Matcher.addMatcher(binaryOperator(allOf(
	  		hasOperatorName("="),
	  		hasLHS(anyOf(
	  				memberExpr(expr(hasDescendant(declRefExpr().bind("mcssssettonull3")))).bind("mcssssettonull4"),
	  				hasDescendant(memberExpr(expr(hasDescendant(declRefExpr().bind("mcssssettonull3")))).bind("mcssssettonull4")),
						hasDescendant(declRefExpr().bind("mcssssettonull3"))
				)),
				hasLHS(expr(hasType(pointerType())))
				)).bind("mcssssettonull1"), &HandlerForSSSSetToNull);
  }

  void HandleTranslationUnit(ASTContext &Context) override 
  {
    Matcher.matchAST(Context);
  }

private:

  CState1 m_state1;

  MCSSSNativePointer HandlerForSSSNativePointer;
  MCSSSArrayToPointerDecay HandlerForSSSArrayToPointerDecay;
  MCSSSVarDecl HandlerForSSSVarDecl;
  MCSSSPointerArithmetic HandlerForSSSPointerArithmetic;
  MCSSSMalloc HandlerForSSSMalloc;
  MCSSSMallocInitializer HandlerForSSSMallocInitializer;
  MCSSSFree HandlerForSSSFree;
  MCSSSSetToNull HandlerForSSSSetToNull;

  MatchFinder Matcher;
};

/**********************************************************************************************************************/
class MyFrontendAction : public ASTFrontendAction 
{
public:
  MyFrontendAction() {}
  ~MyFrontendAction() {
	  if (ConvertToSCPP) {
		  auto res = overwriteChangedFiles();
		  int q = 5;
	  }
  }

  void EndSourceFileAction() override {
    TheRewriter.getEditBuffer(TheRewriter.getSourceMgr().getMainFileID()).write(llvm::outs());
  }

  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) override {
    TheRewriter.setSourceMgr(CI.getSourceManager(), CI.getLangOpts());
    return llvm::make_unique<MyASTConsumer>(TheRewriter);
  }

  bool overwriteChangedFiles() {
	  return TheRewriter.overwriteChangedFiles();
  }

private:
  Rewriter TheRewriter;
};
/**********************************************************************************************************************/
/*Main*/
int main(int argc, const char **argv) 
{
  CommonOptionsParser op(argc, argv, MatcherSampleCategory);
  ClangTool Tool(op.getCompilations(), op.getSourcePathList());

  return Tool.run(newFrontendActionFactory<MyFrontendAction>().get());
}
/*last line intentionally left blank*/