LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/smt - illegal_checker.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 133 138 96.4 %
Date: 2026-03-28 10:41:09 Functions: 3 3 100.0 %
Branches: 103 117 88.0 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * This file is part of the cvc5 project.
       3                 :            :  *
       4                 :            :  * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
       5                 :            :  * in the top-level source directory and their institutional affiliations.
       6                 :            :  * All rights reserved.  See the file COPYING in the top-level source
       7                 :            :  * directory for licensing information.
       8                 :            :  * ****************************************************************************
       9                 :            :  *
      10                 :            :  * Utility for checking for illegal inputs
      11                 :            :  */
      12                 :            : 
      13                 :            : #include "smt/illegal_checker.h"
      14                 :            : 
      15                 :            : #include <unordered_set>
      16                 :            : 
      17                 :            : #include "base/modal_exception.h"
      18                 :            : #include "expr/dtype.h"
      19                 :            : #include "expr/node_algorithm.h"
      20                 :            : #include "options/arith_options.h"
      21                 :            : #include "options/arrays_options.h"
      22                 :            : #include "options/bags_options.h"
      23                 :            : #include "options/base_options.h"
      24                 :            : #include "options/datatypes_options.h"
      25                 :            : #include "options/ff_options.h"
      26                 :            : #include "options/fp_options.h"
      27                 :            : #include "options/main_options.h"
      28                 :            : #include "options/sep_options.h"
      29                 :            : #include "options/sets_options.h"
      30                 :            : #include "options/smt_options.h"
      31                 :            : #include "options/uf_options.h"
      32                 :            : #include "smt/env.h"
      33                 :            : #include "smt/logic_exception.h"
      34                 :            : 
      35                 :            : namespace cvc5::internal {
      36                 :            : namespace smt {
      37                 :            : 
      38                 :      52216 : IllegalChecker::IllegalChecker(Env& e)
      39                 :      52216 :     : EnvObj(e), d_visited(userContext()), d_assertionIndex(userContext(), 0)
      40                 :            : {
      41                 :            :   // Determine any illegal kinds that are dependent on options that need to be
      42                 :            :   // guarded here. Note that nearly all illegal kinds should be properly guarded
      43                 :            :   // by either the theory engine, theory solvers, or by theory rewriters. We
      44                 :            :   // only require special handling for rare cases, including array constants,
      45                 :            :   // where array constants *must* be rewritten by the rewriter for the purposes
      46                 :            :   // of model verification, but we do not want array constants to appear in
      47                 :            :   // assertions unless --arrays-exp is enabled.
      48                 :            : 
      49                 :            :   // Note that we don't guard against HO_APPLY, since it can naturally be
      50                 :            :   // handled in proofs.
      51                 :            : 
      52                 :            :   // Array constants are not supported unless arraysExp is enabled
      53                 :      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_ARRAYS)
      54 [ +  + ][ +  + ]:      52216 :       && !options().arrays.arraysExp)
                 [ +  + ]
      55                 :            :   {
      56                 :      33465 :     d_illegalKinds.insert(Kind::STORE_ALL);
      57                 :            :   }
      58                 :      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_ARITH)
      59 [ +  + ][ +  + ]:      52216 :       && !options().arith.arithExp)
                 [ +  + ]
      60                 :            :   {
      61                 :          5 :     d_illegalKinds.insert(Kind::POW);
      62                 :          5 :     d_illegalKinds.insert(Kind::PI);
      63                 :          5 :     d_illegalKinds.insert(Kind::EXPONENTIAL);
      64                 :          5 :     d_illegalKinds.insert(Kind::SINE);
      65                 :          5 :     d_illegalKinds.insert(Kind::COSINE);
      66                 :          5 :     d_illegalKinds.insert(Kind::TANGENT);
      67                 :          5 :     d_illegalKinds.insert(Kind::COSECANT);
      68                 :          5 :     d_illegalKinds.insert(Kind::SECANT);
      69                 :          5 :     d_illegalKinds.insert(Kind::COTANGENT);
      70                 :          5 :     d_illegalKinds.insert(Kind::ARCSINE);
      71                 :          5 :     d_illegalKinds.insert(Kind::ARCCOSINE);
      72                 :          5 :     d_illegalKinds.insert(Kind::ARCTANGENT);
      73                 :          5 :     d_illegalKinds.insert(Kind::ARCCOSECANT);
      74                 :          5 :     d_illegalKinds.insert(Kind::ARCSECANT);
      75                 :          5 :     d_illegalKinds.insert(Kind::ARCCOTANGENT);
      76                 :          5 :     d_illegalKinds.insert(Kind::SQRT);
      77                 :          5 :     d_illegalKinds.insert(Kind::IAND);
      78                 :          5 :     d_illegalKinds.insert(Kind::PIAND);
      79                 :          5 :     d_illegalKinds.insert(Kind::POW2);
      80                 :          5 :     d_illegalKinds.insert(Kind::INTS_LOG2);
      81                 :            :   }
      82                 :      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_DATATYPES)
      83 [ +  + ][ +  + ]:      52216 :       && !options().datatypes.datatypesExp)
                 [ +  + ]
      84                 :            :   {
      85                 :          5 :     d_illegalKinds.insert(Kind::MATCH);
      86                 :            :     // catches all occurrences of nullables
      87                 :          5 :     d_illegalKinds.insert(Kind::NULLABLE_TYPE);
      88                 :            :   }
      89 [ +  + ][ -  + ]:      52216 :   if (logicInfo().hasCardinalityConstraints() && !options().uf.ufCardExp)
                 [ -  + ]
      90                 :            :   {
      91                 :          0 :     d_illegalKinds.insert(Kind::CARDINALITY_CONSTRAINT);
      92                 :            :   }
      93         [ +  + ]:      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_SETS))
      94                 :            :   {
      95         [ +  + ]:      32126 :     if (!options().sets.setsCardExp)
      96                 :            :     {
      97                 :          5 :       d_illegalKinds.insert(Kind::SET_CARD);
      98                 :            :     }
      99         [ +  + ]:      32126 :     if (!options().sets.relsExp)
     100                 :            :     {
     101                 :          5 :       d_illegalKinds.insert(Kind::RELATION_TABLE_JOIN);
     102                 :          5 :       d_illegalKinds.insert(Kind::RELATION_TRANSPOSE);
     103                 :          5 :       d_illegalKinds.insert(Kind::RELATION_PRODUCT);
     104                 :          5 :       d_illegalKinds.insert(Kind::RELATION_JOIN);
     105                 :          5 :       d_illegalKinds.insert(Kind::RELATION_TCLOSURE);
     106                 :          5 :       d_illegalKinds.insert(Kind::RELATION_IDEN);
     107                 :          5 :       d_illegalKinds.insert(Kind::RELATION_JOIN_IMAGE);
     108                 :          5 :       d_illegalKinds.insert(Kind::RELATION_GROUP);
     109                 :          5 :       d_illegalKinds.insert(Kind::RELATION_AGGREGATE);
     110                 :          5 :       d_illegalKinds.insert(Kind::RELATION_PROJECT);
     111                 :            :     }
     112                 :            :   }
     113                 :            :   // unsupported theories disables all kinds belonging to the theory
     114                 :      52216 :   std::unordered_set<theory::TheoryId> unsupportedTheories;
     115 [ +  + ][ +  + ]:      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_FP) && !options().fp.fp)
                 [ +  + ]
     116                 :            :   {
     117                 :          5 :     unsupportedTheories.insert(theory::TheoryId::THEORY_FP);
     118                 :            :     // Require a special check for rounding mode
     119                 :          5 :     d_illegalTypes.insert(nodeManager()->roundingModeType());
     120                 :            :   }
     121 [ +  + ][ +  + ]:      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_FF) && !options().ff.ff)
                 [ +  + ]
     122                 :            :   {
     123                 :          5 :     unsupportedTheories.insert(theory::TheoryId::THEORY_FF);
     124                 :            :   }
     125 [ +  + ][ +  + ]:      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_BAGS) && !options().bags.bags)
                 [ +  + ]
     126                 :            :   {
     127                 :          5 :     unsupportedTheories.insert(theory::TheoryId::THEORY_BAGS);
     128                 :            :   }
     129 [ +  + ][ +  + ]:      52216 :   if (logicInfo().isTheoryEnabled(theory::THEORY_SEP) && !options().sep.sep)
                 [ +  + ]
     130                 :            :   {
     131                 :          5 :     unsupportedTheories.insert(theory::TheoryId::THEORY_SEP);
     132                 :            :   }
     133         [ +  + ]:      52216 :   if (!unsupportedTheories.empty())
     134                 :            :   {
     135         [ +  + ]:       1915 :     for (int32_t i = 0; i < static_cast<int32_t>(Kind::LAST_KIND); ++i)
     136                 :            :     {
     137                 :       1910 :       Kind k = static_cast<Kind>(i);
     138                 :            :       // these two kinds are special cased in kindToTheoryId, skip
     139 [ +  - ][ +  + ]:       1910 :       if (k == Kind::UNDEFINED_KIND || k == Kind::NULL_EXPR)
     140                 :            :       {
     141                 :          5 :         continue;
     142                 :            :       }
     143                 :       1905 :       theory::TheoryId tid = theory::kindToTheoryId(k);
     144         [ +  + ]:       1905 :       if (unsupportedTheories.find(tid) != unsupportedTheories.end())
     145                 :            :       {
     146                 :        490 :         d_illegalKinds.insert(k);
     147                 :            :       }
     148                 :            :     }
     149                 :            :   }
     150                 :      52216 : }
     151                 :            : 
     152                 :      50529 : void IllegalChecker::checkAssertions(Assertions& as)
     153                 :            : {
     154 [ +  + ][ +  - ]:      50529 :   if (d_illegalKinds.empty() && d_illegalTypes.empty())
                 [ +  + ]
     155                 :            :   {
     156                 :            :     // nothing to check
     157                 :      21224 :     return;
     158                 :            :   }
     159                 :            :   // check illegal kinds here
     160                 :      29305 :   const context::CDList<Node>& assertions = as.getAssertionList();
     161                 :      29305 :   size_t asize = assertions.size();
     162         [ +  + ]:     134063 :   for (size_t i = d_assertionIndex.get(); i < asize; ++i)
     163                 :            :   {
     164                 :     104762 :     Node n = assertions[i];
     165         [ +  - ]:     104762 :     Trace("illegal-check") << "Check assertion " << n << std::endl;
     166                 :     104763 :     Kind k = checkInternal(n);
     167         [ +  + ]:     104761 :     if (k != Kind::UNDEFINED_KIND)
     168                 :            :     {
     169                 :          3 :       std::stringstream ss;
     170                 :          3 :       ss << "Cannot handle assertion with term of kind " << k
     171                 :          3 :          << " in this configuration.";
     172                 :            :       // suggested options only in non-safe builds
     173                 :            : #if !defined(CVC5_SAFE_MODE) && !defined(CVC5_STABLE_MODE)
     174         [ -  + ]:          3 :       if (k == Kind::STORE_ALL)
     175                 :            :       {
     176                 :          0 :         ss << " Try --arrays-exp.";
     177                 :            :       }
     178                 :            :       else
     179                 :            :       {
     180                 :          3 :         theory::TheoryId tid = theory::kindToTheoryId(k);
     181                 :            :         // if the kind was disabled based a theory, report it.
     182 [ +  + ][ -  - ]:          3 :         switch (tid)
                    [ - ]
     183                 :            :         {
     184                 :          1 :           case theory::THEORY_FF: ss << " Try --ff."; break;
     185                 :          2 :           case theory::THEORY_FP: ss << " Try --fp."; break;
     186                 :          0 :           case theory::THEORY_BAGS: ss << " Try --bags."; break;
     187                 :          0 :           case theory::THEORY_SEP: ss << " Try --sep."; break;
     188                 :          0 :           default: break;
     189                 :            :         }
     190                 :            :       }
     191                 :            : #endif
     192                 :          3 :       throw SafeLogicException(ss.str());
     193                 :          3 :     }
     194                 :     104762 :   }
     195                 :      29301 :   d_assertionIndex = asize;
     196                 :            : }
     197                 :            : 
     198                 :     104762 : Kind IllegalChecker::checkInternal(TNode n)
     199                 :            : {
     200 [ -  + ][ -  + ]:     104762 :   Assert(!d_illegalKinds.empty());
                 [ -  - ]
     201                 :     104762 :   std::vector<TNode> visit;
     202                 :     104762 :   std::unordered_set<TypeNode> allTypes;
     203                 :     104762 :   TNode cur;
     204                 :     104762 :   visit.push_back(n);
     205                 :            :   Kind k;
     206                 :            :   do
     207                 :            :   {
     208                 :    2458862 :     cur = visit.back();
     209                 :    2458862 :     visit.pop_back();
     210         [ +  + ]:    2458862 :     if (d_visited.find(cur) == d_visited.end())
     211                 :            :     {
     212                 :    1135846 :       k = cur.getKind();
     213         [ +  + ]:    1135846 :       if (d_illegalKinds.find(k) != d_illegalKinds.end())
     214                 :            :       {
     215                 :          3 :         return k;
     216                 :            :       }
     217         [ +  + ]:    1135843 :       else if (cur.isVar())
     218                 :            :       {
     219                 :            :         // check its type
     220                 :     215964 :         TypeNode tn = cur.getType();
     221                 :     215964 :         expr::getComponentTypes(tn, allTypes);
     222                 :     215964 :       }
     223                 :    1135843 :       d_visited.insert(cur);
     224         [ +  + ]:    1135843 :       if (cur.hasOperator())
     225                 :            :       {
     226                 :     782673 :         visit.push_back(cur.getOperator());
     227                 :            :       }
     228                 :    1135843 :       visit.insert(visit.end(), cur.begin(), cur.end());
     229                 :            :     }
     230         [ +  + ]:    2458859 :   } while (!visit.empty());
     231                 :            :   // now, go back and check if the types are legal
     232                 :     104759 :   std::vector<TypeNode> tlist(allTypes.begin(), allTypes.end());
     233         [ +  + ]:     246248 :   for (size_t i = 0; i < tlist.size(); i++)
     234                 :            :   {
     235                 :     141490 :     TypeNode tn = tlist[i];
     236                 :            :     // Must additionally get the subfield types from datatypes.
     237         [ +  + ]:     141490 :     if (tn.isDatatype())
     238                 :            :     {
     239                 :      11944 :       const DType& dt = tn.getDType();
     240                 :      11944 :       std::unordered_set<TypeNode> sftypes = dt.getSubfieldTypes();
     241                 :      11944 :       std::unordered_set<TypeNode> sfctypes;
     242                 :            :       // get the component types of each of the subfield types
     243         [ +  + ]:      29553 :       for (const TypeNode& sft : sftypes)
     244                 :            :       {
     245                 :            :         // as an optimization, if we've already considered this type, don't
     246                 :            :         // have to find its component types
     247         [ +  + ]:      17609 :         if (allTypes.find(sft) == allTypes.end())
     248                 :            :         {
     249                 :       4137 :           expr::getComponentTypes(sft, sfctypes);
     250                 :            :         }
     251                 :            :       }
     252         [ +  + ]:      16517 :       for (const TypeNode& sft : sfctypes)
     253                 :            :       {
     254         [ +  + ]:       4573 :         if (allTypes.find(sft) == allTypes.end())
     255                 :            :         {
     256                 :       4407 :           tlist.emplace_back(sft);
     257                 :       4407 :           allTypes.insert(sft);
     258                 :            :         }
     259                 :            :       }
     260                 :      11944 :     }
     261                 :     141490 :     k = tn.getKind();
     262                 :     141490 :     if (d_illegalKinds.find(k) != d_illegalKinds.end()
     263 [ +  - ][ +  + ]:     141490 :         || d_illegalTypes.find(tn) != d_illegalTypes.end())
                 [ +  + ]
     264                 :            :     {
     265                 :          1 :       std::stringstream ss;
     266                 :          1 :       ss << "Cannot handle term with type " << tn << " in this configuration";
     267                 :          1 :       throw SafeLogicException(ss.str());
     268                 :          1 :     }
     269                 :     141490 :   }
     270                 :     104758 :   return Kind::UNDEFINED_KIND;
     271                 :     104765 : }
     272                 :            : 
     273                 :            : }  // namespace smt
     274                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14