Add proper support for the declare-heap command for separation logic (#5405)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Tue, 10 Nov 2020 13:43:19 +0000 (07:43 -0600)
committerGitHub <noreply@github.com>
Tue, 10 Nov 2020 13:43:19 +0000 (07:43 -0600)
This adds proper support for the (declare-heap (T U)) command, which declares the type of the heap in separation logic. This command is part of the standard for separation logic.

This previous was handled in an ad-hoc way where the type of the heap would be inferred on demand. This was a poor solution and has led to a number of issues related to when the heap is inferred.

Fixes #5343, fixes #4926.

Work towards CVC4/cvc4-wishues#22.

68 files changed:
src/api/cvc4cpp.cpp
src/api/cvc4cpp.h
src/api/python/cvc4.pxd
src/api/python/cvc4.pxi
src/parser/smt2/Smt2.g
src/printer/printer.cpp
src/printer/printer.h
src/printer/smt2/smt2_printer.cpp
src/printer/smt2/smt2_printer.h
src/smt/command.cpp
src/smt/command.h
src/smt/smt_engine.cpp
src/smt/smt_engine.h
src/theory/sep/theory_sep.cpp
src/theory/sep/theory_sep.h
src/theory/smt_engine_subsolver.cpp
src/theory/smt_engine_subsolver.h
src/theory/theory.h
src/theory/theory_engine.cpp
src/theory/theory_engine.h
test/api/sep_log_api.cpp
test/regress/regress0/sep/dispose-1.smt2
test/regress/regress0/sep/dup-nemp.smt2
test/regress/regress0/sep/issue3720-check-model.smt2
test/regress/regress0/sep/nemp.smt2
test/regress/regress0/sep/nil-no-elim.smt2
test/regress/regress0/sep/nspatial-simp.smt2
test/regress/regress0/sep/pto-01.smt2
test/regress/regress0/sep/pto-02.smt2
test/regress/regress0/sep/sep-01.smt2
test/regress/regress0/sep/sep-plus1.smt2
test/regress/regress0/sep/sep-simp-unsat-emp.smt2
test/regress/regress0/sep/simple-080420-const-sets.smt2
test/regress/regress0/sep/skolem_emp.smt2
test/regress/regress0/sep/trees-1.smt2
test/regress/regress0/sep/wand-crash.smt2
test/regress/regress1/sep/chain-int.smt2
test/regress/regress1/sep/crash1220.smt2
test/regress/regress1/sep/dispose-list-4-init.smt2
test/regress/regress1/sep/emp2-quant-unsat.smt2
test/regress/regress1/sep/finite-witness-sat.smt2
test/regress/regress1/sep/fmf-nemp-2.smt2
test/regress/regress1/sep/loop-1220.smt2
test/regress/regress1/sep/pto-04.smt2
test/regress/regress1/sep/quant_wand.smt2
test/regress/regress1/sep/sep-02.smt2
test/regress/regress1/sep/sep-03.smt2
test/regress/regress1/sep/sep-find2.smt2
test/regress/regress1/sep/sep-fmf-priority.smt2
test/regress/regress1/sep/sep-neg-1refine.smt2
test/regress/regress1/sep/sep-neg-nstrict.smt2
test/regress/regress1/sep/sep-neg-nstrict2.smt2
test/regress/regress1/sep/sep-neg-simple.smt2
test/regress/regress1/sep/sep-neg-swap.smt2
test/regress/regress1/sep/sep-nterm-again.smt2
test/regress/regress1/sep/sep-nterm-val-model.smt2
test/regress/regress1/sep/sep-simp-unc.smt2
test/regress/regress1/sep/simple-neg-sat.smt2
test/regress/regress1/sep/split-find-unsat-w-emp.smt2
test/regress/regress1/sep/split-find-unsat.smt2
test/regress/regress1/sep/wand-0526-sat.smt2
test/regress/regress1/sep/wand-false.smt2
test/regress/regress1/sep/wand-nterm-simp.smt2
test/regress/regress1/sep/wand-nterm-simp2.smt2
test/regress/regress1/sep/wand-simp-sat.smt2
test/regress/regress1/sep/wand-simp-sat2.smt2
test/regress/regress1/sep/wand-simp-unsat.smt2
test/unit/api/solver_black.h

index c0e6bad5fcb93fd316f3d08102a62bb54a199954..566bcc3c7418847f366c1f40add6552749ad7a79 100644 (file)
@@ -5194,6 +5194,17 @@ Term Solver::getQuantifierEliminationDisjunct(api::Term q) const
   CVC4_API_SOLVER_TRY_CATCH_END;
 }
 
