Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package cvise for openSUSE:Factory checked 
in at 2022-12-16 17:51:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/cvise (Old)
 and      /work/SRC/openSUSE:Factory/.cvise.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "cvise"

Fri Dec 16 17:51:37 2022 rev:64 rq:1043346 version:2.6.0+git.20221216.1423ed5

Changes:
--------
--- /work/SRC/openSUSE:Factory/cvise/cvise.changes      2022-12-14 
14:11:31.831657513 +0100
+++ /work/SRC/openSUSE:Factory/.cvise.new.1835/cvise.changes    2022-12-16 
17:51:44.292046225 +0100
@@ -1,0 +2,18 @@
+Fri Dec 16 14:46:32 UTC 2022 - mli...@suse.cz
+
+- Update to version 2.6.0+git.20221216.1423ed5:
+  * Split remove-base-class transformation into remove-base-class and 
merge-base-class and supporting templated base classes
+  * Update reason comment.
+  * Improve LLVM version detection.
+  * Add support for skipIf get_llvm_version.
+
+-------------------------------------------------------------------
+Thu Dec 15 17:37:53 UTC 2022 - mli...@suse.cz
+
+- Update to version 2.6.0+git.20221215.2f76b4f:
+  * Added getDescribedTemplateParams for backwards compatibility
+  * The move-function-body transformation learned to move class methods, 
templated functions and methods within templated classes
+  * testing: quit if we cannot create bug report
+  * Fixed crash in reduce-class-template-param
+
+-------------------------------------------------------------------

Old:
----
  cvise-2.6.0+git.20221214.96f841e.tar.xz

New:
----
  cvise-2.6.0+git.20221216.1423ed5.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ cvise.spec ++++++
--- /var/tmp/diff_new_pack.a0wCJ1/_old  2022-12-16 17:51:44.840049241 +0100
+++ /var/tmp/diff_new_pack.a0wCJ1/_new  2022-12-16 17:51:44.844049263 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           cvise
-Version:        2.6.0+git.20221214.96f841e
+Version:        2.6.0+git.20221216.1423ed5
 Release:        0
 Summary:        Super-parallel Python port of the C-Reduce
 License:        BSD-3-Clause

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.a0wCJ1/_old  2022-12-16 17:51:44.908049615 +0100
+++ /var/tmp/diff_new_pack.a0wCJ1/_new  2022-12-16 17:51:44.912049637 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/marxin/cvise</param>
-              <param 
name="changesrevision">96f841e316adad54bdce10cc2b045eaf4619e142</param></service></servicedata>
+              <param 
name="changesrevision">1423ed528af9bcef03169c09c3a5077cf65867b4</param></service></servicedata>
 (No newline at EOF)
 

++++++ cvise-2.6.0+git.20221214.96f841e.tar.xz -> 
cvise-2.6.0+git.20221216.1423ed5.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/CMakeLists.txt 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/CMakeLists.txt
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/CMakeLists.txt     
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/CMakeLists.txt     
2022-12-16 15:46:11.000000000 +0100
@@ -118,6 +118,30 @@
   "/tests/reduce-array-dim/non-type-temp-arg.output"
   "/tests/reduce-pointer-level/scalar-init-expr.cpp"
   "/tests/reduce-pointer-level/scalar-init-expr.output"
+  "/tests/merge-base-class/test1.cc"
+  "/tests/merge-base-class/test1.output"
+  "/tests/merge-base-class/test2.cc"
+  "/tests/merge-base-class/test2.output"
+  "/tests/merge-base-class/test3.cc"
+  "/tests/merge-base-class/test3.output"
+  "/tests/remove-base-class/test1.cc"
+  "/tests/remove-base-class/test1.output"
+  "/tests/remove-base-class/test2.cc"
+  "/tests/remove-base-class/test2.output"
+  "/tests/remove-base-class/test3.cc"
+  "/tests/remove-base-class/test3.output"
+  "/tests/remove-base-class/test4.cc"
+  "/tests/remove-base-class/test4.output"
+  "/tests/move-function-body/test1.cc"
+  "/tests/move-function-body/test1.output"
+  "/tests/move-function-body/test2.cc"
+  "/tests/move-function-body/test2.output"
+  "/tests/move-function-body/test3.cc"
+  "/tests/move-function-body/test3.output"
+  "/tests/move-function-body/test4.cc"
+  "/tests/move-function-body/test4.output"
+  "/tests/move-function-body/test5.cc"
+  "/tests/move-function-body/test5.output"
   "/tests/remove-namespace/macro.cpp"
   "/tests/remove-namespace/macro.output"
   "/tests/remove-namespace/macro.output2"
@@ -519,6 +543,7 @@
   RemoveArray.h
   RemoveBaseClass.cpp
   RemoveBaseClass.h
