diff --git a/src/main/scala/leon/purescala/CallGraph.scala b/src/main/scala/leon/purescala/CallGraph.scala
index 9247f0071b4e87fa65f4f173c30256898ae73b46..63886dfd27c2eaf8af28bd993ab26de98cc9e873 100644
--- a/src/main/scala/leon/purescala/CallGraph.scala
+++ b/src/main/scala/leon/purescala/CallGraph.scala
@@ -37,6 +37,21 @@ class CallGraph(p: Program) {
   def transitiveCallees(from: Set[FunDef]): Set[FunDef] = from.flatMap(transitiveCallees)
   def transitiveCallers(to: Set[FunDef]): Set[FunDef] = to.flatMap(transitiveCallers)
 
+  lazy val stronglyConnectedComponents: Seq[Set[FunDef]] = {
+    def rec(funs: Set[FunDef]): Seq[Set[FunDef]] = {
+      if (funs.isEmpty) Seq()
+      else {
+        val h = funs.head
+        val component = transitiveCallees(h).filter{ transitivelyCalls(_, h) } + h
+        component +: rec(funs -- component)
+      }
+    }
+    rec(p.definedFunctions.toSet)
+  }
+  
+  def stronglyConnectedComponent(fd: FunDef) = 
+    stronglyConnectedComponents.find{ _.contains(fd) }.getOrElse(Set(fd))
+
   private def init() {
     _calls   = Set()
     _callers = Map()
diff --git a/src/main/scala/leon/solvers/Solver.scala b/src/main/scala/leon/solvers/Solver.scala
index 3703464cf25e36c329203ffd39f5558825e4778b..daf7b84999f46bd6ebcd647e86477d5e383f18ff 100644
--- a/src/main/scala/leon/solvers/Solver.scala
+++ b/src/main/scala/leon/solvers/Solver.scala
@@ -4,9 +4,9 @@ package leon
 package solvers
 
 import utils.DebugSectionSolver
-import purescala.Expressions.Expr
+import purescala.Expressions._
 import purescala.Common.Identifier
-
+import verification.VC
 
 trait Solver {
   def name: String
@@ -15,6 +15,9 @@ trait Solver {
   implicit lazy val leonContext = context
 
   def assertCnstr(expression: Expr): Unit
+  def assertVC(vc: VC) = {
+    assertCnstr(Not(vc.condition))
+  }
 
   def check: Option[Boolean]
   def getModel: Map[Identifier, Expr]
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4QuantifiedSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4QuantifiedSolver.scala
index 3bdc59d2556c528f74715d78b806d0118939a3b2..53239581b267bd8fce175541202e744809c2e4c0 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4QuantifiedSolver.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4QuantifiedSolver.scala
@@ -5,10 +5,11 @@ package solvers.smtlib
 
 import purescala._
 import Expressions._
-import Definitions.{Program, TypedFunDef}
+import Definitions._
 import Constructors.{application, implies}
 import DefOps.typedTransitiveCallees
-import smtlib.parser.Commands.{Assert => SMTAssert, _}
+import verification.VC
+import smtlib.parser.Commands.{Assert => SMTAssert, FunDef => _, _}
 import smtlib.parser.Terms._
 import smtlib.theories.Core.Equals
 
@@ -17,6 +18,13 @@ import smtlib.theories.Core.Equals
 abstract class SMTLIBCVC4QuantifiedSolver(context: LeonContext, program: Program) extends SMTLIBCVC4Solver(context, program) {
 
   override def targetName = "cvc4-quantified"
+  
+  private var currentFunDef: Option[FunDef] = None
+  def refersToCurrent(fd: FunDef) = {
+    (currentFunDef contains fd) || (currentFunDef exists {
+      program.callGraph.transitivelyCalls(fd, _)
+    })
+  }
 
   private val typedFunDefExplorationLimit = 10000
 
@@ -54,9 +62,9 @@ abstract class SMTLIBCVC4QuantifiedSolver(context: LeonContext, program: Program
       }
     }
 
-    val seen = withParams filterNot functions.containsA
+    val notSeen = withParams filterNot functions.containsA
 
-    val smtFunDecls = seen map { tfd =>
+    val smtFunDecls = notSeen map { tfd =>
       val id = if (tfd.tps.isEmpty) {
         tfd.id
       } else {
@@ -85,12 +93,17 @@ abstract class SMTLIBCVC4QuantifiedSolver(context: LeonContext, program: Program
     }
 
     if (smtFunDecls.nonEmpty) {
+      //println("smtFuns: ")
+      //println(smtFunDecls map { _.name.name} mkString ", ")
+      //println(s"current: ${currentFunDef.get.id}")
       sendCommand(DefineFunsRec(smtFunDecls, smtBodies))
       // Assert contracts for defined functions
       for {
-        tfd <- seen
+        // Exclude contracts of functions that refer to current to avoid unsoundness
+        tfd <- notSeen if !refersToCurrent(tfd.fd)
         post <- tfd.postcondition
       } {
+        //println(s"${tfd.id.uniqueName} does not refer to ${currentFunDef.get.id.uniqueName}")
         val term = implies(
           tfd.precondition getOrElse BooleanLiteral(true),
           application(post, Seq(FunctionInvocation(tfd, tfd.params map { _.toVariable})))
@@ -119,4 +132,12 @@ abstract class SMTLIBCVC4QuantifiedSolver(context: LeonContext, program: Program
         addError()
     }
 
+  // We need to know the function context.
+  // The reason is we do not want to assume postconditions of functions referring to 
+  // the current function, as this may make the proof unsound
+  override def assertVC(vc: VC) = {
+    currentFunDef = Some(vc.fd)
+    super.assertVC(vc)
+  }
+
 }
diff --git a/src/main/scala/leon/verification/AnalysisPhase.scala b/src/main/scala/leon/verification/AnalysisPhase.scala
index c6a39924c7f5d289878f7403c346eb88e9ec3966..ce65a93bfe16269bb91b382429cc9197343cdb60 100644
--- a/src/main/scala/leon/verification/AnalysisPhase.scala
+++ b/src/main/scala/leon/verification/AnalysisPhase.scala
@@ -4,12 +4,12 @@ package leon
 package verification
 
 import purescala.Definitions._
-import purescala.Expressions._
 import purescala.ExprOps._
 
 import scala.concurrent.duration._
 
 import solvers._
+import solvers.smtlib.SMTLIBCVC4QuantifiedSolver
 
 object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
   val name = "Analysis"
@@ -38,7 +38,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
     reporter.debug("Generating Verification Conditions...")
 
     try { 
-      val vcs = generateVCs(vctx, filterFuns)
+      val vcs = generateVCs(vctx, filterFuns, forceGrouped = baseSolverF.getNewSolver.isInstanceOf[SMTLIBCVC4QuantifiedSolver])
 
       reporter.debug("Checking Verification Conditions...")
 
@@ -48,13 +48,14 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
     }
   }
 
-  def generateVCs(vctx: VerificationContext, filterFuns: Option[Seq[String]]): Seq[VC] = {
+  def generateVCs(vctx: VerificationContext, filterFuns: Option[Seq[String]], forceGrouped: Boolean = false): Seq[VC] = {
 
     import vctx.reporter
     import vctx.program
 
     val defaultTactic   = new DefaultTactic(vctx)
     val inductionTactic = new InductionTactic(vctx)
+    val groupedTactic   = new GroupedTactic(vctx)
 
     def excludeByDefault(fd: FunDef): Boolean = fd.annotations contains "library"
 
@@ -72,7 +73,9 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
       }
 
       val tactic: Tactic =
-        if(funDef.annotations.contains("induct")) {
+        if (forceGrouped) {
+          groupedTactic
+        } else if(funDef.annotations.contains("induct")) {
           inductionTactic
         } else {
           defaultTactic
@@ -138,7 +141,7 @@ object AnalysisPhase extends LeonPhase[Program,VerificationReport] {
 
       val tStart = System.currentTimeMillis
 
-      s.assertCnstr(Not(vcCond))
+      s.assertVC(vc)
 
       val satResult = s.check
 
diff --git a/src/main/scala/leon/verification/GroupedTactic.scala b/src/main/scala/leon/verification/GroupedTactic.scala
new file mode 100644
index 0000000000000000000000000000000000000000..6ef63a8f8cdc4e9a21171e06e501387f8e684e52
--- /dev/null
+++ b/src/main/scala/leon/verification/GroupedTactic.scala
@@ -0,0 +1,90 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon
+package verification
+
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Definitions._
+import purescala.Constructors._
+
+class GroupedTactic(vctx: VerificationContext) extends Tactic(vctx) {
+    val description = "Default verification condition generation approach"
+
+    def generatePostconditions(fd: FunDef): Seq[VC] = {
+      fd.postcondition map { post =>
+        val perFunc = for {
+          inComp <- vctx.program.callGraph.stronglyConnectedComponent(fd)
+          p <- inComp.postcondition
+          b <- inComp.body
+        } yield {
+          implies(
+            precOrTrue(inComp),
+            application(p, Seq(b))
+          )
+        }
+        
+        VC(andJoin(perFunc.toSeq), fd, VCKinds.Postcondition, this).setPos(post)
+      }
+    }.toSeq
+
+    def generatePreconditions(fd: FunDef): Seq[VC] = {
+      fd.body match {
+        case Some(body) =>
+          val calls = collectWithPC {
+            case c @ FunctionInvocation(tfd, _) if tfd.hasPrecondition => (c, tfd.precondition.get)
+          }(body)
+
+          calls.map {
+            case ((fi @ FunctionInvocation(tfd, args), pre), path) =>
+              val pre2 = replaceFromIDs((tfd.params.map(_.id) zip args).toMap, pre)
+              val vc = implies(and(precOrTrue(fd), path), pre2)
+              val fiS = exprToShortString(fi)
+              VC(vc, fd, VCKinds.Info(VCKinds.Precondition, s"call $fiS"), this).setPos(fi)
+          }
+
+        case None =>
+          Nil
+      }
+    }
+
+    def generateCorrectnessConditions(fd: FunDef): Seq[VC] = {
+      fd.body match {
+        case Some(body) =>
+          val calls = collectWithPC {
+            case e @ Error(_, "Match is non-exhaustive") =>
+              (e, VCKinds.ExhaustiveMatch, BooleanLiteral(false))
+
+
+            case e @ Error(_, _) =>
+              (e, VCKinds.Assert, BooleanLiteral(false))
+
+            case a @ Assert(cond, Some(err), _) => 
+              val kind = if (err.startsWith("Map ")) {
+                VCKinds.MapUsage
+              } else if (err.startsWith("Array ")) {
+                VCKinds.ArrayUsage
+              } else if (err.startsWith("Division ")) {
+                VCKinds.DivisionByZero
+              } else {
+                VCKinds.Assert
+              }
+
+              (a, kind, cond)
+            case a @ Assert(cond, None, _) => (a, VCKinds.Assert, cond)
+            // Only triggered for inner ensurings, general postconditions are handled by generatePostconditions
+            case a @ Ensuring(body, post) => (a, VCKinds.Assert, application(post, Seq(body)))
+          }(body)
+
+          calls.map {
+            case ((e, kind, errorCond), path) =>
+              val vc = implies(and(precOrTrue(fd), path), errorCond)
+
+              VC(vc, fd, kind, this).setPos(e)
+          }
+
+        case None =>
+          Nil
+      }
+    }
+}