+void Solver::declareSeparationHeap(api::Sort locSort, api::Sort dataSort) const
+{
+  CVC4_API_SOLVER_TRY_CATCH_BEGIN;
+  CVC4_API_CHECK(
+      d_smtEngine->getLogicInfo().isTheoryEnabled(theory::THEORY_SEP))
+      << "Cannot obtain separation logic expressions if not using the "
+         "separation logic theory.";
+  d_smtEngine->declareSepHeap(locSort.getTypeNode(), dataSort.getTypeNode());
+  CVC4_API_SOLVER_TRY_CATCH_END;
+}
+
 Term Solver::getSeparationHeap() const
 {
   CVC4_API_SOLVER_TRY_CATCH_BEGIN;
index 13d4f6e231d458ef034831ab8c7adae91edf1ab8..db57af121987fea23c6d2cdde5b06b78efc56434 100644 (file)
@@ -3157,6 +3157,15 @@ class CVC4_PUBLIC Solver
    */
   Term getQuantifierEliminationDisjunct(api::Term q) const;
 
+  /**
+   * When using separation logic, this sets the location sort and the
+   * datatype sort to the given ones. This method should be invoked exactly
+   * once, before any separation logic constraints are provided.
+   * @param locSort The location sort of the heap
+   * @param dataSort The data sort of the heap
+   */
+  void declareSeparationHeap(api::Sort locSort, api::Sort dataSort) const;
+
   /**
    * When using separation logic, obtain the term for the heap.
    * @return The term for the heap
index 13f4606daa655b681ceb7a12e16dc28541334f6b..29f997394180891253957ae3c762a913d5723b0d 100644 (file)
@@ -235,6 +235,7 @@ cdef extern from "api/cvc4cpp.h" namespace "CVC4::api":
         vector[Term] getUnsatCore() except +
         Term getValue(Term term) except +
         vector[Term] getValue(const vector[Term]& terms) except +
+        void declareSeparationHeap(Sort locSort, Sort dataSort) except +
         Term getSeparationHeap() except +
         Term getSeparationNilTerm() except +
         void pop(uint32_t nscopes) except +
index 16f4543112a8ea496d526d6c3fd6ce2506cda691..f945228dd62d97bf9757dbe9f2e083f2890004ff 100644 (file)
@@ -1122,6 +1122,9 @@ cdef class Solver:
         term.cterm = self.csolver.getSeparationHeap()
         return term
 
+    def declareSeparationHeap(self, Sort locType, Sort dataType):
+        self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
+
     def getSeparationNilTerm(self):
         cdef Term term = Term(self)
         term.cterm = self.csolver.getSeparationNilTerm()
index fe051f0362ef8567f32d0c1f40485d0643903952..40c66eaa52be25caf1daca12847de7f98a8facd8 100644 (file)
@@ -895,7 +895,7 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd]
 @declarations {
   std::vector<api::DatatypeDecl> dts;
   CVC4::api::Term e, e2;
-  CVC4::api::Sort t;
+  CVC4::api::Sort t, s;
   std::string name;
   std::vector<std::string> names;
   std::vector<CVC4::api::Term> terms;
@@ -1073,9 +1073,8 @@ extendedCommand[std::unique_ptr<CVC4::Command>* cmd]
     }
   | DECLARE_HEAP LPAREN_TOK
     sortSymbol[t, CHECK_DECLARED]
-    sortSymbol[t, CHECK_DECLARED]
-    // We currently do nothing with the type information declared for the heap.
-    { cmd->reset(new EmptyCommand()); }
+    sortSymbol[s, CHECK_DECLARED]
+    { cmd->reset(new DeclareHeapCommand(t, s)); }
     RPAREN_TOK
   | BLOCK_MODEL_TOK { PARSER_STATE->checkThatLogicIsSet(); }
     { cmd->reset(new BlockModelCommand()); }
index 195247df71e0e19181588e6d256861ba1afe4089..21eb88c8cc8eb242c25d67df28b68088d06950b5 100644 (file)
@@ -415,6 +415,13 @@ void Printer::toStreamCmdComment(std::ostream& out,
   printUnknownCommand(out, "comment");
 }
 
+void Printer::toStreamCmdDeclareHeap(std::ostream& out,
+                                     TypeNode locType,
+                                     TypeNode dataType) const
+{
+  printUnknownCommand(out, "declare-heap");
+}
+
 void Printer::toStreamCmdCommandSequence(
     std::ostream& out, const std::vector<Command*>& sequence) const
 {
index 84262d9928ba8afa1b4310fddaebf53737b511be..ffacaa5d8bdf2db867e070b69d76da4e0538c579 100644 (file)
@@ -256,6 +256,10 @@ class Printer
   /** Print comment command */
   virtual void toStreamCmdComment(std::ostream& out,
                                   const std::string& comment) const;
+  /** Declare heap command */
+  virtual void toStreamCmdDeclareHeap(std::ostream& out,
+                                      TypeNode locType,
+                                      TypeNode dataType) const;
 
   /** Print command sequence command */
   virtual void toStreamCmdCommandSequence(
index bc69023058d387fa1c7b0167a82bdf171641e4de..032d265112664b314273b7736edbde854c2f97d2 100644 (file)
@@ -1938,6 +1938,13 @@ void Smt2Printer::toStreamCmdComment(std::ostream& out,
   out << "(set-info :notes \"" << s << "\")" << std::endl;
 }
 
+void Smt2Printer::toStreamCmdDeclareHeap(std::ostream& out,
+                                         TypeNode locType,
+                                         TypeNode dataType) const
+{
+  out << "(declare-heap (" << locType << " " << dataType << "))" << std::endl;
+}
+
 void Smt2Printer::toStreamCmdEmpty(std::ostream& out,
                                    const std::string& name) const
 {
index f4783c955e98ca9f1002b3c48f339b465bebaf15..3fc144d4617685c4a1ea85481cf07306612c0103 100644 (file)
@@ -217,6 +217,11 @@ class Smt2Printer : public CVC4::Printer
   void toStreamCmdComment(std::ostream& out,
                           const std::string& comment) const override;
 
+  /** Print declare-heap command */
+  void toStreamCmdDeclareHeap(std::ostream& out,
+                              TypeNode locType,
+                              TypeNode dataType) const override;
+
   /** Print command sequence command */
   void toStreamCmdCommandSequence(
       std::ostream& out, const std::vector<Command*>& sequence) const override;
index 58ac57cc956b62db6d52ca4c3ad1bc46fd89b5ab..b33fe5ad96d1f02180cb71d204b4ef5232ae015c 100644 (file)
@@ -1425,9 +1425,43 @@ void DefineFunctionRecCommand::toStream(std::ostream& out,
       formals,
       api::termVectorToNodes(d_formulas));
 }
+/* -------------------------------------------------------------------------- */
+/* class DeclareHeapCommand                                                   */
+/* -------------------------------------------------------------------------- */
+DeclareHeapCommand::DeclareHeapCommand(api::Sort locSort, api::Sort dataSort)
+    : d_locSort(locSort), d_dataSort(dataSort)
+{
+}
+
+api::Sort DeclareHeapCommand::getLocationSort() const { return d_locSort; }
+api::Sort DeclareHeapCommand::getDataSort() const { return d_dataSort; }
+
+void DeclareHeapCommand::invoke(api::Solver* solver)
+{
+  solver->declareSeparationHeap(d_locSort, d_dataSort);
+}
+
+Command* DeclareHeapCommand::clone() const
+{
+  return new DeclareHeapCommand(d_locSort, d_dataSort);
+}
+
+std::string DeclareHeapCommand::getCommandName() const
+{
+  return "declare-heap";
+}
+
+void DeclareHeapCommand::toStream(std::ostream& out,
+                                  int toDepth,
+                                  size_t dag,
+                                  OutputLanguage language) const
+{
+  Printer::getPrinter(language)->toStreamCmdDeclareHeap(
+      out, d_locSort.getTypeNode(), d_dataSort.getTypeNode());
+}
 
 /* -------------------------------------------------------------------------- */
-/* class SetUserAttribute                                                     */
+/* class SetUserAttributeCommand                                              */
 /* -------------------------------------------------------------------------- */
 
 SetUserAttributeCommand::SetUserAttributeCommand(
index d2ce99f2fcef4eb85c30b54109c33f8ec946b9b8..438f9febb3989611d6c7a0b57375f780299973ba 100644 (file)
@@ -511,7 +511,6 @@ class CVC4_PUBLIC DefineNamedFunctionCommand : public DefineFunctionCommand
   void toStream(
       std::ostream& out,
       int toDepth = -1,
-
       size_t dag = 1,
       OutputLanguage language = language::output::LANG_AUTO) const override;
 }; /* class DefineNamedFunctionCommand */
@@ -561,6 +560,34 @@ class CVC4_PUBLIC DefineFunctionRecCommand : public Command
   bool d_global;
 }; /* class DefineFunctionRecCommand */
 
+/**
+ * In separation logic inputs, which is an extension of smt2 inputs, this
+ * corresponds to the command:
+ *   (declare-heap (T U))
+ * where T is the location sort and U is the data sort.
+ */
+class CVC4_PUBLIC DeclareHeapCommand : public Command
+{
+ public:
+  DeclareHeapCommand(api::Sort locSort, api::Sort dataSort);
+  api::Sort getLocationSort() const;
+  api::Sort getDataSort() const;
+  void invoke(api::Solver* solver) override;
+  Command* clone() const override;
+  std::string getCommandName() const override;
+  void toStream(
+      std::ostream& out,
+      int toDepth = -1,
+      size_t dag = 1,
+      OutputLanguage language = language::output::LANG_AUTO) const override;
+
+ protected:
+  /** The location sort */
+  api::Sort d_locSort;
+  /** The data sort */
+  api::Sort d_dataSort;
+};
+
 /**
  * The command when an attribute is set by a user.  In SMT-LIBv2 this is done
  *  via the syntax (! expr :attr)
index dc5338199846bc7ee25bd5a9cc0f01443f40bf14..a5861c6b08a2275e70098dbc40ca9acd22660dc2 100644 (file)
@@ -65,6 +65,7 @@
 #include "theory/logic_info.h"
 #include "theory/quantifiers/quantifiers_attributes.h"
 #include "theory/rewriter.h"
+#include "theory/smt_engine_subsolver.h"
 #include "theory/theory_engine.h"
 #include "util/hash.h"
 #include "util/random.h"
@@ -1448,6 +1449,28 @@ std::vector<Node> SmtEngine::getExpandedAssertions()
   return eassertsProc;
 }
 
+void SmtEngine::declareSepHeap(TypeNode locT, TypeNode dataT)
+{
+  if (!d_logic.isTheoryEnabled(THEORY_SEP))
+  {
+    const char* msg =
+        "Cannot declare heap if not using the separation logic theory.";
+    throw RecoverableModalException(msg);
+  }
+  SmtScope smts(this);
+  finishInit();
+  TheoryEngine* te = getTheoryEngine();
+  te->declareSepHeap(locT, dataT);
+}
+
+bool SmtEngine::getSepHeapTypes(TypeNode& locT, TypeNode& dataT)
+{
+  SmtScope smts(this);
+  finishInit();
+  TheoryEngine* te = getTheoryEngine();
+  return te->getSepHeapTypes(locT, dataT);
+}
+
 Node SmtEngine::getSepHeapExpr() { return getSepHeapAndNilExpr().first; }
 
 Node SmtEngine::getSepNilExpr() { return getSepHeapAndNilExpr().second; }
@@ -1483,21 +1506,28 @@ void SmtEngine::checkUnsatCore() {
   Notice() << "SmtEngine::checkUnsatCore(): generating unsat core" << endl;
   UnsatCore core = getUnsatCore();
 
-  SmtEngine coreChecker(d_exprManager, &d_options);
-  coreChecker.setIsInternalSubsolver();
-  coreChecker.setLogic(getLogicInfo());
-  coreChecker.getOptions().set(options::checkUnsatCores, false);
+  // initialize the core checker
+  std::unique_ptr<SmtEngine> coreChecker;
+  initializeSubsolver(coreChecker);
+  coreChecker->getOptions().set(options::checkUnsatCores, false);
+
+  // set up separation logic heap if necessary
+  TypeNode sepLocType, sepDataType;
+  if (getSepHeapTypes(sepLocType, sepDataType))
+  {
+    coreChecker->declareSepHeap(sepLocType, sepDataType);
+  }
 
   Notice() << "SmtEngine::checkUnsatCore(): pushing core assertions (size == " << core.size() << ")" << endl;
   for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
     Node assertionAfterExpansion = expandDefinitions(*i);
     Notice() << "SmtEngine::checkUnsatCore(): pushing core member " << *i
              << ", expanded to " << assertionAfterExpansion << "\n";
-    coreChecker.assertFormula(assertionAfterExpansion);
+    coreChecker->assertFormula(assertionAfterExpansion);
   }
   Result r;
   try {
-    r = coreChecker.checkSat();
+    r = coreChecker->checkSat();
   } catch(...) {
     throw;
   }
index de0daffd092c0ce6818c1d2e930d2f469997e95e..0661ae918c0f0dc5902ba6061d7d87e0356f1625 100644 (file)
@@ -309,6 +309,23 @@ class CVC4_PUBLIC SmtEngine
    */
   Result blockModelValues(const std::vector<Node>& exprs);
 
+  /**
+   * Declare heap. For smt2 inputs, this is called when the command
+   * (declare-heap (locT datat)) is invoked by the user. This sets locT as the
+   * location type and dataT is the data type for the heap. This command should
+   * be executed only once, and must be invoked before solving separation logic
+   * inputs.
+   */
+  void declareSepHeap(TypeNode locT, TypeNode dataT);
+
+  /**
+   * Get the separation heap types, which extracts which types were passed to
+   * the method above.
+   *
+   * @return true if the separation logic heap types have been declared.
+   */
+  bool getSepHeapTypes(TypeNode& locT, TypeNode& dataT);
+
   /** When using separation logic, obtain the expression for the heap.  */
   Node getSepHeapExpr();
 
index 013c61e5218a3d1ead0eaafb8427dbcb6fa2428c..1b25bb0f424b046a7efff277324c920a3bb08575 100644 (file)
@@ -69,6 +69,22 @@ TheorySep::~TheorySep() {
   }
 }
 