+  MergeBaseClass.cpp
   RemoveCtorInitializer.cpp
   RemoveCtorInitializer.h
   RemoveEnumMemberValue.cpp
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MergeBaseClass.cpp 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MergeBaseClass.cpp
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MergeBaseClass.cpp 
1970-01-01 01:00:00.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MergeBaseClass.cpp 
2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// Copyright (c) 2012, 2013, 2014, 2015, 2016, 2017, 2018 The University of 
Utah
+// All rights reserved.
+//
+// This file is distributed under the University of Illinois Open Source
+// License.  See the file COPYING for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "RemoveBaseClass.h"
+
+#include "TransformationManager.h"
+
+static const char* DescriptionMsg =
+"This pass merges a base class into a derived class if \n\
+  * it has less than or equal to 5 declarations. \n\
+All its declarations will be moved into one of its subclasses, \
+and all references to this base class will be replaced with \
+the corresponding subclass. \n";
+
+static RegisterTransformation<RemoveBaseClass, RemoveBaseClass::EMode>
+         Trans("merge-base-class", DescriptionMsg, 
RemoveBaseClass::EMode::Merge);
+
+
+// Implementation is in RemoveBaseClass.cp
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MoveFunctionBody.cpp 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MoveFunctionBody.cpp
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MoveFunctionBody.cpp       
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MoveFunctionBody.cpp       
2022-12-16 15:46:11.000000000 +0100
@@ -24,58 +24,41 @@
 
 static const char *DescriptionMsg =
 "Move function body towards its declaration. \
-Note that this pass would generate incompilable code. \n";
+Note that this pass would generate uncompilable code. \n";
 
 static RegisterTransformation<MoveFunctionBody>
          Trans("move-function-body", DescriptionMsg);
 
-void MoveFunctionBody::Initialize(ASTContext &context) 
-{
-  Transformation::Initialize(context);
-}
-
-bool MoveFunctionBody::HandleTopLevelDecl(DeclGroupRef D) 
-{
-  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
-    FunctionDecl *FD = dyn_cast<FunctionDecl>(*I);
-    if (!FD || isInIncludedFile(FD)) {
-      PrevFunctionDecl = NULL;
-      continue;
-    }
+class MoveFunctionBody::CollectionVisitor : public 
RecursiveASTVisitor<CollectionVisitor> {
+    MoveFunctionBody* ConsumerInstance;
 
-    FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
-    if (FD->isThisDeclarationADefinition()) {
-      FunctionDecl *FDDecl = AllValidFunctionDecls[CanonicalFD];
-      if (!FDDecl) {
-        PrevFunctionDecl = NULL;
-        continue;
-      }
+public:
+  explicit CollectionVisitor(MoveFunctionBody* Instance) : 
ConsumerInstance(Instance)
+  { }
+
+  bool VisitFunctionDecl(FunctionDecl* FuncDef) {
+    if (!FuncDef->isThisDeclarationADefinition())
+      return true;
+
+    auto* FuncDecl = FuncDef->getFirstDecl();
+    if (FuncDef == FuncDecl)
+      return true;
+    if (ConsumerInstance->isInIncludedFile(FuncDef) || 
ConsumerInstance->isInIncludedFile(FuncDecl))
+      return true;
 
-      // Declaration and Definition are next to each other
-      if (PrevFunctionDecl) {
-        FunctionDecl *CanonicalPrevFD = PrevFunctionDecl->getCanonicalDecl();
-        if (CanonicalFD == CanonicalPrevFD) {
-          PrevFunctionDecl = NULL;
-          continue;
-        }
-      }
+    ConsumerInstance->FunctionCandidates.push_back(FuncDef);
 
-      FuncDeclToFuncDef[FDDecl] = FD;
-    }
+    return true;
+  }
 
-    PrevFunctionDecl = FD;
-    // We only need the first FunctionDecl
-    if (AllValidFunctionDecls[CanonicalFD])
-      continue;
+private:
+};
 
-    AllValidFunctionDecls[CanonicalFD] = FD;
-  }
-  return true;
-}
- 
 void MoveFunctionBody::HandleTranslationUnit(ASTContext &Ctx)
 {
-  doAnalysis();
+  CollectionVisitor(this).TraverseDecl(Ctx.getTranslationUnitDecl());
+
+  ValidInstanceNum = FunctionCandidates.size();
 
   if (QueryInstanceOnly)
     return;
@@ -85,6 +68,9 @@
     return;
   }
 
+  TheFunctionDef = FunctionCandidates[TransformationCounter-1];
+  TheFunctionDecl = TheFunctionDef->getFirstDecl();
+
   Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
 
   TransAssert(TheFunctionDecl && "NULL TheFunctionDecl!");
@@ -101,28 +87,70 @@
     TransError = TransInternalError;
 }
 
