diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-04-08 03:23:16 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-04-08 03:23:16 +0800 |
| commit | 4b31d8f59a6d3237f176a122c82f46fdaef4551d (patch) | |
| tree | 917c9d42bb2cdbe96f5fc5416ae55789986029d7 | |
| parent | 5ab3efd522cf0221481684b5bbc9c2ac6bfc9919 (diff) | |
| download | ratp-master.tar.gz ratp-master.tar.xz | |
| -rw-r--r-- | .clang-tidy | 8 | ||||
| -rw-r--r-- | CMakeLists.txt | 13 | ||||
| -rw-r--r-- | include/atp/core/term_bank.h | 11 | ||||
| -rw-r--r-- | include/atp/frontend/tptp_parser.h | 2 | ||||
| -rw-r--r-- | include/atp/search/prover.h | 9 | ||||
| -rw-r--r-- | src/core/term_bank.cc | 2 | ||||
| -rw-r--r-- | src/frontend/tptp_parser.cc | 57 | ||||
| -rw-r--r-- | src/infer/resolution.cc | 2 | ||||
| -rw-r--r-- | src/infer/substitution.cc | 9 | ||||
| -rw-r--r-- | src/main.cc | 16 | ||||
| -rw-r--r-- | src/proof/proof_trace.cc | 50 | ||||
| -rw-r--r-- | src/search/prover.cc | 177 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 1 |
13 files changed, 198 insertions, 159 deletions
diff --git a/.clang-tidy b/.clang-tidy index 227c129..412e8a8 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -10,11 +10,13 @@ Checks: > -bugprone-easily-swappable-parameters, clang-analyzer-*, cppcoreguidelines-*, + -cppcoreguidelines-avoid-const-or-ref-data-members, -cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-owning-memory, misc-*, + -misc-no-recursion, -misc-non-private-member-variables-in-classes, modernize-*, -modernize-use-trailing-return-type, @@ -46,6 +48,12 @@ CheckOptions: value: CamelCase - key: readability-identifier-naming.ConstantPrefix value: k + - key: readability-identifier-naming.LocalConstantCase + value: lower_case + - key: readability-identifier-naming.LocalConstantPrefix + value: '' + - key: readability-identifier-naming.LocalConstantSuffix + value: '' - key: readability-identifier-naming.EnumConstantCase value: CamelCase - key: readability-identifier-naming.EnumConstantPrefix diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b6473e..2257766 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Export compile_commands.json for clang-tidy and IDE support set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -# ─── Compiler Warnings ────────────────────────────────────────────────────── -add_compile_options( +# ─── Compiler Warnings ────────────────────────── +set(ATP_PROJECT_WARNING_FLAGS -Wall -Wextra -Wpedantic -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wunused @@ -34,7 +34,6 @@ option(ATP_ENABLE_CLANG_TIDY "Enable clang-tidy static analysis" OFF) if(ATP_ENABLE_CLANG_TIDY) find_program(CLANG_TIDY_EXE NAMES clang-tidy) if(CLANG_TIDY_EXE) - set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") else() message(WARNING "clang-tidy requested but not found") @@ -91,10 +90,18 @@ add_library(atp_core STATIC ${ATP_SOURCES}) target_include_directories(atp_core PUBLIC ${PROJECT_SOURCE_DIR}/include ) +target_compile_options(atp_core PRIVATE ${ATP_PROJECT_WARNING_FLAGS}) +if(ATP_ENABLE_CLANG_TIDY AND CLANG_TIDY_EXE) + set_property(TARGET atp_core PROPERTY CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") +endif() # ─── Main Executable ──────────────────────────────────────────────────────── add_executable(atp src/main.cc) target_link_libraries(atp PRIVATE atp_core) +target_compile_options(atp PRIVATE ${ATP_PROJECT_WARNING_FLAGS}) +if(ATP_ENABLE_CLANG_TIDY AND CLANG_TIDY_EXE) + set_property(TARGET atp PROPERTY CXX_CLANG_TIDY "${CLANG_TIDY_EXE}") +endif() # ─── Tests ─────────────────────────────────────────────────────────────────── option(ATP_BUILD_TESTS "Build unit tests" ON) diff --git a/include/atp/core/term_bank.h b/include/atp/core/term_bank.h index 3339ceb..ca12759 100644 --- a/include/atp/core/term_bank.h +++ b/include/atp/core/term_bank.h @@ -39,7 +39,7 @@ class TermBank { public: /// TermBank needs the SymbolTable to distinguish variables from constants /// (both have 0 args, but SymbolKind differs). - explicit TermBank(const SymbolTable& symbols) : symbols_(symbols) {} + explicit TermBank(SymbolTable& symbols) : symbols_(&symbols) {} /// Create or retrieve a term. Returns the canonical TermId. TermId makeTerm(SymbolId symbol, std::span<const TermId> args); @@ -57,7 +57,8 @@ class TermBank { [[nodiscard]] size_t size() const; /// Access the underlying SymbolTable. - [[nodiscard]] const SymbolTable& symbols() const { return symbols_; } + [[nodiscard]] const SymbolTable& symbols() const { return *symbols_; } + [[nodiscard]] SymbolTable& mutableSymbols() { return *symbols_; } private: struct TermKey { @@ -70,14 +71,14 @@ class TermBank { struct TermKeyHash { size_t operator()(const TermKey& key) const { size_t seed = std::hash<uint32_t>{}(key.symbol_); - for (const TermId kArg : key.args_) { - seed ^= std::hash<TermId>{}(kArg) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + for (const TermId arg : key.args_) { + seed ^= std::hash<TermId>{}(arg) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } return seed; } }; - const SymbolTable& symbols_; + SymbolTable* symbols_; std::vector<Term> terms_; std::unordered_map<TermKey, TermId, TermKeyHash> term_to_id_; }; diff --git a/include/atp/frontend/tptp_parser.h b/include/atp/frontend/tptp_parser.h index 89eab6b..68a5564 100644 --- a/include/atp/frontend/tptp_parser.h +++ b/include/atp/frontend/tptp_parser.h @@ -59,7 +59,7 @@ FormulaRole parseRole(std::string_view role_str); /// A parsed TPTP formula with its name and role. struct AnnotatedFormula { std::string name_; ///< Formula name (e.g., "axiom1") - FormulaRole role_; ///< Semantic role + FormulaRole role_ = FormulaRole::kPlain; ///< Semantic role std::unique_ptr<Formula> formula_; ///< The FOL formula (for fof(...)) std::vector<Clause> clauses_; ///< Direct clauses (for cnf(...)) bool is_cnf_ = false; ///< true if input was cnf(), false if fof() diff --git a/include/atp/search/prover.h b/include/atp/search/prover.h index c1246ae..65ec7f0 100644 --- a/include/atp/search/prover.h +++ b/include/atp/search/prover.h @@ -72,6 +72,15 @@ class Prover { [[nodiscard]] const ClauseStore& clauseStore() const { return store_; } private: + [[nodiscard]] bool hitResourceLimit(size_t iterations) const; + [[nodiscard]] Clause popGivenClause(); + [[nodiscard]] bool isForwardSubsumedByProcessed(const Clause& clause) const; + [[nodiscard]] bool shouldSkipGiven(const Clause& given) const; + void applyBackwardSubsumption(const Clause& given); + [[nodiscard]] std::vector<Clause> generateNewClauses(const Clause& given) const; + [[nodiscard]] uint16_t computeDepth(const Clause& clause) const; + [[nodiscard]] std::optional<ClauseId> processNewClauses(std::vector<Clause> new_clauses); + TermBank& bank_; ClauseStore& store_; ProverConfig config_; diff --git a/src/core/term_bank.cc b/src/core/term_bank.cc index 2e117b3..0dc166f 100644 --- a/src/core/term_bank.cc +++ b/src/core/term_bank.cc @@ -53,7 +53,7 @@ const Term& TermBank::getTerm(TermId id) const { bool TermBank::isVariable(TermId id) const { assert(id < terms_.size() && "TermId out of bounds!"); - return symbols_.isVariable(terms_[id].symbol_id_); + return symbols_->isVariable(terms_[id].symbol_id_); } size_t TermBank::size() const { diff --git a/src/frontend/tptp_parser.cc b/src/frontend/tptp_parser.cc index ddf8aad..10190b8 100644 --- a/src/frontend/tptp_parser.cc +++ b/src/frontend/tptp_parser.cc @@ -42,31 +42,31 @@ namespace atp { FormulaRole parseRole(std::string_view role_str) { if (role_str == "axiom") { return FormulaRole::kAxiom; -} + } if (role_str == "hypothesis") { return FormulaRole::kHypothesis; -} + } if (role_str == "definition") { return FormulaRole::kDefinition; -} + } if (role_str == "assumption") { return FormulaRole::kAssumption; -} + } if (role_str == "lemma") { return FormulaRole::kLemma; -} + } if (role_str == "theorem") { return FormulaRole::kTheorem; -} + } if (role_str == "conjecture") { return FormulaRole::kConjecture; -} + } if (role_str == "negated_conjecture") { return FormulaRole::kNegatedConjecture; -} + } if (role_str == "plain") { return FormulaRole::kPlain; -} + } return FormulaRole::kPlain; } @@ -215,7 +215,7 @@ class TptpParser { SymbolTable& symbols_; Token current_token_{}; std::vector<Token> tokens_; - std::unordered_map<std::string_view, SymbolId> variable_cache_{}; + std::unordered_map<std::string_view, SymbolId> variable_cache_; void advance() { current_token_ = lexer_.nextToken(); } @@ -252,27 +252,28 @@ class TptpParser { TermId const var_id = bank_.makeVar(sym); variable_cache_[name] = var_id; return var_id; - } // Check if this is a function/predicate (has args) or a constant (no parens) - if (current_token_.type_ == TokenType::kLParen) { - advance(); // consume '(' - std::vector<TermId> args; - if (current_token_.type_ != TokenType::kRParen) { + } + + // Check if this is a function/predicate (has args) or a constant (no parens) + if (current_token_.type_ == TokenType::kLParen) { + advance(); // consume '(' + std::vector<TermId> args; + if (current_token_.type_ != TokenType::kRParen) { + args.push_back(parseTerm()); + while (current_token_.type_ == TokenType::kComma) { + advance(); args.push_back(parseTerm()); - while (current_token_.type_ == TokenType::kComma) { - advance(); - args.push_back(parseTerm()); - } } - expect(TokenType::kRParen); - SymbolId sym = symbols_.intern(name, SymbolKind::kFunction, - static_cast<uint16_t>(args.size())); - return bank_.makeTerm(sym, args); - } else { - // Constant: no parentheses (e.g., a, b, h0, s0) - SymbolId sym = symbols_.intern(name, SymbolKind::kConstant, 0); - return bank_.makeTerm(sym, {}); } - + expect(TokenType::kRParen); + const SymbolId sym = symbols_.intern(name, SymbolKind::kFunction, + static_cast<uint16_t>(args.size())); + return bank_.makeTerm(sym, args); + } + + // Constant: no parentheses (e.g., a, b, h0, s0) + const SymbolId sym = symbols_.intern(name, SymbolKind::kConstant, 0); + return bank_.makeTerm(sym, {}); } Literal parseLiteral() { diff --git a/src/infer/resolution.cc b/src/infer/resolution.cc index 82e59b7..5fb0d4a 100644 --- a/src/infer/resolution.cc +++ b/src/infer/resolution.cc @@ -98,7 +98,7 @@ std::optional<Clause> resolve(TermBank& bank, const Clause& c1, size_t lit_idx1, // Rename c2's variables to avoid clashes with c1 // Use a static counter — safe for single-threaded prover static uint32_t var_counter = 0; - auto& symbols = const_cast<SymbolTable&>(bank.symbols()); + auto& symbols = bank.mutableSymbols(); Clause c2r = renameVariables(c2, bank, symbols, var_counter); // Unify the complementary atoms diff --git a/src/infer/substitution.cc b/src/infer/substitution.cc index 8710fb0..584008b 100644 --- a/src/infer/substitution.cc +++ b/src/infer/substitution.cc @@ -22,6 +22,7 @@ #include "atp/core/term_bank.h" #include "atp/core/types.h" +#include <algorithm> #include <vector> namespace atp { @@ -107,12 +108,8 @@ bool Substitution::occursIn(TermId var, TermId term, const TermBank& bank) const } const Term& t = bank.getTerm(term); - for (TermId const arg : t.args_) { - if (occursIn(var, arg, bank)) { - return true; - } - } - return false; + return std::any_of(t.args_.begin(), t.args_.end(), + [&](TermId arg) { return occursIn(var, arg, bank); }); } void Substitution::clear() { diff --git a/src/main.cc b/src/main.cc index 81dbc91..c683d39 100644 --- a/src/main.cc +++ b/src/main.cc @@ -43,7 +43,7 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } - const std::string kFilepath = argv[1]; + const std::string filepath = argv[1]; try { // 1. Initialize core modules @@ -52,9 +52,9 @@ int main(int argc, char* argv[]) { atp::ClauseStore store; // 2. Parse TPTP input - auto problem = atp::parseTptpFile(kFilepath, bank, symbols); + auto problem = atp::parseTptpFile(filepath, bank, symbols); - std::cerr << "% Parsed " << problem.formulas_.size() << " formulas from " << kFilepath + std::cerr << "% Parsed " << problem.formulas_.size() << " formulas from " << filepath << "\n"; // 3. Prepare clauses for proving @@ -70,23 +70,23 @@ int main(int argc, char* argv[]) { // 5. Output result (SZS format) switch (result) { case atp::ProverResult::kTheorem: { - std::cout << "% SZS status Theorem for " << kFilepath << "\n\n"; + std::cout << "% SZS status Theorem for " << filepath << "\n\n"; // Extract and print proof auto eid = prover.getEmptyClauseId(); if (eid.has_value()) { auto proof = atp::extractProof(store, *eid); - std::cout << "% SZS output start Proof for " << kFilepath << "\n"; + std::cout << "% SZS output start Proof for " << filepath << "\n"; std::cout << atp::formatProof(proof, store, bank); - std::cout << "% SZS output end Proof for " << kFilepath << "\n"; + std::cout << "% SZS output end Proof for " << filepath << "\n"; } break; } case atp::ProverResult::kSaturation: - std::cout << "% SZS status Satisfiable for " << kFilepath << "\n"; + std::cout << "% SZS status Satisfiable for " << filepath << "\n"; break; case atp::ProverResult::kTimeout: - std::cout << "% SZS status Timeout for " << kFilepath << "\n"; + std::cout << "% SZS status Timeout for " << filepath << "\n"; break; } diff --git a/src/proof/proof_trace.cc b/src/proof/proof_trace.cc index a0d5a11..5fa4b04 100644 --- a/src/proof/proof_trace.cc +++ b/src/proof/proof_trace.cc @@ -26,7 +26,6 @@ #include "atp/core/types.h" #include <algorithm> -#include <array> #include <cstddef> #include <stack> #include <string> @@ -47,20 +46,20 @@ std::vector<ProofStep> extractProof(const ClauseStore& store, ClauseId empty_cla worklist.push(empty_clause_id); while (!worklist.empty()) { - const ClauseId kCid = worklist.top(); + const ClauseId cid = worklist.top(); worklist.pop(); - if (kCid == kInvalidId) { + if (cid == kInvalidId) { continue; } - if (visited.contains(kCid)) { + if (visited.contains(cid)) { continue; } - visited.insert(kCid); + visited.insert(cid); - const Clause& c = store.getClause(kCid); + const Clause& c = store.getClause(cid); steps.push_back({ - .clause_id_ = kCid, + .clause_id_ = cid, .rule_ = c.rule_, .parent1_ = c.parent1_, .parent2_ = c.parent2_, @@ -105,15 +104,32 @@ namespace { /// Generate a human-readable variable name from an index. /// 0→X, 1→Y, 2→Z, 3→W, 4→V, 5→U, 6→X1, 7→Y1, ... std::string prettyVarName(size_t index) { - static constexpr std::array<char, 6> kBaseNames = {'X', 'Y', 'Z', 'W', 'V', 'U'}; - static constexpr size_t kBaseCount = kBaseNames.size(); + constexpr size_t kBaseCount = 6; + const size_t base_index = index % kBaseCount; + const char base = [&]() { + switch (base_index) { + case 0: + return 'X'; + case 1: + return 'Y'; + case 2: + return 'Z'; + case 3: + return 'W'; + case 4: + return 'V'; + case 5: + return 'U'; + default: + return 'X'; + } + }(); - const char kBase = kBaseNames[index % kBaseCount]; - const size_t kSuffix = index / kBaseCount; - if (kSuffix == 0) { - return std::string{kBase}; + const size_t suffix = index / kBaseCount; + if (suffix == 0) { + return std::string{base}; } - return std::string{kBase} + std::to_string(kSuffix); + return std::string{base} + std::to_string(suffix); } /// Pretty-print a term, renaming variables to readable names. @@ -125,9 +141,9 @@ std::string termToPretty(TermId id, const TermBank& bank, if (it != var_map.end()) { return it->second; } - const std::string kName = prettyVarName(var_map.size()); - var_map[id] = kName; - return kName; + const std::string name = prettyVarName(var_map.size()); + var_map[id] = name; + return name; } const Term& t = bank.getTerm(id); diff --git a/src/search/prover.cc b/src/search/prover.cc index 2c2de40..f3f8bb0 100644 --- a/src/search/prover.cc +++ b/src/search/prover.cc @@ -47,114 +47,113 @@ void Prover::addClauses(std::vector<Clause> clauses) { } } +bool Prover::hitResourceLimit(size_t iterations) const { + return iterations >= config_.max_iterations_ || store_.size() >= config_.max_clauses_; +} + +Clause Prover::popGivenClause() { + Clause given = unprocessed_.top(); + unprocessed_.pop(); + return given; +} + +bool Prover::isForwardSubsumedByProcessed(const Clause& clause) const { + return std::ranges::any_of(processed_, + [&](ClauseId pid) { return subsumes(store_.getClause(pid), clause); }); +} + +bool Prover::shouldSkipGiven(const Clause& given) const { + return isTautology(given) || isForwardSubsumedByProcessed(given); +} + +void Prover::applyBackwardSubsumption(const Clause& given) { + std::erase_if(processed_, [&](ClauseId pid) { return subsumes(given, store_.getClause(pid)); }); +} + +std::vector<Clause> Prover::generateNewClauses(const Clause& given) const { + std::vector<Clause> new_clauses; + const UnificationConfig uconfig{.enable_occurs_check_ = config_.enable_occurs_check_}; + + for (ClauseId const pid : processed_) { + const Clause& pc = store_.getClause(pid); + + auto resolvents1 = allResolvents(bank_, given, pc, uconfig); + auto resolvents2 = allResolvents(bank_, pc, given, uconfig); + + for (auto& r : resolvents1) { + new_clauses.push_back(std::move(r)); + } + for (auto& r : resolvents2) { + new_clauses.push_back(std::move(r)); + } + } + + auto factors = factor(bank_, given, uconfig); + for (auto& f : factors) { + new_clauses.push_back(std::move(f)); + } + + return new_clauses; +} + +uint16_t Prover::computeDepth(const Clause& clause) const { + uint32_t const d1 = (clause.parent1_ != kInvalidId) ? store_.getClause(clause.parent1_).depth_ : 0; + uint32_t const d2 = (clause.parent2_ != kInvalidId) ? store_.getClause(clause.parent2_).depth_ : 0; + return static_cast<uint16_t>(std::max(d1, d2) + 1); +} + +std::optional<ClauseId> Prover::processNewClauses(std::vector<Clause> new_clauses) { + for (auto& nc : new_clauses) { + if (nc.isEmpty()) { + return store_.addClause(std::move(nc)); + } + + if (isTautology(nc)) { + continue; + } + + nc.depth_ = computeDepth(nc); + + ClauseId const nid = store_.addClause(nc); + const Clause& stored_nc = store_.getClause(nid); + if (isForwardSubsumedByProcessed(stored_nc)) { + continue; + } + + unprocessed_.push(stored_nc); + } + + return std::nullopt; +} + ProverResult Prover::prove() { size_t iterations = 0; while (!unprocessed_.empty()) { - // Resource limits - if (iterations >= config_.max_iterations_ || store_.size() >= config_.max_clauses_) { + if (hitResourceLimit(iterations)) { return ProverResult::kTimeout; } ++iterations; - // 1. Select the best clause from unprocessed - Clause given = unprocessed_.top(); - unprocessed_.pop(); + Clause given = popGivenClause(); - // 2. Check if given is itself the empty clause if (given.isEmpty()) { empty_clause_id_ = given.id_; return ProverResult::kTheorem; } - // 3. Forward redundancy checks - if (isTautology(given)) { - continue; - } - - bool forward_subsumed = false; - for (ClauseId const pid : processed_) { - if (subsumes(store_.getClause(pid), given)) { - forward_subsumed = true; - break; - } - } - if (forward_subsumed) { + if (shouldSkipGiven(given)) { continue; } - // 4. Backward subsumption - // Remove from processed all clauses that are subsumed by given. - // Use erase-remove idiom for O(n) scan instead of repeated erase. - std::erase_if(processed_, - [&](ClauseId pid) { return subsumes(given, store_.getClause(pid)); }); - - // 5. Generate new clauses - // Inference BEFORE adding given to processed — matches doc §4.6. - std::vector<Clause> new_clauses; - const UnificationConfig kUconfig{.enable_occurs_check_ = config_.enable_occurs_check_}; - - // 5a. Resolve given with every processed clause (both directions) - for (ClauseId const pid : processed_) { - const Clause& pc = store_.getClause(pid); - - auto resolvents1 = allResolvents(bank_, given, pc, kUconfig); - auto resolvents2 = allResolvents(bank_, pc, given, kUconfig); - - for (auto& r : resolvents1) { - new_clauses.push_back(std::move(r)); - } - for (auto& r : resolvents2) { - new_clauses.push_back(std::move(r)); - } - } - - // 5b. Factor given (only once) - auto factors = factor(bank_, given, kUconfig); - for (auto& f : factors) { - new_clauses.push_back(std::move(f)); - } - - // 6. Add given to processed AFTER inference + applyBackwardSubsumption(given); + std::vector<Clause> new_clauses = generateNewClauses(given); processed_.push_back(given.id_); - // 7. Process new clauses - for (auto& nc : new_clauses) { - // 7a. Check for empty clause → proof found! - if (nc.isEmpty()) { - ClauseId eid = store_.addClause(std::move(nc)); - empty_clause_id_ = eid; - return ProverResult::kTheorem; - } - - // 7b. Skip tautologies - if (isTautology(nc)) { - continue; - } - - // 7c. Set depth - uint32_t const d1 = (nc.parent1_ != kInvalidId) ? store_.getClause(nc.parent1_).depth_ : 0; - uint32_t const d2 = (nc.parent2_ != kInvalidId) ? store_.getClause(nc.parent2_).depth_ : 0; - nc.depth_ = static_cast<uint16_t>(std::max(d1, d2) + 1); - - // 7d. Store the clause (needed for forward subsumption check) - ClauseId const nid = store_.addClause(nc); - const Clause& stored_nc = store_.getClause(nid); - - // 7e. Forward subsumption on new clause - bool new_subsumed = false; - for (ClauseId const pid : processed_) { - if (subsumes(store_.getClause(pid), stored_nc)) { - new_subsumed = true; - break; - } - } - if (new_subsumed) { - continue; - } - - // 7f. Enqueue - unprocessed_.push(stored_nc); + const std::optional<ClauseId> derived_empty = processNewClauses(std::move(new_clauses)); + if (derived_empty.has_value()) { + empty_clause_id_ = derived_empty; + return ProverResult::kTheorem; } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index eea0ceb..184357b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ include(GoogleTest) function(atp_add_test TEST_NAME TEST_SOURCE) add_executable(${TEST_NAME} ${TEST_SOURCE}) target_link_libraries(${TEST_NAME} PRIVATE atp_core GTest::gtest_main) + target_compile_options(${TEST_NAME} PRIVATE ${ATP_PROJECT_WARNING_FLAGS}) gtest_discover_tests(${TEST_NAME}) endfunction() |