+void TheorySep::declareSepHeap(TypeNode locT, TypeNode dataT)
+{
+  if (!d_type_ref.isNull())
+  {
+    TypeNode te1 = d_loc_to_data_type.begin()->first;
+    std::stringstream ss;
+    ss << "ERROR: cannot declare heap types for separation logic more than "
+          "once.  We are declaring heap of type ";
+    ss << locT << " -> " << dataT << ", but we already have ";
+    ss << d_type_ref << " -> " << d_type_data;
+    throw LogicException(ss.str());
+  }
+  Node nullAtom;
+  registerRefDataTypes(locT, dataT, nullAtom);
+}
+
 TheoryRewriter* TheorySep::getTheoryRewriter() { return &d_rewriter; }
 
 bool TheorySep::needsEqualityEngine(EeSetupInfo& esi)
@@ -239,7 +255,6 @@ void TheorySep::postProcessModel( TheoryModel* m ){
 
 void TheorySep::presolve() {
   Trace("sep-pp") << "Presolving" << std::endl;
-  //TODO: cleanup if incremental?
 }
 
 
@@ -1119,48 +1134,43 @@ int TheorySep::processAssertion( Node n, std::map< int, std::map< Node, int > >&
 }
 
 void TheorySep::registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom ){
-  //separation logic is effectively enabled when we find at least one spatial constraint occurs in the input
-  if( options::incrementalSolving() ){
-    std::stringstream ss;
-    ss << "ERROR: cannot use separation logic in incremental mode." << std::endl;
-    throw LogicException(ss.str());
-  }
-  std::map< TypeNode, TypeNode >::iterator itt = d_loc_to_data_type.find( tn1 );
-  if( itt==d_loc_to_data_type.end() ){
-    if( !d_loc_to_data_type.empty() ){
-      TypeNode te1 = d_loc_to_data_type.begin()->first;
+  if (!d_type_ref.isNull())
+  {
+    Assert(!atom.isNull());
+    // already declared, ensure compatible
+    if ((!tn1.isNull() && !tn1.isComparableTo(d_type_ref))
+        || (!tn2.isNull() && !tn2.isComparableTo(d_type_data)))
+    {
       std::stringstream ss;
-      ss << "ERROR: specifying heap constraints for two different types : " << tn1 << " -> " << tn2 << " and " << te1 << " -> " << d_loc_to_data_type[te1] << std::endl;
-      throw LogicException(ss.str());
-      Assert(false);
-    }
-    if( tn2.isNull() ){
-      Trace("sep-type") << "Sep: assume location type " << tn1 << " (from " << atom << ")" << std::endl;
-    }else{
-      Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
-    }
-    d_loc_to_data_type[tn1] = tn2;
-    //for now, we only allow heap constraints of one type
-    d_type_ref = tn1;
-    d_type_data = tn2;
-    d_bound_kind[tn1] = bound_default;
-  }else{
-    if( !tn2.isNull() ){
-      if( itt->second!=tn2 ){
-        if( itt->second.isNull() ){
-          Trace("sep-type") << "Sep: assume location type " << tn1 << " is associated with data type " << tn2 << " (from " << atom << ")" << std::endl;
-          //now we know data type
-          d_loc_to_data_type[tn1] = tn2;
-          d_type_data = tn2;
-        }else{
-          std::stringstream ss;
-          ss << "ERROR: location type " << tn1 << " is already associated with data type " << itt->second << ", offending atom is " << atom << " with data type " << tn2 << std::endl;
-          throw LogicException(ss.str());
-          Assert(false);
-        }
-      }
+      ss << "ERROR: the separation logic heap type has already been set to "
+         << d_type_ref << " -> " << d_type_data
+         << " but we have a constraint that uses different heap types, "
+            "offending atom is "
+         << atom << " with associated heap type " << tn1 << " -> " << tn2
+         << std::endl;
     }
+    return;
+  }
+  // if not declared yet, and we have a separation logic constraint, throw
+  // an error.
+  if (!atom.isNull())
+  {
+    std::stringstream ss;
+    // error, heap not declared
+    ss << "ERROR: the type of the separation logic heap has not been declared "
+          "(e.g. via a declare-heap command), and we have a separation logic "
+          "constraint "
+       << atom << std::endl;
+    throw LogicException(ss.str());
   }
+  // otherwise set it
+  Trace("sep-type") << "Sep: assume location type " << tn1
+                    << " is associated with data type " << tn2 << std::endl;
+  d_loc_to_data_type[tn1] = tn2;
+  // for now, we only allow heap constraints of one type
+  d_type_ref = tn1;
+  d_type_data = tn2;
+  d_bound_kind[tn1] = bound_default;
 }
 
 void TheorySep::initializeBounds() {
index ac87ebe67b9d8e4f198df95dec7394c933bc1e31..2cd7aba915acc39473d6e5e79ce351d6a662b954 100644 (file)
@@ -79,6 +79,15 @@ class TheorySep : public Theory {
             ProofNodeManager* pnm = nullptr);
   ~TheorySep();
 
+  /**
+   * Declare heap. For smt2 inputs, this is called when the command
+   * (declare-heap (locT datat)) is invoked by the user. This sets locT as the
+   * location type and dataT is the data type for the heap. This command can be
+   * executed once only, and must be invoked before solving separation logic
+   * inputs.
+   */
+  void declareSepHeap(TypeNode locT, TypeNode dataT) override;
+
   //--------------------------------- initialization
   /** get the official theory rewriter of this theory */
   TheoryRewriter* getTheoryRewriter() override;
@@ -274,7 +283,14 @@ class TheorySep : public Theory {
   //get global reference/data type
   TypeNode getReferenceType( Node n );
   TypeNode getDataType( Node n );
-  void registerRefDataTypes( TypeNode tn1, TypeNode tn2, Node atom );
+  /**
+   * This is called either when:
+   * (A) a declare-heap command is issued with tn1/tn2, and atom is null, or
+   * (B) an atom specifying the heap type tn1/tn2 is registered to this theory.
+   * We set the heap type if we are are case (A), and check whether the
+   * heap type is consistent in the case of (B).
+   */
+  void registerRefDataTypes(TypeNode tn1, TypeNode tn2, Node atom);
   //get location/data type
   //get the base label for the spatial assertion
   Node getBaseLabel( TypeNode tn );
index cedb838af0c56d6b2347eea159bf92e34a0cf757..ed10e85ae13a3f0d7ae4e5df1cd9c3def55e6eed 100644 (file)
@@ -51,11 +51,11 @@ void initializeSubsolver(std::unique_ptr<SmtEngine>& smte,
   smte.reset(new SmtEngine(nm->toExprManager(), &smtCurr->getOptions()));
   smte->setIsInternalSubsolver();
   smte->setLogic(smtCurr->getLogicInfo());
+  // set the options
   if (needsTimeout)
   {
     smte->setTimeLimit(timeout);
   }
-  smte->setLogic(smt::currentSmtEngine()->getLogicInfo());
 }
 
 Result checkWithSubsolver(std::unique_ptr<SmtEngine>& smte,
index d34729dec9543a9c01c748f3a8a4252da681ec9c..f68900ccc0dc6562b569886a054e0cb14691ca03 100644 (file)
@@ -31,7 +31,16 @@ namespace theory {
 
 /**
  * This function initializes the smt engine smte to check the satisfiability
- * of the argument "query".
+ * of the argument "query". It takes the logic and options of the current
+ * SMT engine in scope.
+ *
+ * Notice this method intentionally does not fully initialize smte. This means
+ * that the options of smte can still be modified after it is returned by
+ * this method.
+ *
+ * Notice that some aspects of subsolvers are not incoporated by this call.
+ * For example, the type of separation logic heaps is not set on smte, even
+ * if the current SMT engine has declared a separation logic heap.
  *
  * @param smte The smt engine pointer to initialize
  * @param needsTimeout Whether we would like to set a timeout
index 9519624b771603d54d187162b08afcf7a7a2596e..6256360e4c6adb71085b6c1846b02e14fee07294 100644 (file)
@@ -248,6 +248,15 @@ class Theory {
     return d_logicInfo;
   }
 
+  /**
+   * Set separation logic heap. This is called when the location and data
+   * types for separation logic are determined. This should be called at
+   * most once, before solving.
+   *
+   * This currently should be overridden by the separation logic theory only.
+   */
+  virtual void declareSepHeap(TypeNode locT, TypeNode dataT) {}
+
   /**
    * The theory that owns the uninterpreted sort.
    */
index 706149d86f618caad10e7b32a2ce5af094807162..3a155b9ad3ce2407847360ef15f8af6a8788d8e6 100644 (file)
@@ -1116,6 +1116,42 @@ bool TheoryEngine::propagate(TNode literal, theory::TheoryId theory) {
 
 const LogicInfo& TheoryEngine::getLogicInfo() const { return d_logicInfo; }
 
+bool TheoryEngine::getSepHeapTypes(TypeNode& locType, TypeNode& dataType) const
+{
+  if (d_sepLocType.isNull())
+  {
+    return false;
+  }
+  locType = d_sepLocType;
+  dataType = d_sepDataType;
+  return true;
+}
+
+void TheoryEngine::declareSepHeap(TypeNode locT, TypeNode dataT)
+{
+  Theory* tsep = theoryOf(THEORY_SEP);
+  if (tsep == nullptr)
+  {
+    Assert(false) << "TheoryEngine::declareSepHeap called without the "
+                     "separation logic theory enabled";
+    return;
+  }
+
+  // Definition of the statement that is to be run by every theory
+#ifdef CVC4_FOR_EACH_THEORY_STATEMENT
+#undef CVC4_FOR_EACH_THEORY_STATEMENT
+#endif
+#define CVC4_FOR_EACH_THEORY_STATEMENT(THEORY) \
+  theoryOf(THEORY)->declareSepHeap(locT, dataT);
+
+  // notify each theory using the statement above
+  CVC4_FOR_EACH_THEORY;
+
+  // remember the types we have set
+  d_sepLocType = locT;
+  d_sepDataType = dataT;
+}
+
 theory::EqualityStatus TheoryEngine::getEqualityStatus(TNode a, TNode b) {
   Assert(a.getType().isComparableTo(b.getType()));
   return d_sharedSolver->getEqualityStatus(a, b);
index e47dbbc6fabca704f4556f47f5344f3f5348cc46..088e413bba630ba7754b1c7f02eda148b6563e6b 100644 (file)
@@ -139,6 +139,9 @@ class TheoryEngine {
    * the cost of walking the DAG on registration, etc.
    */
   const LogicInfo& d_logicInfo;
+  /** The separation logic location and data types */
+  TypeNode d_sepLocType;
+  TypeNode d_sepDataType;
 
   /** Reference to the output manager of the smt engine */
   OutputManager& d_outMgr;
@@ -637,6 +640,16 @@ class TheoryEngine {
   }
   /** get the logic info used by this theory engine */
   const LogicInfo& getLogicInfo() const;
+  /** get the separation logic heap types */
+  bool getSepHeapTypes(TypeNode& locType, TypeNode& dataType) const;
+
+  /**
+   * Declare heap. This is used for separation logics to set the location
+   * and data types. It should be called only once, and before any separation
+   * logic constraints are asserted to this theory engine.
+   */
+  void declareSepHeap(TypeNode locT, TypeNode dataT);
+
   /**
    * Returns the equality status of the two terms, from the theory
    * that owns the domain type.  The types of a and b must be the same.
index 1b1efb07ed1f8b90f33f6aa981504f8d9217d799..cc20f1ed1b7d2260431fb64773e52e3d7d621ee0 100644 (file)
@@ -46,6 +46,8 @@ int validate_exception(void)
   /* Our integer type */
   Sort integer = slv.getIntegerSort();
 
+  /** we intentionally do not set the separation logic heap */
+
   /* Our SMT constants */
   Term x = slv.mkConst(integer, "x");
   Term y = slv.mkConst(integer, "y");
@@ -134,6 +136,9 @@ int validate_getters(void)
   /* Our integer type */
   Sort integer = slv.getIntegerSort();
 
+  /** Declare the separation logic heap types */
+  slv.declareSeparationHeap(integer, integer);
+
   /* A "random" constant */
   Term random_constant = slv.mkInteger(0xDEADBEEF);
 
index 25a38b0187319b84abd2331d9bc1104b0f633766..aff32e241e3ac2fb1868124616c41ebbde729d3f 100644 (file)
@@ -1,6 +1,8 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
 
+(declare-heap (Int Int))
+
 (declare-const w Int)
 (declare-const w1 Int)
 (declare-const w2 Int)
index 20421e7353f45db39fc82532c43632e3ff9e7c0f..454b73f64fb2adc814ea0cbfcf575b46e641ccc2 100644 (file)
@@ -2,6 +2,7 @@
 (set-info :status unsat)
 (declare-sort Loc 0)
 (declare-const l Loc)
+(declare-heap (Loc Loc))
 (assert (sep (not (_ emp Loc Loc)) (not (_ emp Loc Loc))))
 (assert (pto l l))
 (check-sat)
index 6130c0ca87dd294bb8348ff3e6b72be58a27d794..7e9c73cb860fb475004cb610c9eeff5d7de8fc09 100644 (file)
@@ -1,5 +1,6 @@
 ; COMMAND-LINE: --quiet
 ; EXPECT: sat
 (set-logic ALL)
+(declare-heap (Int Int))
 (assert (_ emp Int Int))
 (check-sat)
index 2eaf664cd25930701e5e92f811f3e377c36944fe..583457e481a75f335630b94514edbc5f041933ea 100644 (file)
@@ -1,5 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
 (set-logic QF_SEP_LIA)
+(declare-heap (Int Int))
 (assert (not (_ emp Int Int)))
 (check-sat)
index e9aa3807ab45365ec081b35a84c45d35def8ad17..6e66568654de634a4562bc1bb67d31c431da3650 100644 (file)
@@ -3,6 +3,7 @@
 (declare-sort U 0)
 (declare-fun f (U) U)
 (declare-fun a () U)
+(declare-heap (U Int))
 
 (assert (= (as sep.nil U) (f a)))
 
index c807757d126cfd870c6a3a0387bed5798760da44..e57e50ea236773833f70bbff6e6391e571ed63c6 100644 (file)
@@ -3,6 +3,7 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-fun x () Int)
+(declare-heap (Int Int))
 
 (assert (sep (= x 0) (not (= x 5))))
 
index 28ed5c47b71730eb8b35b77a476bea2081a88a13..f980ac13f4884a308ebc7e7c26cb0e6490a96852 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 
index ab1cea0c86b05c81d81fb4ece89a6c5d69397d34..111048c7017a68f3ff9094f43c4e73e9efeb1fc9 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 
 (declare-const x Int)
index a93fc4db88b1c268364ff1988fdd75c320c5fb2d..8e577d5b72fc3f30f0c9e4039e046958deca2525 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 9522e2420a50527d2f8e69e967e58c68489c56bf..b843c1eda03cf1cc4f583fbd785cf17b8097308b 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index f620e9360361ad88b5a5eec3af3ce4a2a3df0ccf..fc7bd0a51e0a13d36aee7e21721a598526fd6249 100644 (file)
@@ -1,7 +1,8 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
-
 (declare-sort U 0)
+(declare-heap (U U))
+
 (declare-fun x () U)
 (declare-fun y () U)
 (declare-fun a () U)
index 1d85fb133080250299cf48b5fb8871ae728f608a..785017d5c0a0eac40bd076f3eb7e8c023c025834 100644 (file)
@@ -3,6 +3,7 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-option :produce-models true)
 (set-info :status sat)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 
 ; works
index 7798f6bed80745a045fd6edf2892c32a3c6b2e6e..aac8382a73d0f1280b5f3ab4ce4c2e5718996880 100644 (file)
@@ -1,5 +1,6 @@
 ; COMMAND-LINE: --no-check-models --sep-pre-skolem-emp
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
+(declare-heap (Int Int))
 (assert (not (_ emp Int Int)))
 (check-sat)
index 7daf012e2c3a51ae4aff08d63a4a32caef5c9411..46d96e84cc20a1737ef95bdb98de5805a5a68843 100644 (file)
@@ -5,6 +5,7 @@
 (declare-const loc0 Loc)
 
 (declare-datatypes ((Node 0)) (((node (data Int) (left Loc) (right Loc)))))
+(declare-heap (Loc Node))
 
 (declare-fun data0 () Node)
 
index 4828646cb45863f614b052e051af16445c77cf7a..95156a20cb4449b36d59316d7191dd5cda363e9c 100644 (file)
@@ -1,5 +1,6 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
+(declare-heap (Int Int))
 (assert (wand (_ emp Int Int) (_ emp Int Int)))
 (check-sat)
index ebe52fa4643817dcff60ed38cb32686f53d7735d..6aaca31c5e8aa6b402bbb09acaed5174b5288bfa 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index f68434f33026e1fc7eac8df429eabf088d2c77a3..4df23fd80de06f29222ae8432fab289fb9cd8ba7 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const a Int)
index b3e2088b1404680f18db39ac26608ea3868d4b42..0ee63cc8a5d0b582f53d1eb17ad20725f77e0a4e 100644 (file)
@@ -3,6 +3,7 @@
 (set-logic QF_ALL_SUPPORTED)
 
 (declare-sort Loc 0)
+(declare-heap (Loc Loc))
 
 (declare-const w Loc)
 (declare-const u1 Loc)
index 118e63f074e6a9c95e42176b65ff3f0788737769..a0921aa31b7a0e246fc59b8231665709e5ddfa8a 100644 (file)
@@ -4,6 +4,7 @@
 (set-info :status unsat)
 (declare-sort U 0)
 (declare-fun u () U)
+(declare-heap (U U))
 
 (assert (sep (not (_ emp U U)) (not (_ emp U U))))
 
index 1f3338ed782fbdb5113434f50128c70225fe0248..fac9d6b9d08828609257133d9bc59f1179756327 100644 (file)
@@ -3,6 +3,7 @@
 (set-logic ALL_SUPPORTED)
 (declare-sort Loc 0)
 (declare-const l Loc)
+(declare-heap (Loc Loc))
 
 (assert (not (_ emp Loc Loc)))
 (assert (forall ((x Loc) (y Loc)) (not (pto x y))))
index 35640586933fb8f0cd07466e03d4bfb936260d00..49420145e2ca62ec3ff5150a409ad79ff91bcae0 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic ALL_SUPPORTED)
 (declare-sort U 0)
+(declare-heap (U Int))
 (declare-fun u1 () U)
 (declare-fun u2 () U)
 (assert (not (= u1 u2)))
index b857aec2af35657b52641bb67732f44232c46055..41078391a17aef1da584e3fb826defaafcd9dd2b 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const a Int)
index 9b0afda7a7063032725bb9ef990022f52727b0be..e3d3ea7a1b151a941898a3da1fe186ade27b2891 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x1 Int)
 (declare-const x2 Int)
index 662682ec3d8c86764837f81530bf18ccb5b0cb64..bb4e4030848eee4b3508555f4ed6ee599900e26a 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: unsat
 (set-logic ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const u Int)
 
index 6f190d9643df6953b018691c88254b6907abba65..a67394d9015c907ce9cf2b1d187bd9646020b1da 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 8dce5acc72b9813c44e293996e6d34490a817c68..f29d081fc3b9b9487d3b12cc5e7a3aa0b2de8a59 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 3d6188894eb21352bd8aca9f8b31bbec9b3d8420..412caee9b2999a27c26f6ee77908c510c9b774e4 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_SEP_LIA)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x1 Int)
 (declare-const x2 Int)
index fe3af1b35035e12089e265a00551b607864c3682..8aed931190d295a78006e52be9c1bbf215c69284 100644 (file)
@@ -5,6 +5,7 @@
 (declare-sort Loc 0)
 (declare-const l Loc)
 (declare-const x Loc)
+(declare-heap (Loc Loc))
 
 (assert (wand (pto x x) false))
 (assert (forall ((x Loc) (y Loc)) (not (pto x y))))
index ab12c64615ec21efe903263f8f2270d5532a1058..81b107ab53c9d85f4911fc786c5c129a1adbaf81 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 425e5ce3c2b87e486a4b822d4ac55bcdcf7c2e86..6594a1075cb386c4671241e7fba75f6ef16bbd77 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 7ada6ff068f418a5291d09590ce67ea449d477ac..0243282a30c6766bae5801c918c4092c75ad5164 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 7b6fc69e9ae1877e997c914377b7e6e8bfa2036a..8b23a6da80a5e9cdee7c6fdcd646ff93973e3374 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 53f890b0df8a3ff74f2efd8fca08551a3b1e9214..ba83f2575fe3358e8124389d4b2d3e5e0a0bd9c3 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 3e595b5e9f6361cb693182b44a177930871c5d34..43fb7b00d35834554a0417a4e79fcd5975019b19 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index d4fb0fd5279562144380fc1ecbb82f001aa12a4d..635f0895a5bece93e806d26c0c4f2289f4087156 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index cedbb53eb8cdd95c2f9a4d255c22ec2980a0ae3f..88950d655fed5c3436107fd0d4cde00ae1fb08dc 100644 (file)
@@ -3,6 +3,7 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
 (declare-sort U 0)
+(declare-heap (U U))
 (declare-fun x () U)
 (declare-fun y () U)
 (declare-fun a () U)
index 70927ad82468b20bc4d1e4db3fa114da7f4d460c..929a8e66f4b5de841e73b12a18eda34250deeb18 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 91b07093c9c1d2e243942347c772b60158175828..1b7932dc4761a66cc1c04099a22422730abc7b79 100644 (file)
@@ -1,5 +1,6 @@
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 1a9e76a8a0de6367fbff711de5381b68b49caa7a..60ab5d038c7f5d797f1c5be7cc00570c7baae172 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: unsat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status unsat)
+(declare-heap (Int Int))
 
 (declare-const x Int)
 (declare-const y Int)