-void MoveFunctionBody::doAnalysis(void)
-{
-  for (FuncDeclToFuncDeclMap::iterator I = FuncDeclToFuncDef.begin(),
-       E = FuncDeclToFuncDef.end(); I != E; ++I) {
-    ValidInstanceNum++;
-
-    if (ValidInstanceNum == TransformationCounter) {
-      TheFunctionDecl = (*I).first;
-      TheFunctionDef = (*I).second;
-    }
-  }
+// Decl::getDescribedTemplateParams was introduced in LLVM 11.
+// Copied here for backwards compatibility.
+static const TemplateParameterList* getDescribedTemplateParams(Decl* D) {
+  if (auto* TD = D->getDescribedTemplate())
+    return TD->getTemplateParameters();
+  if (auto* CTPSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
+    return CTPSD->getTemplateParameters();
+  if (auto* VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl>(D))
+    return VTPSD->getTemplateParameters();
+  return nullptr;
 }
 
 void MoveFunctionBody::doRewriting(void)
 {
-  std::string FuncDefStr;
-  RewriteHelper->getFunctionDefStrAndRemove(TheFunctionDef, FuncDefStr);
-  RewriteHelper->addStringAfterFuncDecl(TheFunctionDecl, FuncDefStr);
+  SourceRange DefRange = RewriteHelper->getDeclFullSourceRange(TheFunctionDef);
+
+  // Remove namespace and class qualifiers
+  if (auto QL = TheFunctionDef->getQualifierLoc()) {
+    TheRewriter.RemoveText(QL.getSourceRange());
+  }
+
+  if (auto* MD = dyn_cast<CXXMethodDecl>(TheFunctionDecl)) {
+    // Update the template parameters name of the class if they are empty
+    // This is very likely since unused parameter names gets removed during 
reduction
+    if (TheFunctionDef->getNumTemplateParameterLists() == 1) {
+      TemplateParameterList* TPL = TheFunctionDef->getTemplateParameterList(0);
+
+      if (const TemplateParameterList* ClassTPL = 
getDescribedTemplateParams(MD->getParent())) {
+        assert(TPL->size() == ClassTPL->size());
+        for (unsigned i2 = 0; i2 < ClassTPL->size(); ++i2) {
+          auto* Param = TPL->getParam(i2);
+          auto* ClassParam = ClassTPL->getParam(i2);
+
+          if (ClassParam->getName().empty()) {
+            std::string ParamStr = 
TheRewriter.getRewrittenText(Param->getSourceRange());
+            TheRewriter.ReplaceText(ClassParam->getSourceRange().getEnd(), 
ParamStr);
+          }
+        }
+      }
+
+      TheRewriter.RemoveText(TPL->getSourceRange());
+    }
+
+    // Removing template lists for classes
+    for (unsigned i = 0; i < TheFunctionDef->getNumTemplateParameterLists(); 
++i) {
+      TemplateParameterList* TPL = TheFunctionDef->getTemplateParameterList(i);
+      TheRewriter.RemoveText(TPL->getSourceRange());
+    }
+  }
+
+  std::string FuncDefStr = TheRewriter.getRewrittenText(DefRange);
+
+  TheRewriter.RemoveText(DefRange);
+
+  // Inside a class we need to remove the declaration
+  if (isa<CXXMethodDecl>(TheFunctionDecl)) {
+    auto DeclRange = RewriteHelper->getDeclFullSourceRange(TheFunctionDecl);
+    TheRewriter.ReplaceText(DeclRange, FuncDefStr);
+  } else {
+    RewriteHelper->addStringAfterFuncDecl(TheFunctionDecl, FuncDefStr);
+  }
 }
 
 MoveFunctionBody::~MoveFunctionBody(void)
 {
   // Nothing to do
 }
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MoveFunctionBody.h 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MoveFunctionBody.h
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/MoveFunctionBody.h 
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/MoveFunctionBody.h 
2022-12-16 15:46:11.000000000 +0100
@@ -22,14 +22,13 @@
 }
 
 class MoveFunctionBody : public Transformation {
+  class CollectionVisitor;
+
 
 public:
 
   MoveFunctionBody(const char *TransName, const char *Desc)
-    : Transformation(TransName, Desc),
-      TheFunctionDecl(NULL),
-      TheFunctionDef(NULL),
-      PrevFunctionDecl(NULL)
+    : Transformation(TransName, Desc)
   { }
 
   ~MoveFunctionBody(void);
@@ -39,31 +38,14 @@
   typedef llvm::DenseMap<clang::FunctionDecl *, clang::FunctionDecl *>
             FuncDeclToFuncDeclMap;
 
-  virtual void Initialize(clang::ASTContext &context);
-
-  virtual bool HandleTopLevelDecl(clang::DeclGroupRef D);
-
   virtual void HandleTranslationUnit(clang::ASTContext &Ctx);
 
-  void doAnalysis(void);
-
   void doRewriting(void);
 
-  FuncDeclToFuncDeclMap AllValidFunctionDecls;
-
-  FuncDeclToFuncDeclMap FuncDeclToFuncDef;
-
-  clang::FunctionDecl *TheFunctionDecl;
-
-  clang::FunctionDecl *TheFunctionDef;
-
-  clang::FunctionDecl *PrevFunctionDecl;
-
-  // Unimplemented
-  MoveFunctionBody(void);
+  std::vector<clang::FunctionDecl*> FunctionCandidates;
 
-  MoveFunctionBody(const MoveFunctionBody &);
+  clang::FunctionDecl *TheFunctionDecl = nullptr;
 
-  void operator=(const MoveFunctionBody &);
+  clang::FunctionDecl *TheFunctionDef = nullptr;
 };
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/ReduceClassTemplateParameter.cpp
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/ReduceClassTemplateParameter.cpp
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/ReduceClassTemplateParameter.cpp
   2022-12-14 08:57:16.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/ReduceClassTemplateParameter.cpp
   2022-12-16 15:46:11.000000000 +0100
@@ -206,10 +206,8 @@
                                               "<>");
   }
   else if ((ConsumerInstance->TheParameterIndex + 1) == NumArgs) {
-    SourceLocation EndLoc = Loc.getRAngleLoc();
-    EndLoc = EndLoc.getLocWithOffset(-1);
     ConsumerInstance->RewriteHelper->removeTextFromLeftAt(
-                                       Range, ',', EndLoc);
+                                       Range, ',', Range.getEnd());
   }
   else {
     ConsumerInstance->RewriteHelper->removeTextUntil(Range, ',');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RemoveBaseClass.cpp 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RemoveBaseClass.cpp
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RemoveBaseClass.cpp        
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RemoveBaseClass.cpp        
2022-12-16 15:46:11.000000000 +0100
@@ -24,19 +24,14 @@
 using namespace clang_delta_common_visitor;
 
 static const char *DescriptionMsg = 
-"This pass removes a base class from its class hierarchy if \n\
-  * it has less than or equal to 5 declarations, and \n\
-  * it is not a templated class. \n\
-All its declarations will be moved into one of its subclasses, \
-and all references to this base class will be replaced with \
-the corresponding subclass. \n";
+"This pass removes a base class from a derived class. \n";
 
 // Note that this pass doesn't do much analysis, so
-// it will produce quite a few incompilable code, especially
+// it will produce quite a few uncompilable code, especially
 // when multi-inheritance is involved.
 
-static RegisterTransformation<RemoveBaseClass>
-         Trans("remove-base-class", DescriptionMsg);
+static RegisterTransformation<RemoveBaseClass, RemoveBaseClass::EMode>
+         Trans("remove-base-class", DescriptionMsg, 
RemoveBaseClass::EMode::Remove);
 
 class RemoveBaseClassBaseVisitor : public 
   RecursiveASTVisitor<RemoveBaseClassBaseVisitor> {
@@ -60,20 +55,6 @@
   return true;
 }
 
-class RemoveBaseClassRewriteVisitor : public
-  CommonRenameClassRewriteVisitor<RemoveBaseClassRewriteVisitor> 
-{
-public:
-  RemoveBaseClassRewriteVisitor(Transformation *Instance,
-                                Rewriter *RT,
-                                RewriteUtils *Helper,
-                                const CXXRecordDecl *CXXRD,
-                                const std::string &Name)
-    : CommonRenameClassRewriteVisitor<RemoveBaseClassRewriteVisitor>
-      (Instance, RT, Helper, CXXRD, Name)
-  { }
-};
-
 void RemoveBaseClass::Initialize(ASTContext &context) 
 {
   Transformation::Initialize(context);
@@ -102,13 +83,6 @@
   TransAssert(TheDerivedClass && "TheDerivedClass is NULL!");
   Ctx.getDiagnostics().setSuppressAllDiagnostics(false);
 
-  RewriteVisitor = 
-    new RemoveBaseClassRewriteVisitor(this, &TheRewriter, RewriteHelper,
-                                      TheBaseClass->getCanonicalDecl(),
-                                      TheDerivedClass->getNameAsString());
-
-  TransAssert(RewriteVisitor && "NULL RewriteVisitor!");
-  RewriteVisitor->TraverseDecl(Ctx.getTranslationUnitDecl());
   doRewrite();
 
   if (Ctx.getDiagnostics().hasErrorOccurred() ||
@@ -134,59 +108,39 @@
 
 void RemoveBaseClass::handleOneCXXRecordDecl(const CXXRecordDecl *CXXRD)
 {
-  if (isSpecialRecordDecl(CXXRD) || CXXRD->getDescribedClassTemplate() || 
-      !CXXRD->hasDefinition())
+  if (isSpecialRecordDecl(CXXRD) || !CXXRD->isThisDeclarationADefinition())
     return;
 
-  const CXXRecordDecl *CanonicalRD = CXXRD->getCanonicalDecl();
-  if (VisitedCXXRecordDecls.count(CanonicalRD))
-    return;
-  VisitedCXXRecordDecls.insert(CanonicalRD);
-  if (CanonicalRD->getNumBases()) {
-    const CXXRecordDecl *Base = NULL;
-    for (CXXRecordDeclSet::iterator I = AllBaseClasses.begin(), 
-         E = AllBaseClasses.end(); I != E; ++I) {
-      if (const ClassTemplateSpecializationDecl * CTSD = 
-          dyn_cast<ClassTemplateSpecializationDecl>
-            (CanonicalRD->getDefinition())) {
-        if (!CTSD->isExplicitSpecialization())
-          continue;
-      }
+  for (const CXXBaseSpecifier& BS : CXXRD->bases()) {
+    auto* Base = BS.getType()->getAsCXXRecordDecl();
 
-      if (isInIncludedFile(*I))
-        continue;
-      if (isDirectlyDerivedFrom(CanonicalRD, *I)) {
-        Base = (*I);
-        ValidInstanceNum++;
-        if (ValidInstanceNum == TransformationCounter) {
-          TransAssert(Base->hasDefinition() && 
-                      "Base class does not have any definition!");
-          TheBaseClass = Base->getDefinition();
-          TransAssert(CanonicalRD->hasDefinition() && 
-                      "Derived class does not have any definition!");
-          TheDerivedClass = CanonicalRD->getDefinition();
-        }
-      }
+    if (Base == nullptr)
+      continue;
+    if (Mode == EMode::Merge && getNumExplicitDecls(Base) > MaxNumDecls)
+      continue;
+    if (isInIncludedFile(Base))
+      continue;
+
+    ValidInstanceNum++;
+    if (ValidInstanceNum == TransformationCounter) {
+      TransAssert(Base->hasDefinition() && "Base class does not have any 
definition!");
+      TheBaseClass = Base->getDefinition();
+      TheDerivedClass = CXXRD;
     }
-    return;
   }
-
-  if (getNumExplicitDecls(CanonicalRD) > MaxNumDecls)
-    return;
-
-  if (!AllBaseClasses.count(CanonicalRD))
-    AllBaseClasses.insert(CanonicalRD);
 }
 
 void RemoveBaseClass::doRewrite(void)
 {
-  copyBaseClassDecls();
+  if (Mode == EMode::Merge)
+    copyBaseClassDecls();
   removeBaseSpecifier();
-  RewriteHelper->removeClassDecls(TheBaseClass);
+  if (Mode == EMode::Merge)
+    RewriteHelper->removeClassDecls(TheBaseClass);
 
   // ISSUE: I didn't handle Base initializer in a Ctor's initlist.
   //        * keeping it untouched is wrong, because delegating constructors 
-  //        are only valie in c++11
+  //        are only valid in c++11
   //        * naively removing the base initializer doesn't work in some cases,
   //        e.g., 
   //        class A { 
@@ -207,13 +161,37 @@
 {
   if (!getNumExplicitDecls(TheBaseClass))
     return;
-  SourceLocation StartLoc = TheBaseClass->getBraceRange().getBegin();
-  SourceLocation EndLoc = TheBaseClass->getBraceRange().getEnd();
-  TransAssert(EndLoc.isValid() && "Invalid RBraceLoc!");
-  EndLoc = EndLoc.getLocWithOffset(-1);
 
-  std::string DeclsStr = 
-    TheRewriter.getRewrittenText(SourceRange(StartLoc, EndLoc));
+  std::string DeclsStr;
+  auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TheBaseClass);
+  if (CTSD && CTSD->getSpecializationKind() == TSK_ImplicitInstantiation) {
+    // For template bases, we use the printing feature of clang to generate
+    // the class with all resolved template parameters
+
+    // Rename internally the constructors to the derived class
+    for (CXXConstructorDecl* CD : CTSD->ctors()) {
+      CD->setDeclName(TheDerivedClass->getDeclName());
+    }
+
+    llvm::raw_string_ostream Strm(DeclsStr);
+    CTSD->print(Strm);
+
+    DeclsStr.erase(0, DeclsStr.find('{') + 1);
+    DeclsStr.erase(DeclsStr.rfind('}'), 1);
+  } else {
+    // Rename constructors
+    for (CXXConstructorDecl* CD : TheBaseClass->ctors()) {
+      TheRewriter.ReplaceText(CD->getNameInfo().getSourceRange(), 
TheDerivedClass->getDeclName().getAsString());
+    }
+
+    SourceLocation StartLoc = TheBaseClass->getBraceRange().getBegin();
+    SourceLocation EndLoc = TheBaseClass->getBraceRange().getEnd();
+    TransAssert(EndLoc.isValid() && "Invalid RBraceLoc!");
+    StartLoc = StartLoc.getLocWithOffset(1);
+    EndLoc = EndLoc.getLocWithOffset(-1);
+
+    DeclsStr = TheRewriter.getRewrittenText(SourceRange(StartLoc, EndLoc)) + 
"\n";
+  }
 
   TransAssert(!DeclsStr.empty() && "Empty DeclsStr!");
   SourceLocation InsertLoc = TheDerivedClass->getBraceRange().getEnd();
@@ -290,16 +268,16 @@
 
 void RemoveBaseClass::removeBaseInitializer(void)
 {
-  for (CXXRecordDecl::ctor_iterator I = TheDerivedClass->ctor_begin(),
-       E = TheDerivedClass->ctor_end(); I != E; ++I) {
-    if ((*I)->isThisDeclarationADefinition() && !(*I)->isDefaulted())
-      rewriteOneCtor(*I);
+  for (Decl* D : TheDerivedClass->decls()) {
+    if (auto* FTD = dyn_cast<FunctionTemplateDecl>(D))
+      D =FTD->getTemplatedDecl();
+    if (auto* Ctor = dyn_cast<CXXConstructorDecl>(D))
+      if (Ctor->isThisDeclarationADefinition() && !Ctor->isDefaulted())
+        rewriteOneCtor(Ctor);
   }
 }
 
 RemoveBaseClass::~RemoveBaseClass(void)
 {
   delete CollectionVisitor;
-  delete RewriteVisitor;
 }
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RemoveBaseClass.h 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RemoveBaseClass.h
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RemoveBaseClass.h  
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RemoveBaseClass.h  
2022-12-16 15:46:11.000000000 +0100
@@ -22,21 +22,17 @@
 }
 
 class RemoveBaseClassBaseVisitor;
-class RemoveBaseClassRewriteVisitor;
 
 class RemoveBaseClass : public Transformation {
 friend class RemoveBaseClassBaseVisitor;
 
 public:
-  RemoveBaseClass(const char *TransName, const char *Desc)
+  enum class EMode { Remove, Merge };
+
+  RemoveBaseClass(const char *TransName, const char *Desc, EMode Mode)
     : Transformation(TransName, Desc),
-      CollectionVisitor(NULL),
-      RewriteVisitor(NULL),
-      TheBaseClass(NULL),
-      TheDerivedClass(NULL),
-      MaxNumDecls(5)
+      Mode(Mode)
   { }
-
   ~RemoveBaseClass(void);
 
 private:
@@ -63,19 +59,15 @@
 
   bool isTheBaseClass(const clang::CXXBaseSpecifier &Specifier);
 
-  CXXRecordDeclSet VisitedCXXRecordDecls;
-
-  CXXRecordDeclSet AllBaseClasses;
-
-  RemoveBaseClassBaseVisitor *CollectionVisitor;
+  RemoveBaseClassBaseVisitor *CollectionVisitor = nullptr;
 
-  RemoveBaseClassRewriteVisitor *RewriteVisitor;
+  const clang::CXXRecordDecl *TheBaseClass = nullptr;
 
-  const clang::CXXRecordDecl *TheBaseClass;
+  const clang::CXXRecordDecl *TheDerivedClass = nullptr;
 
-  const clang::CXXRecordDecl *TheDerivedClass;
+  const unsigned MaxNumDecls = 5;
 
-  const unsigned MaxNumDecls;
+  EMode Mode;
 
   // Unimplemented
   RemoveBaseClass(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RewriteUtils.cpp 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RewriteUtils.cpp
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RewriteUtils.cpp   
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RewriteUtils.cpp   
2022-12-16 15:46:11.000000000 +0100
@@ -173,6 +173,45 @@
   return EndLoc.getLocWithOffset(Offset);
 }
 
+clang::SourceRange RewriteUtils::getDeclFullSourceRange(const clang::Decl* D)
+{
+  SourceRange Range = D->getSourceRange();
+
+  // Ensure that template parameters are included in the def range
+  if (auto* FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->getNumTemplateParameterLists()) {
+      TemplateParameterList* TPL = FD->getTemplateParameterList(0);
+      Range.setBegin(TPL->getSourceRange().getBegin());
+    } else if (auto* T = FD->getDescribedTemplate()) {
+      TemplateParameterList* TPL = T->getTemplateParameters();
+      Range.setBegin(TPL->getSourceRange().getBegin());
+    }
+  } else if (auto* TD = dyn_cast<TagDecl>(D)) {
+    if (TD->getNumTemplateParameterLists()) {
+      TemplateParameterList* TPL = TD->getTemplateParameterList(0);
+      Range.setBegin(TPL->getSourceRange().getBegin());
+    } else if (auto* T = TD->getDescribedTemplate()) {
+      TemplateParameterList* TPL = T->getTemplateParameters();
+      Range.setBegin(TPL->getSourceRange().getBegin());
+    }
+  }
+
+
+  // Include the semicolon into the declaration. 
+  // See DeclPrinter::VisitDeclContext in clang source code for all cases.
+  bool HasSemicolon = true;
+  if (auto* FD = dyn_cast<FunctionDecl>(D)) {
+    HasSemicolon = !FD->doesThisDeclarationHaveABody();
+  } else if (auto* FTD = dyn_cast<FunctionTemplateDecl>(D)) {
+    HasSemicolon = !FTD->getTemplatedDecl()->isThisDeclarationADefinition();
+  }
+
+  if (HasSemicolon)
+    Range.setEnd(getEndLocationAfter(Range, ';'));
+
+  return Range;
+}
+
 SourceLocation RewriteUtils::getLocationAfter(SourceLocation Loc, 
                                                 char Symbol)
 {
@@ -1862,22 +1901,17 @@
 
 bool RewriteUtils::removeClassDecls(const CXXRecordDecl *CXXRD)
 {
-  for (CXXRecordDecl::redecl_iterator I = CXXRD->redecls_begin(),
-      E = CXXRD->redecls_end(); I != E; ++I) {
-    SourceRange Range = (*I)->getSourceRange();
-    SourceLocation LocEnd;
-    if ((*I)->isThisDeclarationADefinition()) {
-      LocEnd = (*I)->getBraceRange().getEnd();
-      if (LocEnd.isValid())
-        LocEnd = getLocationUntil(LocEnd, ';');
-      else
-        LocEnd = getEndLocationUntil(Range, ';');
-    }
-    else {
-      LocEnd = getEndLocationUntil(Range, ';');
-    }
-    TheRewriter->RemoveText(SourceRange(Range.getBegin(), LocEnd));
+  if (auto* CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
+    if (CTSD->getSpecializationKind() == TSK_ImplicitInstantiation)
+      CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
+  }
+
+  for (const TagDecl* Redecl : CXXRD->redecls()) {
+    SourceRange Range = getDeclFullSourceRange(Redecl);
+    if (Range.isValid())
+      TheRewriter->RemoveText(Range);
   }
+
   return true;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RewriteUtils.h 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RewriteUtils.h
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/RewriteUtils.h     
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/RewriteUtils.h     
2022-12-16 15:46:11.000000000 +0100
@@ -282,6 +282,8 @@
   clang::SourceLocation getLocationAfterSkiping(clang::SourceLocation StartLoc,
                                                 char Symbol);
 
+  clang::SourceRange getDeclFullSourceRange(const clang::Decl* D);
+
 private:
 
   static RewriteUtils *Instance;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/TransformationManager.h 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/TransformationManager.h
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/TransformationManager.h    
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/TransformationManager.h    
2022-12-16 15:46:11.000000000 +0100
@@ -184,12 +184,12 @@
 
 };
 
-template<typename TransformationClass>
+template<typename TransformationClass, typename... Args>
 class RegisterTransformation {
 
 public:
-  RegisterTransformation(const char *TransName, const char *Desc) {
-    Transformation *TransImpl = new TransformationClass(TransName, Desc);
+  RegisterTransformation(const char *TransName, const char *Desc, Args... 
args) {
+    Transformation *TransImpl = new TransformationClass(TransName, Desc, 
args...);
     assert(TransImpl && "Fail to create TransformationClass");
  
     TransformationManager::registerTransformation(TransName, TransImpl);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test1.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test1.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test1.cc
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test1.cc
    2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+struct c1 {
+       int x;
+       int y;
+       
+       // hello
+       c1(int x);
+};
+
+struct c2 : public c1 {
+       c2() :  c1(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test1.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test1.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test1.output
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test1.output
        2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,13 @@
+
+
+
+struct c2  {
+       c2()  {
+       }
+       
+
+       int x;
+       int y;
+       
+       // hello
+       c2(int x);
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test2.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test2.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test2.cc
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test2.cc
    2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+template <class T>
+struct c1 {
+       c1(T x);
+       
+       // hello
+       T y;
+};
+
+struct c2 : public c1<int> {
+       c2() :  c1<int>(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test2.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test2.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test2.output
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test2.output
        2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,11 @@
+
+
+
+struct c2  {
+       c2()  {
+       }
+       
+
+    c2(int x);
+    int y;
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test3.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test3.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test3.cc
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test3.cc
    2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,18 @@
+
+template <class T>
+struct c1 {
+};
+
+template <>
+struct c1<int> {
+       c1(int x);
+       
+       // hello
+       int y;
+};
+
+struct c2 : public c1<int> {
+       c2() :  c1<int>(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test3.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test3.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/merge-base-class/test3.output
        1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/merge-base-class/test3.output
        2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,16 @@
+
+template <class T>
+struct c1 {
+};
+
+
+
+struct c2  {
+       c2()  {
+       }
+       
+
+       c2(int x);
+       
+       // hello
+       int y;
};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test1.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test1.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test1.cc
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test1.cc
  2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,8 @@
+
+int test(int hello);
+
+// ...
+
+int test(int x) {
+       return 42;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test1.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test1.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test1.output
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test1.output
      2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,9 @@
+
+int test(int hello);
+int test(int x) {
+       return 42;
+}
+
+// ...
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test2.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test2.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test2.cc
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test2.cc
  2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,10 @@
+
+template <class T>
+T test(T);
+
+// ...
+
+template <class T>
+T test(T x) {
+       return x;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test2.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test2.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test2.output
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test2.output
      2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,11 @@
+
+template <class T>
+T test(T);
+template <class T>
+T test(T x) {
+       return x;
+}
+
+// ...
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test3.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test3.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test3.cc
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test3.cc
  2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,12 @@
+
+namespace ns {
+       struct C {
+               int test(int hello);
+       };
+}
+
+// ...
+
+int ns::C::test(int x) {
+       return 42;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test3.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test3.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test3.output
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test3.output
      2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,12 @@
+
+namespace ns {
+       struct C {
+               int test(int x) {
+       return 42;
+}
+       };
+}
+
+// ...
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test4.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test4.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test4.cc
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test4.cc
  2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+namespace ns {
+       struct C {
+               template <class T> 
+               T test(T hello);
+       };
+}
+
+// ...
+
+template <class T> 
+T ns::C::test(T x) {
+       return 42;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test4.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test4.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test4.output
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test4.output
      2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,13 @@
+
+namespace ns {
+       struct C {
+               template <class T> 
+T test(T x) {
+       return 42;
+}
+       };
+}
+
+// ...
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test5.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test5.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test5.cc
  1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test5.cc
  2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+template <class>
+struct C {
+       template <class T> 
+       T test(T hello);
+};
+
+// ...
+
+template <class T1> 
+template <class T2> 
+T2 C<T1>::test(T2 x) {
+       return T1();
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test5.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test5.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/move-function-body/test5.output
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/move-function-body/test5.output
      2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,13 @@
+
+template <class T1>
+struct C {
+        
+template <class T2> 
+T2 test(T2 x) {
+       return T1();
+}
+};
+
+// ...
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test1.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test1.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test1.cc
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test1.cc
   2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+struct c1 {
+       int x;
+       int y;
+       
+       // hello
+       c1(int x);
+};
+
+struct c2 : public c1 {
+       c2() :  c1(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test1.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test1.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test1.output
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test1.output
       2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+struct c1 {
+       int x;
+       int y;
+       
+       // hello
+       c1(int x);
+};
+
+struct c2  {
+       c2()  {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test2.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test2.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test2.cc
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test2.cc
   2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+template <class T>
+struct c1 {
+       c1(T x);
+       
+       // hello
+       T y;
+};
+
+struct c2 : public c1<int> {
+       c2() :  c1<int>(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test2.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test2.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test2.output
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test2.output
       2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,14 @@
+
+template <class T>
+struct c1 {
+       c1(T x);
+       
+       // hello
+       T y;
+};
+
+struct c2  {
+       c2()  {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test3.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test3.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test3.cc
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test3.cc
   2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,18 @@
+
+template <class T>
+struct c1 {
+};
+
+template <>
+struct c1<int> {
+       c1(int x);
+       
+       // hello
+       int y;
+};
+
+struct c2 : public c1<int> {
+       c2() :  c1<int>(5) {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test3.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test3.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test3.output
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test3.output
       2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,18 @@
+
+template <class T>
+struct c1 {
+};
+
+template <>
+struct c1<int> {
+       c1(int x);
+       
+       // hello
+       int y;
+};
+
+struct c2  {
+       c2()  {
+       }
+       
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test4.cc
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test4.cc
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test4.cc
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test4.cc
   2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,9 @@
+template <class T> 
+struct c {
+  c(T) {}
+};
+
+struct i : c<double>, c<int> {
+  template <class T>
+  i() : c<double>(1.0), c<int>(10) {}
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test4.output
 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test4.output
--- 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/remove-base-class/test4.output
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/remove-base-class/test4.output
       2022-12-16 15:46:11.000000000 +0100
@@ -0,0 +1,9 @@
+template <class T> 
+struct c {
+  c(T) {}
+};
+
+struct i :  c<int> {
+  template <class T>
+  i() :  c<int>(10) {}
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/test_clang_delta.py 
new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/test_clang_delta.py
--- old/cvise-2.6.0+git.20221214.96f841e/clang_delta/tests/test_clang_delta.py  
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/clang_delta/tests/test_clang_delta.py  
2022-12-16 15:46:11.000000000 +0100
@@ -1,8 +1,25 @@
 import os
+import re
 import subprocess
 import unittest
 
 
+def get_llvm_version():
+    current = os.path.dirname(__file__)
+    binary = os.path.join(current, '../clang_delta')
+    output = subprocess.check_output(f'ldd {binary}', shell=True, 
universal_newlines=True)
+    for line in output.splitlines():
+        part = line.strip().split()[0]
+        if part.startswith('libLLVM'):
+            m = re.match(r'libLLVM-(?P<version>[0-9]+)\.so', part)
+            if m:
+                return int(m.group('version'))
+            else:
+                return int(part.split('.')[-1])
+
+    raise AssertionError()
+
+
 class TestClangDelta(unittest.TestCase):
 
     @classmethod
@@ -357,7 +374,7 @@
     def test_rename_class_bool(self):
         self.check_clang_delta('rename-class/bool.cc', 
'--transformation=rename-class --counter=1')
 
-    @unittest.skip(reason='Fails with LLVM 16')
+    @unittest.skipIf(get_llvm_version() >= 16, 'Fails with LLVM >= 16')
     def test_rename_class_class_template(self):
         self.check_clang_delta('rename-class/class_template.cc', 
'--transformation=rename-class --counter=1')
 
@@ -614,3 +631,40 @@
 
     def test_rename_operator_test2(self):
         self.check_clang_delta('rename-operator/test2.cc', 
'--transformation=rename-operator --counter=1')
+
+    def test_merge_base_class_test1(self):
+        self.check_clang_delta('merge-base-class/test1.cc', 
'--transformation=merge-base-class --counter=1')
+
+    @unittest.skipIf(get_llvm_version() <= 9, 'Fails with LLVM <= 9')
+    def test_merge_base_class_test2(self):
+        self.check_clang_delta('merge-base-class/test2.cc', 
'--transformation=merge-base-class --counter=1')
+
+    def test_merge_base_class_test3(self):
+        self.check_clang_delta('merge-base-class/test3.cc', 
'--transformation=merge-base-class --counter=1')
+
+    def test_remove_base_class_test1(self):
+        self.check_clang_delta('remove-base-class/test1.cc', 
'--transformation=remove-base-class --counter=1')
+
+    def test_remove_base_class_test2(self):
+        self.check_clang_delta('remove-base-class/test2.cc', 
'--transformation=remove-base-class --counter=1')
+
+    def test_remove_base_class_test3(self):
+        self.check_clang_delta('remove-base-class/test3.cc', 
'--transformation=remove-base-class --counter=1')
+
+    def test_remove_base_class_test4(self):
+        self.check_clang_delta('remove-base-class/test4.cc', 
'--transformation=remove-base-class --counter=1')
+
+    def test_move_function_body_test1(self):
+        self.check_clang_delta('move-function-body/test1.cc', 
'--transformation=move-function-body --counter=1')
+
+    def test_move_function_body_test2(self):
+        self.check_clang_delta('move-function-body/test2.cc', 
'--transformation=move-function-body --counter=1')
+
+    def test_move_function_body_test3(self):
+        self.check_clang_delta('move-function-body/test3.cc', 
'--transformation=move-function-body --counter=1')
+
+    def test_move_function_body_test4(self):
+        self.check_clang_delta('move-function-body/test4.cc', 
'--transformation=move-function-body --counter=1')
+
+    def test_move_function_body_test5(self):
+        self.check_clang_delta('move-function-body/test5.cc', 
'--transformation=move-function-body --counter=1')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/cvise/pass_groups/all.json 
new/cvise-2.6.0+git.20221216.1423ed5/cvise/pass_groups/all.json
--- old/cvise-2.6.0+git.20221214.96f841e/cvise/pass_groups/all.json     
2022-12-14 08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/cvise/pass_groups/all.json     
2022-12-16 15:46:11.000000000 +0100
@@ -85,6 +85,7 @@
     {"pass": "clang", "arg": "reduce-class-template-param", "c": true },
     {"pass": "clang", "arg": "remove-trivial-base-template", "c": true },
     {"pass": "clang", "arg": "class-template-to-class", "c": true },
+    {"pass": "clang", "arg": "merge-base-class", "c": true },
     {"pass": "clang", "arg": "remove-base-class", "c": true },
     {"pass": "clang", "arg": "replace-derived-class", "c": true },
     {"pass": "clang", "arg": "remove-unresolved-base", "c": true },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/cvise-2.6.0+git.20221214.96f841e/cvise/utils/testing.py 
new/cvise-2.6.0+git.20221216.1423ed5/cvise/utils/testing.py
--- old/cvise-2.6.0+git.20221214.96f841e/cvise/utils/testing.py 2022-12-14 
08:57:16.000000000 +0100
+++ new/cvise-2.6.0+git.20221216.1423ed5/cvise/utils/testing.py 2022-12-16 
15:46:11.000000000 +0100
@@ -253,13 +253,15 @@
         return extra_dir
 
     def report_pass_bug(self, test_env, problem):
+        """Create pass report bug and return True if the directory is 
created."""
+
         if not self.die_on_pass_bug:
             logging.warning(f'{self.current_pass} has encountered a non fatal 
bug: {problem}')
 
         crash_dir = self.get_extra_dir('cvise_bug_', self.MAX_CRASH_DIRS)
 
         if crash_dir is None:
-            return
+            return False
 
         os.mkdir(crash_dir)
         test_env.dump(crash_dir)
@@ -276,6 +278,8 @@
 
         if self.die_on_pass_bug:
             raise PassBugError(self.current_pass, problem, test_env.state, 
crash_dir)
+        else:
+            return True
 
     @staticmethod
     def diff_files(orig_file, changed_file):
@@ -382,7 +386,8 @@
                         # Report bug if transform did not change the file
                         if filecmp.cmp(self.current_test_case, 
test_env.test_case_path):
                             if not self.silent_pass_bug:
-                                self.report_pass_bug(test_env, 'pass failed to 
modify the variant')
+                                if not self.report_pass_bug(test_env, 'pass 
failed to modify the variant'):
+                                    quit_loop = True
                         else:
                             quit_loop = True
                             new_futures.add(future)

Reply via email to