index 99116c9d14de9919abc92f90eb8e02a851de5ef4..556be6c18d7109f53a896385b8d616bb1af87966 100644 (file)
@@ -1,6 +1,7 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (declare-fun y () Int)
 (declare-fun u () Int)
index 65500f775703d44e316120da53b667fb37148335..9f95c06b7e1f47a5b317c9442761301f9f62e70c 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (assert (wand (pto x x) false))
 (check-sat)
index 702f03a02cbdc3c62fde7404099476a60c4ff12a..4ecc8ad1ed97387e2e40aac563702d4022ba03cd 100644 (file)
@@ -1,6 +1,7 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (assert (wand (_ emp Int Int) (pto x 3)))
 (check-sat)
index 352be577721aeed482a732722a531805cda61de9..5b7c92a4ab27dec62a9a664f7febd4ee1d238177 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (assert (wand (pto x 1) (_ emp Int Int)))
 (check-sat)
index 120683f7472457738300ab227fdebfa3082f3761..ec63a762edb3a59f02d0a658c8483c68354f0aae 100644 (file)
@@ -1,6 +1,7 @@
 ; COMMAND-LINE: --no-check-models
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (assert (wand (pto x 1) (pto x 1)))
 (check-sat)
index c684d16ad52928ea7b319c89256f148f0f58db97..315071c05953cab284083c30345ca30d873e0f6e 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: sat
 (set-logic QF_ALL_SUPPORTED)
 (set-info :status sat)
+(declare-heap (Int Int))
 (declare-fun x () Int)
 (assert (wand (pto x 1) (pto x 3)))
 (check-sat)
index 8c038e3d7f580536cb847c00ff91746f500ceb9c..da1d8bd51414cf0db5f0663a9bf2424af94cd75e 100644 (file)
@@ -2,6 +2,7 @@
 ; EXPECT: unsat
 (set-logic QF_ALL_SUPPORTED)
 (declare-fun x () Int)
+(declare-heap (Int Int))
 (assert (wand (pto x 1) (pto x 3)))
 (assert (_ emp Int Int))
 (check-sat)
index 1324e3890af04070052bf7f74ec2768e71be354c..f292acc880e1e7c47a96e1c307e6097f8e07ff2f 100644 (file)
@@ -118,6 +118,7 @@ class SolverBlack : public CxxTest::TestSuite
   void testGetValue3();
   void testGetQuantifierElimination();
   void testGetQuantifierEliminationDisjunct();
+  void testDeclareSeparationHeap();
   void testGetSeparationHeapTerm1();
   void testGetSeparationHeapTerm2();
   void testGetSeparationHeapTerm3();
@@ -1697,6 +1698,16 @@ void SolverBlack::testGetQuantifierEliminationDisjunct()
   TS_ASSERT_THROWS_NOTHING(d_solver->getQuantifierEliminationDisjunct(forall));
 }
 
+void SolverBlack::testDeclareSeparationHeap()
+{
+  d_solver->setLogic("ALL_SUPPORTED");
+  Sort integer = d_solver->getIntegerSort();
+  TS_ASSERT_THROWS_NOTHING(d_solver->declareSeparationHeap(integer, integer));
+  // cannot declare separation logic heap more than once
+  TS_ASSERT_THROWS(d_solver->declareSeparationHeap(integer, integer),
+                   CVC4ApiException&);
+}
+
 namespace {
 /**
  * Helper function for testGetSeparation{Heap,Nil}TermX. Asserts and checks
@@ -1705,6 +1716,8 @@ namespace {
 void checkSimpleSeparationConstraints(Solver* solver)
 {
   Sort integer = solver->getIntegerSort();
+  // declare the separation heap
+  solver->declareSeparationHeap(integer, integer);
   Term x = solver->mkConst(integer, "x");
   Term p = solver->mkConst(integer, "p");
   Term heap = solver->mkTerm(Kind::SEP_PTO, p, x);