From ded3ad2f6e2a03095b15f01444709266da082bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20Miku=C4=8Dionis?= Date: Fri, 22 Sep 2023 14:17:20 +0200 Subject: [PATCH] Added clang-tidy support and fixed all the warnings (except bison and libxml2) --- CMakeLists.txt | 12 +- cmake/clang-tidy.cmake | 20 + cmake/sanitizers.cmake | 9 +- include/utap/ExpressionBuilder.hpp | 4 +- include/utap/StatementBuilder.hpp | 4 +- include/utap/builder.h | 2 +- include/utap/document.h | 18 +- include/utap/expression.h | 16 +- include/utap/property.h | 2 +- include/utap/symbols.h | 4 +- include/utap/type.h | 6 +- include/utap/typechecker.h | 68 ++-- src/DocumentBuilder.cpp | 97 +++-- src/ExpressionBuilder.cpp | 24 +- src/StatementBuilder.cpp | 22 +- src/document.cpp | 58 ++- src/dynlib.cpp | 8 +- src/expression.cpp | 66 ++-- src/keywords.cpp | 4 +- src/lexer.l | 14 +- src/libparser.h | 4 +- src/parser.y | 562 ++++++++++++++--------------- src/position.cpp | 1 - src/prettyprinter.cpp | 48 +-- src/print.hpp | 88 +++++ src/property.cpp | 2 +- src/symbols.cpp | 23 +- src/type.cpp | 20 +- src/typechecker.cpp | 190 +++++----- src/xmlreader.cpp | 76 ++-- src/xmlwriter.cpp | 12 +- test/syntaxcheck.cpp | 4 +- test/test_parser.cpp | 46 +-- 33 files changed, 788 insertions(+), 746 deletions(-) create mode 100644 cmake/clang-tidy.cmake create mode 100644 src/print.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c3187da..b634b1e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ option(FIND_FATAL "Stop upon find_package errors" OFF) cmake_policy(SET CMP0048 NEW) # project() command manages VERSION variables include(cmake/stdcpp.cmake) include(cmake/sanitizers.cmake) +include(cmake/clang-tidy.cmake) set(UTAP_PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(UTAP_VERSION "${PACKAGE_VERSION}") @@ -37,6 +38,11 @@ find_package(FLEX 2.6.4 REQUIRED) find_package(BISON 3.6.0 REQUIRED) include(cmake/libxml2.cmake) +if (UTAP_WITH_TESTS) + include(cmake/doctest.cmake) + enable_testing() +endif(UTAP_WITH_TESTS) + if(UTAP_STATIC) #set(CMAKE_CXX_STANDARD_LIBRARIES "-static -static-libgcc -static-libstdc++ ${CMAKE_CXX_STANDARD_LIBRARIES}") set(CMAKE_EXE_LINKER_FLAGS -static) @@ -50,10 +56,8 @@ endif() add_subdirectory(src) if (UTAP_WITH_TESTS) - include(cmake/doctest.cmake) - enable_testing() -endif(UTAP_WITH_TESTS) -add_subdirectory(test) + add_subdirectory(test) +endif (UTAP_WITH_TESTS) target_include_directories(UTAP PRIVATE diff --git a/cmake/clang-tidy.cmake b/cmake/clang-tidy.cmake new file mode 100644 index 00000000..75e7f5ef --- /dev/null +++ b/cmake/clang-tidy.cmake @@ -0,0 +1,20 @@ +find_program(CLANG_TIDY_PROGRAM clang-tidy-14 clang-tidy) +if(CLANG_TIDY_PROGRAM) + execute_process(COMMAND ${CLANG_TIDY_PROGRAM} --version OUTPUT_VARIABLE CLANG_TIDY_VERSION_STRING) + string(REGEX MATCH "LLVM version ([0-9A-Za-z]+)\\.([0-9A-Za-z\\.]+)" TIDY_VERSION "${CLANG_TIDY_VERSION_STRING}") + set(TIDY_MAJOR_VERSION "${CMAKE_MATCH_1}") + set(TIDY_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}") + + # We use NOLINTBEGIN and NOLINTEND to preserve some macros + # This was only introduced in version 14 + if (TIDY_MAJOR_VERSION GREATER_EQUAL 14) + # Add good checks which produce a minimal amount of false positives + # One or two false positives can be dealt with using // NOLINT + set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_PROGRAM} -checks=-*,cppcoreguidelines-macro-usage,hicpp-deprecated-headers,modernize-deprecated-headers,hicpp-use-override,hicpp-use-emplace,modernize-use-emplace,hicpp-use-auto,readability-container-size-empty,readability-implicit-bool-conversion,readability-redundant-smartptr-get,readability-qualified-auto,performance-unnecessary-value-param,modernize-make-unique,modernize-make-shared,misc-unused-using-decls,performance-move-const-arg,modernize-use-using,modernize-use-nullptr,modernize-deprecated-headers,modernize-loop-convert,misc-unused-using-decls,misc-static-assert,misc-redundant-expression,modernize-use-bool-literals,readability-delete-null-pointer,readability-redundant-member-init --warnings-as-errors=-*) + message(STATUS "Enabled clang-tidy ${TIDY_VERSION}: ${CLANG_TIDY_PROGRAM}") + else() + message(WARNING "Found clang-tidy ${TIDY_VERSION}, but >=14 is required, thus disabled.") + endif() +else(CLANG_TIDY_PROGRAM) + message(WARNING "No clang-tidy found. Some checks are not enabled") +endif(CLANG_TIDY_PROGRAM) diff --git a/cmake/sanitizers.cmake b/cmake/sanitizers.cmake index 2c0e2277..8a4d41f1 100644 --- a/cmake/sanitizers.cmake +++ b/cmake/sanitizers.cmake @@ -4,6 +4,7 @@ option(SSP "Stack Smashing Protector" OFF) # Available on Windows too option(UBSAN "Undefined Behavior Sanitizer" OFF) option(ASAN "Address Sanitizer" OFF) +option(LSAN "Leak Sanitizer" OFF) option(TSAN "Thread Sanitizer" OFF) if (SSP) @@ -12,7 +13,7 @@ if (SSP) message(STATUS "Enable Stack Smashing Protector") endif(SSP) -if (ASAN OR UBSAN OR TSAN) +if (ASAN OR UBSAN OR LSAN OR TSAN) add_compile_options(-fno-omit-frame-pointer) add_link_options(-fno-omit-frame-pointer) endif() @@ -29,6 +30,12 @@ if (ASAN) message(STATUS "Enabled Address Sanitizer") endif(ASAN) +if (LSAN) + add_compile_options(-fsanitize=leak) + add_link_options(-fsanitize=leak) + message(STATUS "Enabled Leak Sanitizer") +endif(LSAN) + if (TSAN) add_compile_options(-fsanitize=thread) add_link_options(-fsanitize=thread) diff --git a/include/utap/ExpressionBuilder.hpp b/include/utap/ExpressionBuilder.hpp index 88d469ec..31a6f715 100644 --- a/include/utap/ExpressionBuilder.hpp +++ b/include/utap/ExpressionBuilder.hpp @@ -218,8 +218,8 @@ class ExpressionBuilder : public AbstractBuilder void expr_sum_dynamic_end(const char* name) override; void expr_foreach_dynamic_begin(const char*, const char*) override; void expr_foreach_dynamic_end(const char* name) override; - void push_dynamic_frame_of(template_t* t, std::string name); // no override - void pop_dynamic_frame_of(std::string name); + void push_dynamic_frame_of(template_t* t, const std::string& name); // no override + void pop_dynamic_frame_of(const std::string& name); }; } // namespace UTAP diff --git a/include/utap/StatementBuilder.hpp b/include/utap/StatementBuilder.hpp index 4a0e03ba..2a4d9c19 100644 --- a/include/utap/StatementBuilder.hpp +++ b/include/utap/StatementBuilder.hpp @@ -61,8 +61,8 @@ class StatementBuilder : public ExpressionBuilder virtual variable_t* addVariable(type_t type, const std::string& name, expression_t init, position_t pos) = 0; virtual bool addFunction(type_t type, const std::string& name, position_t pos) = 0; - static void collectDependencies(std::set&, expression_t); - static void collectDependencies(std::set&, type_t); + static void collectDependencies(std::set&, const expression_t&); + static void collectDependencies(std::set&, const type_t&); public: explicit StatementBuilder(Document&, std::vector libpaths = {}); diff --git a/include/utap/builder.h b/include/utap/builder.h index 32f903bf..29d69df9 100644 --- a/include/utap/builder.h +++ b/include/utap/builder.h @@ -478,7 +478,7 @@ int32_t parse_XTA(const char*, UTAP::ParserBuilder*, bool newxta); * is used; otherwise the 3.x syntax is used. On success, this * function returns with a positive value. */ -int32_t parse_XTA(const char*, UTAP::ParserBuilder*, bool newxta, UTAP::xta_part_t part, std::string xpath); +int32_t parse_XTA(const char*, UTAP::ParserBuilder*, bool newxta, UTAP::xta_part_t part, const std::string& xpath); /** * Parse a buffer in the XML format, reporting the document to the given diff --git a/include/utap/document.h b/include/utap/document.h index 8d7104d6..a1a8152a 100644 --- a/include/utap/document.h +++ b/include/utap/document.h @@ -187,7 +187,7 @@ struct declarations_t : stringify_t std::list ganttChart; /** Add function declaration. */ - bool add_function(type_t type, std::string name, position_t, function_t*&); + bool add_function(type_t type, const std::string& name, position_t, function_t*&); /** The following methods are used to write the declarations in an XML file */ std::string str(bool global) const; std::ostream& print(std::ostream&, bool global = false) const; @@ -535,14 +535,14 @@ class Document variable_t* add_variable(declarations_t*, type_t type, const std::string&, expression_t initial, position_t); void add_progress_measure(declarations_t*, expression_t guard, expression_t measure); - template_t& add_template(const std::string& name, frame_t params, position_t, bool isTA = true, + template_t& add_template(const std::string& name, const frame_t& params, position_t, bool isTA = true, const std::string& type = "", const std::string& mode = ""); - template_t& add_dynamic_template(const std::string& name, frame_t params, position_t pos); + template_t& add_dynamic_template(const std::string& name, const frame_t& params, position_t pos); - instance_t& add_instance(const std::string& name, instance_t& instance, frame_t params, + instance_t& add_instance(const std::string& name, instance_t& instance, const frame_t& params, const std::vector& arguments, position_t); - instance_t& add_LSC_instance(const std::string& name, instance_t& instance, frame_t params, + instance_t& add_LSC_instance(const std::string& name, instance_t& instance, const frame_t& params, const std::vector& arguments, position_t); void remove_process(instance_t& instance); // LSC @@ -555,10 +555,10 @@ class Document void add_gantt(declarations_t*, gantt_t); // copies gantt_t and moves it void accept(DocumentVisitor&); - void set_before_update(expression_t); - expression_t get_before_update(); - void set_after_update(expression_t); - expression_t get_after_update(); + void set_before_update(expression_t e) { before_update = std::move(e); } + expression_t& get_before_update() { return before_update; } + void set_after_update(expression_t e) { after_update = std::move(e); } + expression_t& get_after_update() { return after_update; } void add_query(query_t query); // creates a copy and moves it bool queries_empty() const; diff --git a/include/utap/expression.h b/include/utap/expression.h index 9143f15a..3d2d508b 100644 --- a/include/utap/expression.h +++ b/include/utap/expression.h @@ -90,11 +90,11 @@ class expression_t /** Makes a deep clone of the expression and replaces the symbol * "from" with the symbol "to". */ - expression_t clone_deeper(symbol_t from, symbol_t to) const; + expression_t clone_deeper(const symbol_t& from, const symbol_t& to) const; /** Makes a deep clone of the expression and replaces each symbol * with a symbol from the given frame(s), with the same name */ - expression_t clone_deeper(frame_t frame, frame_t select = {}) const; + expression_t clone_deeper(const frame_t& frame, const frame_t& select = {}) const; /** Returns the kind of the expression. */ Constants::kind_t get_kind() const; @@ -206,13 +206,13 @@ class expression_t /** Less-than operator. Makes it possible to put expression_t objects into an STL set. */ - bool operator<(const expression_t) const; + bool operator<(const expression_t&) const; /** Equality operator. Returns true if the two references point to the same expression object. */ - bool operator==(const expression_t) const; + bool operator==(const expression_t&) const; - expression_t subst(symbol_t, expression_t) const; + expression_t subst(const symbol_t&, expression_t) const; /** * Precedence of expression type, higher precedence goes before low precedence @@ -228,7 +228,7 @@ class expression_t static expression_t create_string(StringIndex, position_t = {}); /** Create an IDENTIFIER expression */ - static expression_t create_identifier(symbol_t, position_t = {}); + static expression_t create_identifier(const symbol_t&, position_t = {}); /** Create a unary expression */ static expression_t create_unary(Constants::kind_t, expression_t, position_t = {}, type_t = {}); @@ -257,10 +257,10 @@ class expression_t // true if empty or equal to 1. bool is_true() const; int get_precedence() const; - friend std::ostream& operator<<(std::ostream& o, const UTAP::expression_t& e) { return o << e.str(); } + friend std::ostream& operator<<(std::ostream& o, const UTAP::expression_t& e) { return e.print(o); } private: - std::ostream& print_bound_type(std::ostream& os, expression_t e) const; + std::ostream& print_bound_type(std::ostream& os, const expression_t& e) const; }; } // namespace UTAP diff --git a/include/utap/property.h b/include/utap/property.h index dedaa79f..dc8bfaef 100644 --- a/include/utap/property.h +++ b/include/utap/property.h @@ -211,7 +211,7 @@ class PropertyBuilder : public std::enable_shared_from_this, pu UTAP::position_t pos) override; bool addFunction(UTAP::type_t type, const std::string& name, UTAP::position_t pos) override; - void typeCheck(UTAP::expression_t expr); + void typeCheck(UTAP::expression_t& expr); bool allowProcessReferences() override; virtual void typeProperty(UTAP::expression_t); diff --git a/include/utap/symbols.h b/include/utap/symbols.h index e65b0445..078b1510 100644 --- a/include/utap/symbols.h +++ b/include/utap/symbols.h @@ -200,13 +200,13 @@ class frame_t void add(symbol_t); /** Add all symbols from the given frame */ - void add(frame_t); + void add(const frame_t&); /** Move all symbols from this to a given one (leaving this empty). */ void move_to(frame_t); /** removes the given symbol*/ - void remove(symbol_t s); + void remove(const symbol_t& s); /** Resolves a name in this frame or a parent frame. */ bool resolve(const std::string& name, symbol_t& symbol) const; diff --git a/include/utap/type.h b/include/utap/type.h index 505bc3c6..6bc680f9 100644 --- a/include/utap/type.h +++ b/include/utap/type.h @@ -345,7 +345,7 @@ class type_t * the type (expressions that occur as ranges either on * array sizes, scalars or integers) with \a expr. */ - type_t subst(symbol_t symbol, expression_t expr) const; + type_t subst(const symbol_t& symbol, const expression_t& expr) const; /** * Creates a new type by adding a prefix to it. The prefix * could be anything and it is the responsibility of the @@ -358,7 +358,7 @@ class type_t /** */ - static type_t create_range(type_t, expression_t, expression_t, position_t = position_t()); + static type_t create_range(type_t, const expression_t&, const expression_t&, position_t = position_t()); /** Create a primitive type. */ static type_t create_primitive(Constants::kind_t, position_t = position_t()); @@ -373,7 +373,7 @@ class type_t static type_t create_process(frame_t, position_t = position_t()); /** Creates a new processset type. */ - static type_t create_process_set(type_t instance, position_t = position_t()); + static type_t create_process_set(const type_t& instance, position_t = position_t()); /** Creates a new record type */ static type_t create_record(const std::vector&, const std::vector&, position_t = position_t()); diff --git a/include/utap/typechecker.h b/include/utap/typechecker.h index 21a2ab18..1623512c 100644 --- a/include/utap/typechecker.h +++ b/include/utap/typechecker.h @@ -45,7 +45,7 @@ class CompileTimeComputableValues : public DocumentVisitor void visitVariable(variable_t&) override; void visitInstance(instance_t&) override; void add_symbol(symbol_t); - bool contains(symbol_t) const; + bool contains(const symbol_t&) const; }; /** @@ -58,35 +58,35 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor { private: Document& document; - CompileTimeComputableValues compileTimeComputableValues; + mutable CompileTimeComputableValues compileTimeComputableValues; function_t* function; /**< Current function being type checked. */ bool refinementWarnings; template - void handleError(T, const std::string&); + void handleError(T, const std::string&) const; template - void handleWarning(T, const std::string&); + void handleWarning(T, const std::string&) const; - expression_t checkInitialiser(type_t type, expression_t init); - bool areAssignmentCompatible(type_t lvalue, type_t rvalue, bool init = false) const; - bool areInlineIfCompatible(type_t result_type, type_t thenArg, type_t elseArg) const; + expression_t checkInitialiser(const type_t& type, const expression_t& init); + bool areAssignmentCompatible(const type_t& lvalue, const type_t& rvalue, bool init = false) const; + bool areInlineIfCompatible(const type_t& result_type, const type_t& thenArg, const type_t& elseArg) const; type_t getInlineIfCommonType(type_t t1, type_t t2) const; - bool areEqCompatible(type_t t1, type_t t2) const; - bool isLValue(expression_t) const; - bool isModifiableLValue(expression_t) const; - bool isUniqueReference(expression_t expr) const; - bool isParameterCompatible(type_t param, expression_t arg); - bool checkParameterCompatible(type_t param, expression_t arg); - void checkIgnoredValue(expression_t expr); - bool checkAssignmentExpression(expression_t); - bool checkConditionalExpressionInFunction(expression_t); - void checkObservationConstraints(expression_t); - - bool isCompileTimeComputable(expression_t expr) const; - void checkType(type_t, bool initialisable = false, bool inStruct = false); + bool areEqCompatible(const type_t& t1, const type_t& t2) const; + bool isLValue(const expression_t&) const; + bool isModifiableLValue(const expression_t&) const; + bool isUniqueReference(const expression_t& expr) const; + bool isParameterCompatible(const type_t& param, const expression_t& arg) const; + bool checkParameterCompatible(const type_t& param, const expression_t& arg) const; + void checkIgnoredValue(const expression_t& expr) const; + bool checkAssignmentExpression(expression_t&); + bool checkConditionalExpressionInFunction(const expression_t&); + void checkObservationConstraints(const expression_t&); + + bool isCompileTimeComputable(const expression_t& expr) const; + void checkType(const type_t&, bool initialisable = false, bool inStruct = false) const; public: - static bool areEquivalent(type_t, type_t); + static bool areEquivalent(const type_t&, const type_t&); explicit TypeChecker(Document& doc, bool refinement = false); void visitTemplateAfter(template_t&) override; bool visitTemplateBefore(template_t&) override; @@ -95,10 +95,10 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor void visitLocation(location_t&) override; void visitEdge(edge_t&) override; void visitInstance(instance_t&) override; - virtual void visitProperty(expression_t); // FIXME: does not override?! + virtual void visitProperty(expression_t&); // FIXME: does not override?! void visitFunction(function_t&) override; void visitProgressMeasure(progress_t&) override; - virtual void visitHybridClock(expression_t); // FIXME: does not override?! + virtual void visitHybridClock(expression_t&); // FIXME: does not override?! void visitIODecl(iodecl_t&) override; void visitGanttChart(gantt_t&) override; void visitProcess(instance_t&) override; @@ -119,8 +119,8 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor bool checkDynamicExpressions(Statement* stat); /** Type check an expression */ - bool checkExpression(expression_t); - bool checkSpawnParameterCompatible(type_t param, expression_t arg); + bool checkExpression(expression_t&) const; + bool checkSpawnParameterCompatible(const type_t& param, const expression_t& arg) const; private: int syncUsed; // Keep track of sync declarations, 0->nothing, 1->IO, 2->CSP, -1->error. @@ -130,15 +130,15 @@ class TypeChecker : public DocumentVisitor, public AbstractStatementVisitor 1) consistent semantic checks by code reuse, 2) meaningful names to the otherwise anonymous expressions. */ - bool checkNrOfRuns(const expression_t& expr); - bool checkBoundTypeOrBoundedExpr(const expression_t& expr); - bool checkBound(const expression_t& expr); - bool checkPredicate(const expression_t& expr); - bool checkProbBound(const expression_t& expr); - bool checkUntilCond(Constants::kind_t kind, const expression_t& expr); - bool checkMonitoredExpr(const expression_t& expr); - bool checkPathQuant(const expression_t& expr); - bool checkAggregationOp(const expression_t& expr); + bool checkNrOfRuns(const expression_t& expr) const; + bool checkBoundTypeOrBoundedExpr(const expression_t& expr) const; + bool checkBound(const expression_t& expr) const; + bool checkPredicate(const expression_t& expr) const; + bool checkProbBound(const expression_t& expr) const; + bool checkUntilCond(Constants::kind_t kind, const expression_t& expr) const; + bool checkMonitoredExpr(const expression_t& expr) const; + bool checkPathQuant(const expression_t& expr) const; + bool checkAggregationOp(const expression_t& expr) const; }; } // namespace UTAP diff --git a/src/DocumentBuilder.cpp b/src/DocumentBuilder.cpp index 07611ec1..953bdcb0 100644 --- a/src/DocumentBuilder.cpp +++ b/src/DocumentBuilder.cpp @@ -21,6 +21,8 @@ #include "utap/DocumentBuilder.hpp" +#include "print.hpp" + #include #include #include @@ -30,10 +32,6 @@ using namespace UTAP; using namespace Constants; using std::vector; -using std::pair; -using std::make_pair; -using std::min; -using std::max; using std::string; DocumentBuilder::DocumentBuilder(Document& doc, std::vector paths): @@ -45,7 +43,7 @@ DocumentBuilder::DocumentBuilder(Document& doc, std::vectorparameters.get_size() != params.get_size()) { handle_error(TypeException{"Inconsistent parameters"}); @@ -257,7 +255,7 @@ void DocumentBuilder::proc_select(const char* id) { addSelectSymbolToFrame(id, c void DocumentBuilder::proc_guard() { - if (!currentEdge) { + if (currentEdge == nullptr) { handle_error(TypeException("Must be declared inside of an edge")); return; } @@ -268,7 +266,7 @@ void DocumentBuilder::proc_guard() void DocumentBuilder::proc_sync(synchronisation_t type) { - if (!currentEdge) { + if (currentEdge == nullptr) { handle_error(TypeException("Must be declared inside of an edge")); return; } @@ -279,7 +277,7 @@ void DocumentBuilder::proc_sync(synchronisation_t type) void DocumentBuilder::proc_update() { - if (!currentEdge) { + if (currentEdge == nullptr) { handle_error(TypeException("Must be declared inside of an edge")); return; } @@ -290,7 +288,7 @@ void DocumentBuilder::proc_update() void DocumentBuilder::proc_prob() { - if (!currentEdge) { + if (currentEdge == nullptr) { handle_error(TypeException("Must be declared inside of an edge")); return; } @@ -340,7 +338,7 @@ void DocumentBuilder::instantiation_end(const char* name, size_t parameters, con */ symbol_t id; if (resolve(templ_name, id) && (id.get_type().get_kind() == INSTANCE || id.get_type().get_kind() == LSC_INSTANCE)) { - instance_t* old_instance = static_cast(id.get_data()); + auto* old_instance = static_cast(id.get_data()); /* Check number of arguments. If too many arguments, pop the * rest. @@ -351,17 +349,15 @@ void DocumentBuilder::instantiation_end(const char* name, size_t parameters, con } else if (arguments > expected) { handle_error(TypeException{"$Too_many_arguments"}); } else { - /* Collect arguments from expression stack. - */ - vector exprs(arguments); - while (arguments) { + // Collect arguments from expression stack. + auto exprs = vector(arguments); + while (arguments > 0) { arguments--; - exprs[arguments] = fragments[0]; + exprs[arguments] = std::move(fragments[0]); fragments.pop(); } - /* Create template composition. - */ + // Create template composition. instance_t& new_instance = (id.get_type().get_kind() == INSTANCE) ? document.add_instance(name, *old_instance, params, exprs, position) : document.add_LSC_instance(name, *old_instance, params, exprs, position); @@ -474,7 +470,7 @@ void DocumentBuilder::instance_name(const char* name, bool templ) } } else { if (resolve(string(name), uid) && (uid.get_type().get_kind() == INSTANCE)) { - template_t* t = static_cast(uid.get_data()); + auto* t = static_cast(uid.get_data()); if (t->parameters.get_size() > 0) { handle_error(TypeException{"$Wrong_number_of_arguments_in_instance_line_name"}); } @@ -496,8 +492,8 @@ void DocumentBuilder::instance_name_begin(const char* name) void DocumentBuilder::instance_name_end(const char* name, size_t arguments) { - std::string i_name = std::string(name); - vector::const_iterator itr; + auto i_name = std::ostringstream{}; + i_name << name; /* Parameters are at the top of the frame stack. */ frame_t params = frames.top(); @@ -509,36 +505,26 @@ void DocumentBuilder::instance_name_end(const char* name, size_t arguments) */ symbol_t id; if (resolve(name, id) && id.get_type().get_kind() == INSTANCE) { - instance_t* old_instance = static_cast(id.get_data()); + auto* old_instance = static_cast(id.get_data()); /* Check number of arguments. If too many arguments, pop the * rest. */ - size_t expected = id.get_type().size(); + auto expected = id.get_type().size(); if (arguments < expected) { handle_error(TypeException{"$Too_few_arguments"}); } else if (arguments > expected) { handle_error(TypeException{"$Too_many_arguments"}); } else { - /* Collect arguments from expression stack. - */ - vector exprs(arguments); - while (arguments) { - arguments--; - exprs[arguments] = fragments[0]; + // Collect arguments from expression stack. + auto exprs = vector(arguments); + while (arguments-- > 0) { + exprs[arguments] = std::move(fragments[0]); fragments.pop(); } - i_name += '('; - for (itr = exprs.begin(); itr != exprs.end(); ++itr) { - if (itr != exprs.begin() && exprs.size() > 1) { - i_name += ','; - } - i_name += itr->str(); - } - i_name += ')'; - instance_name(i_name.c_str()); // std::cout << "instance line name: " << i_name << std::endl; - /* Create template composition. - */ + i_name << '(' << infix(exprs, ",") << ')'; + instance_name(i_name.str().c_str()); + // Create template composition. currentInstanceLine->add_parameters(*old_instance, params, exprs); /* Propagate information about restricted variables. The @@ -575,7 +561,7 @@ void DocumentBuilder::proc_message(const char* from, const char* to, const int l void DocumentBuilder::proc_message(synchronisation_t type) // Label { - if (currentMessage) + if (currentMessage != nullptr) currentMessage->label = expression_t::create_sync(fragments[0], type, position); fragments.pop(); } @@ -610,7 +596,7 @@ void DocumentBuilder::proc_condition(const vector& anchors, const int lo void DocumentBuilder::proc_condition() { - if (currentCondition) + if (currentCondition != nullptr) currentCondition->label = fragments[0]; fragments.pop(); } @@ -632,7 +618,7 @@ void DocumentBuilder::proc_LSC_update(const char* anchor, const int loc, const b void DocumentBuilder::proc_LSC_update() // Label { - if (currentUpdate) + if (currentUpdate != nullptr) currentUpdate->label = fragments[0]; fragments.pop(); } @@ -663,16 +649,16 @@ void DocumentBuilder::decl_dynamic_template(const std::string& name) void DocumentBuilder::query_begin() { currentQuery = std::make_unique(); } void DocumentBuilder::query_formula(const char* formula, const char* location) { - if (formula) { + if (formula != nullptr) { currentQuery->formula = formula; } - if (location) { + if (location != nullptr) { currentQuery->location = location; } } void DocumentBuilder::query_comment(const char* comment) { - if (comment) { + if (comment != nullptr) { currentQuery->comment = comment; } } @@ -695,27 +681,28 @@ void DocumentBuilder::expectation_end() void DocumentBuilder::expectation_value(const char* res, const char* type, const char* value) { + using namespace std::string_view_literals; expectation_type _type; - if (!type) { + if (type == nullptr) { _type = expectation_type::_ErrorValue; - } else if (strcmp(type, "probability") == 0) { + } else if (type == "probability"sv) { _type = expectation_type::Probability; - } else if (strcmp(type, "symbolic")) { + } else if (type == "symbolic"sv) { _type = expectation_type::Symbolic; - } else if (strcmp(type, "value")) { + } else if (type == "value"sv) { _type = expectation_type::NumericValue; } else { _type = expectation_type::_ErrorValue; } if (res == nullptr) { currentExpectation->status = query_status_t::Unknown; - } else if (strcmp(res, "success") == 0) { + } else if (res == "success"sv) { currentExpectation->status = query_status_t::True; - } else if (strcmp(res, "failure")) { + } else if (res == "failure"sv) { currentExpectation->status = query_status_t::False; - } else if (strcmp(res, "maybe_true") == 0) { + } else if (res == "maybe_true"sv) { currentExpectation->status = query_status_t::MaybeTrue; - } else if (strcmp(res, "maybe_false") == 0) { + } else if (res == "maybe_false"sv) { currentExpectation->status = query_status_t::MaybeFalse; } else { currentExpectation->status = query_status_t::Unknown; diff --git a/src/ExpressionBuilder.cpp b/src/ExpressionBuilder.cpp index c22dff84..79905812 100644 --- a/src/ExpressionBuilder.cpp +++ b/src/ExpressionBuilder.cpp @@ -36,7 +36,6 @@ using namespace Constants; using std::vector; using std::string; -using std::map; inline static bool isMITL(const expression_t& e) { @@ -59,7 +58,7 @@ inline static expression_t toMITLAtom(const expression_t& e) { return expression void ExpressionBuilder::ExpressionFragments::pop(uint32_t n) { assert(n <= size()); - while (n--) + while (n-- > 0) pop(); } @@ -198,7 +197,7 @@ void ExpressionBuilder::type_void() typeFragments.push(type); } -static void collectDependencies(std::set& dependencies, expression_t expr) +static void collectDependencies(std::set& dependencies, const expression_t& expr) { std::set symbols; expr.collect_possible_reads(symbols); @@ -208,7 +207,7 @@ static void collectDependencies(std::set& dependencies, expression_t e if (dependencies.find(s) == dependencies.end()) { dependencies.insert(s); if (auto* data = s.get_data(); data) { - variable_t* v = static_cast(data); + auto* v = static_cast(data); v->init.collect_possible_reads(symbols); } } @@ -233,7 +232,7 @@ void ExpressionBuilder::type_scalar(PREFIX prefix) type = type.create_label(string("#scalarset") + count, position); - if (currentTemplate) { + if (currentTemplate != nullptr) { /* Local scalar definitions are local to a particular process * - not to the template. Therefore we prefix it with the * template name and rename the template name to the process @@ -977,7 +976,7 @@ void ExpressionBuilder::expr_forall_dynamic_begin(const char* name, const char* push_frame(frame_t::create(frames.top())); frames.top().add_symbol(name, type_t::create_primitive(PROCESS_VAR, position), position); template_t* templ = document.find_dynamic_template(temp); - if (!templ) + if (templ == nullptr) throw UnknownDynamicTemplateError(temp); // dynamicFrames[name]=templ->frame; push_dynamic_frame_of(templ, name); @@ -1010,9 +1009,8 @@ void ExpressionBuilder::expr_exists_dynamic_begin(const char* name, const char* push_frame(frame_t::create(frames.top())); frames.top().add_symbol(name, type_t::create_primitive(Constants::PROCESS_VAR, position), position); template_t* templ = document.find_dynamic_template(temp); - if (!templ) { + if (templ == nullptr) throw UnknownDynamicTemplateError(temp); - } // dynamicFrames [name]=templ->frame; push_dynamic_frame_of(templ, name); } @@ -1042,9 +1040,8 @@ void ExpressionBuilder::expr_sum_dynamic_begin(const char* name, const char* tem push_frame(frame_t::create(frames.top())); frames.top().add_symbol(name, type_t::create_primitive(Constants::PROCESS_VAR, position), position); template_t* templ = document.find_dynamic_template(temp); - if (!templ) { + if (templ == nullptr) throw UnknownDynamicTemplateError(temp); - } // dynamicFrames [name]=templ->frame; push_dynamic_frame_of(templ, name); } @@ -1065,9 +1062,8 @@ void ExpressionBuilder::expr_foreach_dynamic_begin(const char* name, const char* { push_frame(frame_t::create(frames.top())); frames.top().add_symbol(name, type_t::create_primitive(Constants::PROCESS_VAR, position), position); - if (!document.find_dynamic_template(temp)) { + if (document.find_dynamic_template(temp) == nullptr) throw UnknownDynamicTemplateError(temp); - } // dynamicFrames [name]=document->find_dynamic_template(temp)->frame; push_dynamic_frame_of(document.find_dynamic_template(temp), name); } @@ -1085,7 +1081,7 @@ void ExpressionBuilder::expr_foreach_dynamic_end(const char* name) pop_dynamic_frame_of(name); } -void ExpressionBuilder::push_dynamic_frame_of(template_t* t, string name) +void ExpressionBuilder::push_dynamic_frame_of(template_t* t, const string& name) { if (!t->is_defined) { throw TypeException("Template referenced before used"); @@ -1093,4 +1089,4 @@ void ExpressionBuilder::push_dynamic_frame_of(template_t* t, string name) dynamicFrames[name] = t->frame; } -void ExpressionBuilder::pop_dynamic_frame_of(string name) { dynamicFrames.erase(name); } +void ExpressionBuilder::pop_dynamic_frame_of(const string& name) { dynamicFrames.erase(name); } diff --git a/src/StatementBuilder.cpp b/src/StatementBuilder.cpp index dfc98b16..f0b3ecd2 100644 --- a/src/StatementBuilder.cpp +++ b/src/StatementBuilder.cpp @@ -47,19 +47,19 @@ StatementBuilder::StatementBuilder(Document& doc, std::vectorlibpaths.insert(this->libpaths.begin(), ""); } -void StatementBuilder::collectDependencies(std::set& dependencies, expression_t expr) +void StatementBuilder::collectDependencies(std::set& dependencies, const expression_t& expr) { - std::set symbols; + auto symbols = std::set{}; expr.collect_possible_reads(symbols); while (!symbols.empty()) { symbol_t s = *symbols.begin(); symbols.erase(s); if (dependencies.find(s) == dependencies.end()) { dependencies.insert(s); - if (auto d = s.get_data(); d) { + if (auto* d = s.get_data(); d) { if (auto t = s.get_type(); !(t.is_function() || t.is_function_external())) { // assume is its variable, which is not always true - variable_t* v = static_cast(d); + auto* v = static_cast(d); v->init.collect_possible_reads(symbols); } else { // TODO; fixme. @@ -69,7 +69,7 @@ void StatementBuilder::collectDependencies(std::set& dependencies, exp } } -void StatementBuilder::collectDependencies(std::set& dependencies, type_t type) +void StatementBuilder::collectDependencies(std::set& dependencies, const type_t& type) { if (type.get_kind() == RANGE) { auto [lower, upper] = type.get_range(); @@ -111,7 +111,7 @@ void StatementBuilder::type_array_of_type(size_t n) * not be able to compute the offset of a process in a set of * processes. */ - if (currentTemplate) { + if (currentTemplate != nullptr) { collectDependencies(currentTemplate->restricted, size); } @@ -151,7 +151,7 @@ void StatementBuilder::struct_field(const char* name) } fields.push_back(type); - labels.push_back(name); + labels.emplace_back(name); /* Check the base type. We should check this in the type * checker. The problem is that we do not maintain the position of @@ -203,7 +203,7 @@ static bool initialisable(type_t type) } } -static bool mustInitialise(type_t type) +static bool mustInitialise(const type_t& type) { const auto k = type.get_kind(); assert(k != FUNCTION); @@ -254,7 +254,7 @@ void StatementBuilder::decl_var(const char* name, bool hasInit) handle_error(TypeException{"$Constants_must_have_an_initialiser"}); } - if (currentFun && !initialisable(type)) { + if (currentFun != nullptr && !initialisable(type)) { handle_error(TypeException{"$Type_is_not_allowed_in_functions"}); } @@ -420,7 +420,7 @@ void StatementBuilder::dynamic_load_lib(const char* lib) success = true; break; } catch (const std::runtime_error& ex) { - errors.push_back(ex.what()); + errors.emplace_back(ex.what()); continue; } } @@ -575,7 +575,7 @@ void StatementBuilder::expr_statement() void StatementBuilder::return_statement(bool args) { // 1 expr if argument is true - if (!currentFun) { + if (currentFun == nullptr) { handle_error(TypeException{"$Cannot_return_outside_of_function_declaration"}); } else { /* Only functions with non-void return type are allowed to have diff --git a/src/document.cpp b/src/document.cpp index ea22664d..06ca917d 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -41,14 +41,7 @@ using namespace UTAP; using namespace Constants; using std::list; -using std::stack; using std::vector; -using std::map; -using std::pair; -using std::make_pair; -using std::min; -using std::max; -using std::set; using std::string; using std::ostream; using std::deque; @@ -114,7 +107,7 @@ std::ostream& function_t::print(std::ostream& os) const type.get(i).print_declaration(os << ", ") << ' ' << type.get_label(i); } os << ")\n{\n"; // open function body - for (auto& variable : variables) + for (const auto& variable : variables) variable.print(os << " ") << ";\n"; os << body->str(INDENT); return os << "}"; @@ -135,11 +128,11 @@ std::ostream& variable_t::print(std::ostream& os) const return os; } -bool declarations_t::add_function(type_t type, string name, position_t pos, function_t*& fun) +bool declarations_t::add_function(type_t type, const string& name, position_t pos, function_t*& fun) { bool duplicate = frame.contains(name); fun = &functions.emplace_back(); - fun->uid = frame.add_symbol(name, type, pos, fun); // Add symbol + fun->uid = frame.add_symbol(name, std::move(type), pos, fun); // Add symbol return !duplicate; } @@ -179,7 +172,7 @@ std::ostream& declarations_t::print_constants(std::ostream& os) const std::ostream& declarations_t::print_typedefs(std::ostream& os) const { bool first = true; - for (auto& symbol : frame) { + for (const auto& symbol : frame) { if (symbol.get_type().get_kind() == TYPEDEF) { if (first) { os << "// type definitions\n"; @@ -273,11 +266,10 @@ location_t& template_t::add_location(const string& name, expression_t inv, expre auto& loc = locations.emplace_back(); loc.uid = frame.add_symbol(name, type_t::create_primitive(LOCATION), pos, &loc); loc.nr = locations.size() - 1; - loc.invariant = inv; - loc.exp_rate = er; - if (duplicate) { + loc.invariant = std::move(inv); + loc.exp_rate = std::move(er); + if (duplicate) throw DuplicateDefinitionError(name); - } return loc; } @@ -445,7 +437,7 @@ const vector template_t::get_simregions() } } s.nr = simregions.size(); - simregions.push_back(std::move(s)); + simregions.push_back(s); } /** @@ -539,7 +531,7 @@ bool template_t::get_update(vector& instances, int y, update_t void instance_line_t::add_parameters(instance_t& inst, frame_t params, const vector& arguments1) { unbound = params.get_size(); - parameters = params; + parameters = std::move(params); parameters.add(inst.parameters); mapping = inst.mapping; arguments = arguments1.size(); @@ -778,7 +770,7 @@ library_t& Document::last_library() * method does not check for duplicate declarations. An instance with * the same name and parameters is added as well. */ -template_t& Document::add_template(const string& name, frame_t params, position_t position, const bool is_TA, +template_t& Document::add_template(const string& name, const frame_t& params, position_t position, const bool is_TA, const string& typeLSC, const string& mode) { type_t type = (is_TA) ? type_t::create_instance(params) : type_t::create_LSC_instance(params); @@ -798,7 +790,7 @@ template_t& Document::add_template(const string& name, frame_t params, position_ return templ; } -template_t& Document::add_dynamic_template(const std::string& name, frame_t params, position_t pos) +template_t& Document::add_dynamic_template(const std::string& name, const frame_t& params, position_t pos) { type_t type = type_t::create_instance(params); dyn_templates.emplace_back(); @@ -853,7 +845,7 @@ template_t* Document::find_dynamic_template(const std::string& name) return &(*it); } -instance_t& Document::add_instance(const string& name, instance_t& inst, frame_t params, +instance_t& Document::add_instance(const string& name, instance_t& inst, const frame_t& params, const vector& arguments, position_t pos) { type_t type = type_t::create_instance(params); @@ -870,7 +862,7 @@ instance_t& Document::add_instance(const string& name, instance_t& inst, frame_t return instance; } -instance_t& Document::add_LSC_instance(const string& name, instance_t& inst, frame_t params, +instance_t& Document::add_LSC_instance(const string& name, instance_t& inst, const frame_t& params, const vector& arguments, position_t pos) { type_t type = type_t::create_LSC_instance(params); @@ -923,16 +915,16 @@ void Document::set_options(const options_t& options) { model_options = options; variable_t* Document::add_variable(declarations_t* context, type_t type, const string& name, expression_t initial, position_t pos) { - variable_t* var = add_variable(context->variables, context->frame, type, name, pos); - var->init = initial; + variable_t* var = add_variable(context->variables, context->frame, std::move(type), name, pos); + var->init = std::move(initial); return var; } variable_t* Document::add_variable_to_function(function_t* function, frame_t frame, type_t type, const string& name, expression_t initial, position_t pos) { - variable_t* var = add_variable(function->variables, frame, type, name, pos); - var->init = initial; + variable_t* var = add_variable(function->variables, std::move(frame), std::move(type), name, pos); + var->init = std::move(initial); return var; } @@ -944,7 +936,7 @@ variable_t* Document::add_variable(list& variables, frame_t frame, t // Add variable variable_t& var = variables.emplace_back(); // Add symbol - var.uid = frame.add_symbol(name, type, pos, &var); + var.uid = frame.add_symbol(name, std::move(type), pos, &var); if (duplicate) throw DuplicateDefinitionError(name); return &var; @@ -965,7 +957,7 @@ void Document::copy_functions_from_to(const template_t* from, template_t* to) co void Document::add_progress_measure(declarations_t* context, expression_t guard, expression_t measure) { - context->progress.emplace_back(guard, measure); + context->progress.emplace_back(std::move(guard), std::move(measure)); } static void visit(DocumentVisitor& visitor, frame_t frame) @@ -1052,19 +1044,11 @@ void Document::accept(DocumentVisitor& visitor) visitor.visitDocAfter(*this); } -void Document::set_before_update(expression_t e) { before_update = e; } - -expression_t Document::get_before_update() { return before_update; } - -void Document::set_after_update(expression_t e) { after_update = e; } - -expression_t Document::get_after_update() { return after_update; } - void Document::begin_chan_priority(expression_t chan) { hasPriorities |= true; chan_priority_t priorities; - priorities.head = chan; + priorities.head = std::move(chan); chan_priorities.push_back(priorities); } @@ -1072,7 +1056,7 @@ void Document::add_chan_priority(char separator, expression_t chan) { assert(separator == ',' || separator == '<'); chan_priority_t::tail_t& tail = chan_priorities.back().tail; - tail.push_back(chan_priority_t::entry(separator, chan)); + tail.push_back(chan_priority_t::entry(separator, std::move(chan))); } void Document::set_proc_priority(const string& name, int priority) diff --git a/src/dynlib.cpp b/src/dynlib.cpp index d80521fc..f1608092 100644 --- a/src/dynlib.cpp +++ b/src/dynlib.cpp @@ -54,11 +54,11 @@ inline library_t::state_t::state_t(const char* name): handle{dlopen(name, RTLD_N inline library_t::state_t::~state_t() noexcept { - if (handle) { + if (handle != nullptr) { auto res [[maybe_unused]] = dlclose(handle); handle = nullptr; #ifndef NDEBUG - if (res) + if (res != 0) std::cerr << dlerror() << std::endl; #endif } @@ -66,8 +66,8 @@ inline library_t::state_t::~state_t() noexcept void* library_t::get_symbol(const char* name) { - auto res = dlsym(pImpl->handle, name); - if (!res) + auto* res = dlsym(pImpl->handle, name); + if (res == nullptr) throw std::runtime_error(dlerror()); return res; } diff --git a/src/expression.cpp b/src/expression.cpp index 5d3b8367..24f7614c 100644 --- a/src/expression.cpp +++ b/src/expression.cpp @@ -35,12 +35,8 @@ using namespace UTAP; using namespace Constants; -using std::make_pair; -using std::map; -using std::max; using std::min; using std::ostream; -using std::pair; using std::set; using std::vector; @@ -87,7 +83,7 @@ expression_t expression_t::clone_deeper() const return expr; } -expression_t expression_t::clone_deeper(symbol_t from, symbol_t to) const +expression_t expression_t::clone_deeper(const symbol_t& from, const symbol_t& to) const { auto expr = expression_t{data->kind, data->position}; expr.data->value = data->value; @@ -102,7 +98,7 @@ expression_t expression_t::clone_deeper(symbol_t from, symbol_t to) const return expr; } -expression_t expression_t::clone_deeper(frame_t frame, frame_t select) const +expression_t expression_t::clone_deeper(const frame_t& frame, const frame_t& select) const { auto expr = expression_t{data->kind, data->position}; expr.data->value = data->value; @@ -127,7 +123,7 @@ expression_t expression_t::clone_deeper(frame_t frame, frame_t select) const return expr; } -expression_t expression_t::subst(symbol_t symbol, expression_t expr) const +expression_t expression_t::subst(const symbol_t& symbol, expression_t expr) const { if (empty()) { return *this; @@ -430,7 +426,7 @@ size_t expression_t::get_size() const case IDENTIFIER: case CONSTANT: - case DEADLOCK: assert(data->sub.size() == 0); return 0; + case DEADLOCK: assert(data->sub.empty()); return 0; case LOAD_STRAT: case INLINE_IF: @@ -483,7 +479,7 @@ size_t expression_t::get_size() const case MITL_CONJ: assert(data->sub.size() == 2); return 2; case MITL_UNTIL: case MITL_RELEASE: assert(data->sub.size() == 4); return 4; - case EXIT: assert(data->sub.size() == 0); return 0; + case EXIT: assert(data->sub.empty()); return 0; case NUMOF: assert(data->sub.size() == 1); return 1; case EXISTS_DYNAMIC: case FORALL_DYNAMIC: @@ -505,14 +501,14 @@ type_t expression_t::get_type() const void expression_t::set_type(type_t type) { assert(data); - data->type = type; + data->type = std::move(type); } int32_t expression_t::get_value() const { assert(data && data->kind == CONSTANT && (data->type.is_integral() || data->kind == VAR_INDEX)); int32_t value = std::get(data->value); - return data->type.is_integer() ? value : (value ? 1 : 0); + return data->type.is_integer() ? value : (value != 0 ? 1 : 0); } int32_t expression_t::get_record_label_index() const @@ -639,6 +635,7 @@ const symbol_t& expression_t::get_symbol() { return ((const expression_t*)this)- const symbol_t& expression_t::get_symbol() const { + static auto blank = symbol_t{}; assert(data); switch (get_kind()) { @@ -674,9 +671,7 @@ const symbol_t& expression_t::get_symbol() const case SCENARIO: return get(0).get_symbol(); - default: - assert(false); - // return symbol_t(); + default: return blank; } } @@ -984,7 +979,7 @@ static void ensure(char*& str, char*& end, int& size, int len) static void append(char*& str, char*& end, int& size, const char* s) { - while (end < str + size && *s) { + while (end < str + size && *s != '\0') { *(end++) = *(s++); } @@ -996,7 +991,7 @@ static void append(char*& str, char*& end, int& size, const char* s) } } -std::ostream& expression_t::print_bound_type(std::ostream& os, expression_t e) const +std::ostream& expression_t::print_bound_type(std::ostream& os, const expression_t& e) const { if (e.get_kind() == CONSTANT) { assert(e.get_type().is(Constants::INT)); // Encoding used here. @@ -1135,7 +1130,7 @@ std::ostream& expression_t::print(std::ostream& os, bool old) const os << "E["; print_bound_type(os, get(0)); get(1).print(os, old) << "; "; - get(2).print(os, old) << "] (" << (get(4).get_value() ? "max: " : "min: "); + get(2).print(os, old) << "] (" << (get(4).get_value() != 0 ? "max: " : "min: "); get(3).print(os, old) << ")"; break; @@ -1269,7 +1264,7 @@ std::ostream& expression_t::print(std::ostream& os, bool old) const os << std::get(data->value); } else { assert(get_type().is(Constants::BOOL)); - os << (std::get(data->value) ? "true" : "false"); + os << (std::get(data->value) != 0 ? "true" : "false"); } break; @@ -1715,12 +1710,12 @@ std::ostream& expression_t::print(std::ostream& os, bool old) const return os; } -bool expression_t::operator<(const expression_t e) const +bool expression_t::operator<(const expression_t& e) const { return data != nullptr && e.data != nullptr && data < e.data; } -bool expression_t::operator==(const expression_t e) const { return data == e.data; } +bool expression_t::operator==(const expression_t& e) const { return data == e.data; } /** Returns a string representation of the expression. The string returned must be deallocated with delete[]. Returns empty is the @@ -1766,7 +1761,8 @@ void expression_t::collect_possible_writes(set& symbols) const case FUN_CALL_EXT: // Add all symbols which are changed by the function symbol = get(0).get_symbol(); - if ((symbol.get_type().is_function() || symbol.get_type().is_function_external()) && symbol.get_data()) { + if ((symbol.get_type().is_function() || symbol.get_type().is_function_external()) && + symbol.get_data() != nullptr) { fun = (function_t*)symbol.get_data(); symbols.insert(fun->changes.begin(), fun->changes.end()); @@ -1801,7 +1797,7 @@ void expression_t::collect_possible_reads(set& symbols, bool collectRa auto symbol = get(0).get_symbol(); if (auto type = symbol.get_type(); type.is_function() || type.is_function_external()) { if (auto* data = symbol.get_data(); data) { - auto fun = static_cast(data); + auto* fun = static_cast(data); symbols.insert(fun->depends.begin(), fun->depends.end()); } } @@ -1875,7 +1871,7 @@ expression_t expression_t::create_string(StringIndex str, position_t pos) return expr; } -expression_t expression_t::create_identifier(symbol_t symbol, position_t pos) +expression_t expression_t::create_identifier(const symbol_t& symbol, position_t pos) { auto expr = expression_t{IDENTIFIER, pos}; expr.data->symbol = symbol; @@ -1892,15 +1888,15 @@ expression_t expression_t::create_nary(kind_t kind, vector sub, po auto expr = expression_t{kind, pos}; expr.data->value = static_cast(sub.size()); expr.data->sub = std::move(sub); - expr.data->type = type; + expr.data->type = std::move(type); return expr; } expression_t expression_t::create_unary(kind_t kind, expression_t sub, position_t pos, type_t type) { auto expr = expression_t{kind, pos}; - expr.data->sub.push_back(sub); - expr.data->type = type; + expr.data->sub.push_back(std::move(sub)); + expr.data->type = std::move(type); return expr; } @@ -1909,9 +1905,9 @@ expression_t expression_t::create_binary(kind_t kind, expression_t left, express { auto expr = expression_t{kind, pos}; expr.data->sub.reserve(2); - expr.data->sub.push_back(left); - expr.data->sub.push_back(right); - expr.data->type = type; + expr.data->sub.push_back(std::move(left)); + expr.data->sub.push_back(std::move(right)); + expr.data->type = std::move(type); return expr; } @@ -1920,10 +1916,10 @@ expression_t expression_t::create_ternary(kind_t kind, expression_t e1, expressi { auto expr = expression_t{kind, pos}; expr.data->sub.reserve(3); - expr.data->sub.push_back(e1); - expr.data->sub.push_back(e2); - expr.data->sub.push_back(e3); - expr.data->type = type; + expr.data->sub.push_back(std::move(e1)); + expr.data->sub.push_back(std::move(e2)); + expr.data->sub.push_back(std::move(e3)); + expr.data->type = std::move(type); return expr; } @@ -1931,8 +1927,8 @@ expression_t expression_t::create_dot(expression_t e, int32_t idx, position_t po { auto expr = expression_t{DOT, pos}; expr.data->value = idx; - expr.data->sub.push_back(e); - expr.data->type = type; + expr.data->sub.push_back(std::move(e)); + expr.data->type = std::move(type); return expr; } diff --git a/src/keywords.cpp b/src/keywords.cpp index 9c2903b8..6579aa19 100644 --- a/src/keywords.cpp +++ b/src/keywords.cpp @@ -163,8 +163,8 @@ const Keyword* find_keyword(std::string_view word) bool is_keyword(std::string_view word, syntax_t syntax) { const auto* keyword = find_keyword(word); - if (keyword) - return keyword->syntax & syntax; + if (keyword != nullptr) + return (keyword->syntax & syntax) != syntax_t::NONE; else return false; } diff --git a/src/lexer.l b/src/lexer.l index 90c7dc79..799dacbf 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -70,13 +70,13 @@ idchr [a-zA-Z0-9_$#] \n+ { tracker.newline(ch, yyleng); - if ((syntax & syntax_t::PROPERTY) != 0) + if ((syntax & syntax_t::PROPERTY) != syntax_t::NONE) return '\n'; } (\r\n)+ { tracker.newline(ch, yyleng / 2); - if ((syntax & syntax_t::PROPERTY) != 0) + if ((syntax & syntax_t::PROPERTY) != syntax_t::NONE) return '\n'; } @@ -133,14 +133,14 @@ idchr [a-zA-Z0-9_$#] "<=" { return T_LEQ; } ">=" { return T_GEQ; } "=<" { - if (syntax & syntax_t::OLD) { + if ((syntax & syntax_t::OLD) != syntax_t::NONE) { return T_LEQ; } utap_error("$Unknown_symbol"); return T_ERROR; } "=>" { - if (syntax & syntax_t::OLD) { + if ((syntax & syntax_t::OLD) != syntax_t::NONE) { return T_GEQ; } utap_error("$Unknown_symbol"); @@ -181,12 +181,12 @@ idchr [a-zA-Z0-9_$#] auto s = keyword.syntax; #ifndef ENABLE_PROB // Remove all PROB keywords if pro is not enabled. - if (s & syntax_t::PROB) { + if ((s & syntax_t::PROB) != syntax_t::NONE) { s = syntax_t::NONE; } #endif - if (syntax & s) { - if (keyword.token == T_CONST && (syntax & syntax_t::OLD)) { + if ((syntax & s) != syntax_t::NONE) { + if (keyword.token == T_CONST && ((syntax & syntax_t::OLD) != syntax_t::NONE)) { return T_OLDCONST; } return keyword.token; diff --git a/src/libparser.h b/src/libparser.h index fbd4164a..08875118 100644 --- a/src/libparser.h +++ b/src/libparser.h @@ -51,10 +51,10 @@ enum class syntax_t : unsigned int { OLD_GUIDING = OLD | GUIDING }; -constexpr std::underlying_type_t operator&(const syntax_t& s1, const syntax_t& s2) +constexpr syntax_t operator&(const syntax_t& s1, const syntax_t& s2) { using T = std::underlying_type_t; - return (static_cast(s1) & static_cast(s2)); + return syntax_t{static_cast(s1) & static_cast(s2)}; } namespace UTAP { diff --git a/src/parser.y b/src/parser.y index 265b992e..81d5f03b 100644 --- a/src/parser.y +++ b/src/parser.y @@ -1,23 +1,23 @@ // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*- /* libutap - Uppaal Timed Automata Parser. - Copyright (C) 2011-2022 Aalborg University. - Copyright (C) 2002-2011 Uppsala University and Aalborg University. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License - as published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - USA + Copyright (C) 2011-2022 Aalborg University. + Copyright (C) 2002-2011 Uppsala University and Aalborg University. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA */ /********************************************************************* @@ -38,6 +38,11 @@ * made. Please report it, this might be corrected. */ +%{ +// NOLINTBEGIN +/** NO LINTING HERE */ +%} + %code requires { #include "parser.hpp" @@ -50,21 +55,19 @@ using namespace UTAP; using namespace Constants; -#define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).start = YYRHSLOC (Rhs, 1).start; \ - (Current).end = YYRHSLOC (Rhs, N).end; \ - } \ - else \ - { \ - (Current).start = (Current).end = \ - YYRHSLOC (Rhs, 0).end; \ - } \ - while (0) +// NOLINTBEGIN +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) { \ + (Current).start = YYRHSLOC (Rhs, 1).start; \ + (Current).end = YYRHSLOC (Rhs, N).end; \ + } else { \ + (Current).start = (Current).end = YYRHSLOC (Rhs, 0).end; \ + } \ + while (0) #define YYLTYPE position_t +// NOLINTEND } %code { @@ -78,13 +81,13 @@ static int lexer_flex(); static int utap_lex() { - int old; - if (syntax_token) { - old = syntax_token; - syntax_token = 0; - return old; - } - return lexer_flex(); + int old; + if (syntax_token != 0) { + old = syntax_token; + syntax_token = 0; + return old; + } + return lexer_flex(); } static char rootTransId[MAXLEN]; @@ -92,78 +95,57 @@ static char rootTransId[MAXLEN]; /* Counter used during array parsing. */ static int types = 0; -#define CALL(first,last,call) do { ch->set_position(first.start, last.end); try { ch->call; } catch (TypeException &te) { ch->handle_error(te); } } while (0) - -#define YY_(msg) utap_msg(msg) - struct str_entry_t { - int len; - const char* from; - const char* to; + int len; + const char* from; + const char* to; }; const char* utap_msg(const char *msg) { - /* Simple & short log(n) algorithm. - */ -#define NB_STR 8 - static const str_entry_t table[NB_STR] = - { - { .len=12, - .from="syntax error", - .to="$syntax_error" }, - { .len=16, - .from="memory exhausted", - .to="$memory_exhausted" }, - { .len=27, - .from="syntax error, unexpected %s", - .to="$syntax_error: $unexpected %s" }, - { .len=28, - .from="syntax error: cannot back up", - .to="$syntax_error: $cannot_back_up" }, - { .len=41, - .from="syntax error, unexpected %s, expecting %s", - .to="$syntax_error: $unexpected %s, $expecting %s" }, - { .len=47, - .from="syntax error, unexpected %s, expecting %s or %s", - .to="$syntax_error: $unexpected %s, $expecting %s $or %s" }, - { .len=53, - .from="syntax error, unexpected %s, expecting %s or %s or %s", - .to="$syntax_error: $unexpected %s, $expecting %s $or %s $or %s" }, - { .len=59, - .from="syntax error, unexpected %s, expecting %s or %s or %s or %s", - .to="$syntax_error: $unexpected %s, $expecting %s $or %s $or %s $or %s" } - }; - int len = std::strlen(msg); - int i = NB_STR / 2; - while(i < NB_STR) - { - if (len < table[i].len) - { - if (i == 0) return msg; - i = i/2; - continue; - } - if (len > table[i].len) - { - if (i == NB_STR-1) return msg; - i = (i+NB_STR)/2; - continue; - } - for(;i < NB_STR && len <= table[i].len; ++i) - { - if (strcmp(msg, table[i].from) == 0) - { - return table[i].to; - } - } - break; - } + // Simple & short log(n) algorithm. + constexpr auto NB_STR = 8u; + static const str_entry_t table[NB_STR] = { + { 12, "syntax error", "$syntax_error" }, + { 16, "memory exhausted", "$memory_exhausted" }, + { 27, "syntax error, unexpected %s", "$syntax_error: $unexpected %s" }, + { 28, "syntax error: cannot back up", "$syntax_error: $cannot_back_up" }, + { 41, "syntax error, unexpected %s, expecting %s", "$syntax_error: $unexpected %s, $expecting %s" }, + { 47, "syntax error, unexpected %s, expecting %s or %s", + "$syntax_error: $unexpected %s, $expecting %s $or %s" }, + { 53, "syntax error, unexpected %s, expecting %s or %s or %s", + "$syntax_error: $unexpected %s, $expecting %s $or %s $or %s" }, + { 59, "syntax error, unexpected %s, expecting %s or %s or %s or %s", + "$syntax_error: $unexpected %s, $expecting %s $or %s $or %s $or %s" } + }; + int len = std::strlen(msg); + auto i = NB_STR / 2; + while (i < NB_STR) { + if (len < table[i].len) { + if (i == 0) return msg; + i = i/2; + continue; + } + if (len > table[i].len) { + if (i == NB_STR-1) return msg; + i = (i+NB_STR)/2; + continue; + } + for(;i < NB_STR && len <= table[i].len; ++i) { + if (strcmp(msg, table[i].from) == 0) { + return table[i].to; + } + } + break; + } return msg; -#undef NB_STR } +#define CALL(first,last,call) do { ch->set_position(first.start, last.end); try { ch->call; } catch (TypeException &te) { ch->handle_error(te); } } while (0) + +#define YY_(msg) utap_msg(msg) + } %require "3.6.0" @@ -398,10 +380,10 @@ InstanceLineExpression: OptionalInstanceParameterList: /* empty */ { $$ = 0; } | '(' ')' { - $$ = 0; + $$ = 0; } | '(' ParameterList ')' { - $$ = $2; + $$ = $2; }; System: SysDecl Progress GanttDecl; @@ -464,8 +446,8 @@ GanttDef: /* empty */ | GanttDef NonTypeId { CALL(@2, @2, gantt_decl_begin($2)); } GanttArgs ':' GanttExprList ';' { CALL(@2, @6, gantt_decl_end()); - } - ; + } + ; GanttArgs: /* empty */ @@ -484,12 +466,12 @@ GanttDeclSelect: GanttExprList: GanttExpr | GanttExprList ',' GanttExpr - ; + ; GanttExpr: Expression T_ARROW Expression { - CALL(@1, @3, gantt_entry_begin()); - CALL(@1, @3, gantt_entry_end()); + CALL(@1, @3, gantt_entry_begin()); + CALL(@1, @3, gantt_entry_end()); } | T_FOR { CALL(@1, @1, gantt_entry_begin()); } '(' GanttEntrySelect ')' Expression T_ARROW Expression { CALL(@1, @7, gantt_entry_end()); } @@ -530,10 +512,10 @@ FunctionDecl: /* Notice that StatementList will catch all errors. Hence we * should be able to guarantee, that once declFuncBegin() has * been called, we will also call declFuncEnd(). - * Correction: No it won't. - * int f() { if (cond) { return 0; } - * will generate an error, not call declFuncEnd, and the builder - * will be left in an inconsistent state. EndBlock fixes that. + * Correction: No it won't. + * int f() { if (cond) { return 0; } + * will generate an error, not call declFuncEnd, and the builder + * will be left in an inconsistent state. EndBlock fixes that. * * Correction^2: It did not fix it. Discussion continued at * StatementBuilder::declFuncBegin definition @@ -693,17 +675,17 @@ Type: CALL(@1, @2, type_bool($1)); } | T_DOUBLE { - CALL(@1, @1, type_double(ParserBuilder::PREFIX_NONE)); + CALL(@1, @1, type_double(ParserBuilder::PREFIX_NONE)); } | TypePrefix T_DOUBLE { - CALL(@1, @2, type_double($1)); - } + CALL(@1, @2, type_double($1)); + } | T_STRING { - CALL(@1, @1, type_string(ParserBuilder::PREFIX_NONE)); + CALL(@1, @1, type_string(ParserBuilder::PREFIX_NONE)); } | TypePrefix T_STRING { - CALL(@1, @2, type_string($1)); - } + CALL(@1, @2, type_string($1)); + } | T_INT { CALL(@1, @1, type_int(ParserBuilder::PREFIX_NONE)); } @@ -724,11 +706,11 @@ Type: CALL(@1, @2, type_channel($1)); } | T_CLOCK { - CALL(@1, @1, type_clock(ParserBuilder::PREFIX_NONE)); + CALL(@1, @1, type_clock(ParserBuilder::PREFIX_NONE)); } | T_HYBRID T_CLOCK { - CALL(@1, @1, type_clock(ParserBuilder::PREFIX_HYBRID)); - } + CALL(@1, @1, type_clock(ParserBuilder::PREFIX_HYBRID)); + } | T_VOID { CALL(@1, @1, type_void()); } @@ -808,8 +790,8 @@ ProcDecl: ProcBody: ProcLocalDeclList States LocFlags Init Transitions - | ProcLocalDeclList States Branchpoints LocFlags Init Transitions - | /* empty */ + | ProcLocalDeclList States Branchpoints LocFlags Init Transitions + | /* empty */ ; ProcLocalDeclList: @@ -832,17 +814,17 @@ StateDeclList: StateDecl: NonTypeId { CALL(@1, @1, proc_location($1, false, false)); } | NonTypeId '{' ';' ExpRate '}' { - CALL(@1, @5, proc_location($1, false, true)); - } + CALL(@1, @5, proc_location($1, false, true)); + } | NonTypeId '{' Expression '}' { - CALL(@1, @4, proc_location($1, true, false)); + CALL(@1, @4, proc_location($1, true, false)); } | NonTypeId '{' Expression ';' ExpRate '}' { - CALL(@1, @6, proc_location($1, true, true)); - } + CALL(@1, @6, proc_location($1, true, true)); + } | NonTypeId '{' error '}' { - CALL(@1, @4, proc_location($1, false, false)); - } + CALL(@1, @4, proc_location($1, false, false)); + } ; Branchpoints: @@ -857,7 +839,7 @@ BranchpointDeclList: BranchpointDecl: NonTypeId { - CALL(@1, @1, proc_branchpoint($1)); + CALL(@1, @1, proc_branchpoint($1)); }; Init: @@ -940,7 +922,7 @@ Sync: SyncExpr: Expression { - CALL(@1, @1, proc_sync(SYNC_CSP)); + CALL(@1, @1, proc_sync(SYNC_CSP)); } | Expression T_EXCLAM { CALL(@1, @2, proc_sync(SYNC_BANG)); @@ -1017,9 +999,9 @@ UStateList: ExpRate: Expression - | Expression ':' Expression { - CALL(@1,@3, expr_binary(FRACTION)); - }; + | Expression ':' Expression { + CALL(@1,@3, expr_binary(FRACTION)); + }; /********************************************************************** * Uppaal C grammar @@ -1057,18 +1039,18 @@ IfCondition: T_IF '(' { CALL(@1, @2, if_begin()); } ExprList ')' { CALL(@3, @3, IfConditionThenMatched: IfCondition MatchedStatement T_ELSE { CALL(@1, @3, if_then()); }; MatchedStatement: IfConditionThenMatched MatchedStatement { - CALL(@1, @2, if_end(true)); - } + CALL(@1, @2, if_end(true)); + } | OtherStatement - ; + ; UnmatchedStatement: IfCondition Statement { CALL(@2, @2, if_then()); CALL(@1, @2, if_end(false)); - } + } | IfConditionThenMatched UnmatchedStatement { - CALL(@1, @2, if_end(true)); - } + CALL(@1, @2, if_end(true)); + } ; OtherStatement: @@ -1080,7 +1062,7 @@ OtherStatement: CALL(@1, @2, expr_statement()); } | ForStatement - | WhileStatement + | WhileStatement | T_BREAK ';' { CALL(@1, @2, break_statement()); } @@ -1100,8 +1082,8 @@ OtherStatement: CALL(@1, @2, return_statement(false)); } | T_ASSERT Expression ';' { - CALL(@1, @2, assert_statement()); - } + CALL(@1, @2, assert_statement()); + } ; ForStatement: T_FOR '(' ExprList ';' ExprList ';' ExprList ')' { @@ -1117,18 +1099,18 @@ ForStatement: T_FOR '(' ExprList ';' ExprList ';' ExprList ')' { CALL(@7, @7, iteration_end($3)); } | T_FOR '(' error ')' Statement - ; + ; WhileStatement: T_WHILE '(' { CALL(@1, @2, while_begin()); } ExprList ')' Statement { CALL(@3, @4, while_end()); - } + } | T_WHILE '(' error ')' Statement | T_DO { CALL(@1, @1, do_while_begin()); - } + } Statement T_WHILE '(' ExprList ')' ';' { CALL(@2, @7, do_while_end()); } @@ -1140,11 +1122,11 @@ SwitchCaseList: SwitchCase SwitchCase: T_CASE Expression ':' { - CALL(@1, @3, case_begin()); + CALL(@1, @3, case_begin()); } StatementList { CALL(@4, @4, case_end()); - } + } | T_DEFAULT ':' { CALL(@1, @2, default_begin()); } @@ -1161,32 +1143,32 @@ ExprList: Expression: T_FALSE { - CALL(@1, @1, expr_false()); + CALL(@1, @1, expr_false()); } | T_TRUE { - CALL(@1, @1, expr_true()); + CALL(@1, @1, expr_true()); } | T_NAT { - CALL(@1, @1, expr_nat($1)); + CALL(@1, @1, expr_nat($1)); } | T_FLOATING { - CALL(@1, @1, expr_double($1)); - } + CALL(@1, @1, expr_double($1)); + } | T_CHARARR { CALL(@1, @1, expr_string($1)); } | BuiltinFunction1 '(' Expression ')' { - CALL(@1, @4, expr_builtin_function1($1)); - } + CALL(@1, @4, expr_builtin_function1($1)); + } | BuiltinFunction2 '(' Expression ',' Expression ')' { - CALL(@1, @6, expr_builtin_function2($1)); - } + CALL(@1, @6, expr_builtin_function2($1)); + } | BuiltinFunction3 '(' Expression ',' Expression ',' Expression ')' { - CALL(@1, @8, expr_builtin_function3($1)); - } + CALL(@1, @8, expr_builtin_function3($1)); + } | NonTypeId { - CALL(@1, @1, expr_identifier($1)); + CALL(@1, @1, expr_identifier($1)); } | Expression '(' { CALL(@1, @2, expr_call_begin()); @@ -1221,8 +1203,8 @@ Expression: CALL(@1, @2, expr_pre_decrement()); } | T_MINUS T_POS_NEG_MAX { - CALL(@1, @2, expr_nat(std::numeric_limits::min())); - } + CALL(@1, @2, expr_nat(std::numeric_limits::min())); + } | UnaryOp Expression { CALL(@1, @2, expr_unary($1)); } %prec UOPERATOR @@ -1310,8 +1292,8 @@ Expression: CALL(@1, @3, expr_binary(OR)); } | Expression T_KW_XOR Expression { - CALL(@1, @3, expr_binary(XOR)); - } + CALL(@1, @3, expr_binary(XOR)); + } | Expression T_MIN Expression { CALL(@1, @3, expr_binary(MIN)); } @@ -1323,7 +1305,7 @@ Expression: } Expression { CALL(@1, @8, expr_sum_end($3)); } %prec T_SUM - | T_FORALL '(' Id ':' Type ')' { + | T_FORALL '(' Id ':' Type ')' { CALL(@1, @6, expr_forall_begin($3)); } Expression { CALL(@1, @8, expr_forall_end($3)); @@ -1333,48 +1315,48 @@ Expression: } Expression { CALL(@1, @8, expr_exists_end($3)); } %prec T_EXISTS - | DynamicExpression - | MITLExpression + | DynamicExpression + | MITLExpression | Assignment ; DynamicExpression: T_SPAWN NonTypeId { - CALL(@1,@2, expr_identifier($2)); - } '(' ArgList ')' { - CALL(@1,@6, expr_spawn($5)); - } + CALL(@1,@2, expr_identifier($2)); + } '(' ArgList ')' { + CALL(@1,@6, expr_spawn($5)); + } | T_EXIT '(' ')' { - CALL(@1,@3, expr_exit()); - } + CALL(@1,@3, expr_exit()); + } | T_NUMOF '(' NonTypeId ')'{ - CALL(@3,@3, expr_identifier($3)); - CALL(@1,@4, expr_numof()); - } + CALL(@3,@3, expr_identifier($3)); + CALL(@1,@4, expr_numof()); + } | T_FORALL '(' Id ':' NonTypeId { - CALL(@1,@5, expr_identifier($5)); - CALL(@1,@5, expr_forall_dynamic_begin($3,$5)); - } ')' '(' Expression ')' { - CALL(@1,@8, expr_forall_dynamic_end($3)); - } + CALL(@1,@5, expr_identifier($5)); + CALL(@1,@5, expr_forall_dynamic_begin($3,$5)); + } ')' '(' Expression ')' { + CALL(@1,@8, expr_forall_dynamic_end($3)); + } | T_EXISTS '(' Id ':' NonTypeId { - CALL(@1,@5, expr_identifier($5)); - CALL(@1,@5, expr_exists_dynamic_begin($3,$5)); - } ')' '(' Expression ')' { - CALL(@1,@8, expr_exists_dynamic_end($3)); - } + CALL(@1,@5, expr_identifier($5)); + CALL(@1,@5, expr_exists_dynamic_begin($3,$5)); + } ')' '(' Expression ')' { + CALL(@1,@8, expr_exists_dynamic_end($3)); + } | T_SUM '(' Id ':' NonTypeId { - CALL(@1,@5, expr_identifier($5)); - CALL(@1,@5, expr_sum_dynamic_begin($3,$5)); - } ')' Expression { - CALL(@1,@8, expr_sum_dynamic_end($3)); - } + CALL(@1,@5, expr_identifier($5)); + CALL(@1,@5, expr_sum_dynamic_begin($3,$5)); + } ')' Expression { + CALL(@1,@8, expr_sum_dynamic_end($3)); + } | T_FOREACH '(' Id ':' NonTypeId { - CALL(@1,@5, expr_identifier($5)); - CALL(@1,@5, expr_foreach_dynamic_begin($3,$5)); - } ')' Expression { - CALL(@1,@8, expr_foreach_dynamic_end($3)); - } + CALL(@1,@5, expr_identifier($5)); + CALL(@1,@5, expr_foreach_dynamic_begin($3,$5)); + } ')' Expression { + CALL(@1,@8, expr_foreach_dynamic_end($3)); + } ; @@ -1623,10 +1605,10 @@ OldStateDeclList: OldStateDecl: NonTypeId { - CALL(@1, @1, proc_location($1, false, false)); + CALL(@1, @1, proc_location($1, false, false)); } | NonTypeId '{' OldInvariant '}' { - CALL(@1, @4, proc_location($1, true, false)); + CALL(@1, @4, proc_location($1, true, false)); } ; @@ -1718,47 +1700,47 @@ PropertyList: PropertyList2: /* empty */ | PropertyList2 Property '\n' - ; + ; QueryList: /* empty */ - | QueryList Query - ; + | QueryList Query + ; Query: T_QUERY '{' Property '}' | T_QUERY '{' error '}' - ; + ; BoolOrKWAnd: T_KW_AND | T_BOOL_AND; SubProperty: T_AF Expression { - CALL(@1, @2, expr_unary(AF)); - } + CALL(@1, @2, expr_unary(AF)); + } | T_AG '(' Expression BoolOrKWAnd T_AF Expression ')' { CALL(@5, @6, expr_unary(AF)); CALL(@3, @6, expr_binary(AND)); CALL(@1, @7, expr_unary(AG)); } | T_AG Expression { - CALL(@1, @2, expr_unary(AG)); + CALL(@1, @2, expr_unary(AG)); } - | T_EF Expression { - CALL(@1, @2, expr_unary(EF)); + | T_EF Expression { + CALL(@1, @2, expr_unary(EF)); } - | T_EG Expression { - CALL(@1, @2, expr_unary(EG)); + | T_EG Expression { + CALL(@1, @2, expr_unary(EG)); } - | Expression T_LEADS_TO Expression { - CALL(@1, @3, expr_binary(LEADS_TO)); + | Expression T_LEADS_TO Expression { + CALL(@1, @3, expr_binary(LEADS_TO)); } - | 'A' '[' Expression 'U' Expression ']' { - CALL(@1, @6, expr_binary(A_UNTIL)); + | 'A' '[' Expression 'U' Expression ']' { + CALL(@1, @6, expr_binary(A_UNTIL)); } - | 'A' '[' Expression 'W' Expression ']' { - CALL(@1, @6, expr_binary(A_WEAK_UNTIL)); + | 'A' '[' Expression 'W' Expression ']' { + CALL(@1, @6, expr_binary(A_WEAK_UNTIL)); } ; @@ -1774,34 +1756,34 @@ AssignablePropperty: CALL(@1, @3, property()); } | T_CONTROL_T T_MULT '(' Expression ',' Expression ')' ':' SubProperty { - CALL(@1, @9, expr_ternary(CONTROL_TOPT)); - CALL(@1, @9, property()); + CALL(@1, @9, expr_ternary(CONTROL_TOPT)); + CALL(@1, @9, property()); } | T_CONTROL_T T_MULT '(' Expression ')' ':' SubProperty { - CALL(@1, @7, expr_binary(CONTROL_TOPT_DEF1)); - CALL(@1, @7, property()); + CALL(@1, @7, expr_binary(CONTROL_TOPT_DEF1)); + CALL(@1, @7, property()); } | T_CONTROL_T T_MULT ':' SubProperty { - CALL(@1, @4, expr_unary(CONTROL_TOPT_DEF2)); - CALL(@1, @4, property()); + CALL(@1, @4, expr_unary(CONTROL_TOPT_DEF2)); + CALL(@1, @4, property()); } | T_EF T_CONTROL ':' SubProperty Subjection { - CALL(@1, @4, expr_unary(EF_CONTROL)); - CALL(@1, @4, property()); + CALL(@1, @4, expr_unary(EF_CONTROL)); + CALL(@1, @4, property()); } | BracketExprList T_CONTROL ':' SubProperty Subjection { CALL(@1, @4, expr_binary(PO_CONTROL)); - CALL(@1, @4, property()); + CALL(@1, @4, property()); } | ExpQuantifier '(' Expression ')' '[' BoundType ']' Features ':' PathType Expression Subjection Imitation { CALL(@1, @12, expr_optimize_exp($1, ParserBuilder::EXPRPRICE, $10)); - CALL(@1, @9, property()); + CALL(@1, @9, property()); } | ExpPrQuantifier '[' BoundType ']' Features ':' PathType Expression Subjection Imitation { CALL(@1, @9, expr_optimize_exp($1, ParserBuilder::TIMEPRICE, $7)); - CALL(@1, @6, property()); + CALL(@1, @6, property()); } | T_LOAD_STRAT Features '(' Expression ')' { CALL(@1, @5, expr_load_strategy()); @@ -1818,7 +1800,7 @@ PropertyExpr: CALL(@1, @1, property()); } | T_PMAX Expression { // Deprecated, comes from old uppaal-prob. - CALL(@1, @2, expr_unary(PMAX)); + CALL(@1, @2, expr_unary(PMAX)); CALL(@1, @2, property()); } | AssignablePropperty @@ -1829,47 +1811,47 @@ PropertyExpr: CALL(@1, @3, property()); } | T_PROBA SMCBounds '(' PathType Expression ')' CmpGLE T_FLOATING Subjection { - CALL(@1, @9, expr_proba_qualitative($4, $7, $8)); + CALL(@1, @9, expr_proba_qualitative($4, $7, $8)); CALL(@1, @9, property()); } | T_PROBA SMCBounds '(' PathType Expression ')' Subjection { CALL(@6, @6, expr_true()); // push a trivial stop-predicate (see next rule) CALL(@1, @7, expr_proba_quantitative($4)); - CALL(@1, @7, property()); + CALL(@1, @7, property()); } | T_PROBA SMCBounds '(' Expression 'U' Expression ')' Subjection { CALL(@1, @8, expr_proba_quantitative(DIAMOND)); - CALL(@1, @8, property()); + CALL(@1, @8, property()); } | T_PROBA SMCBounds '(' PathType Expression ')' T_GEQ T_PROBA SMCBounds '(' PathType Expression ')' Subjection { - CALL(@1, @14, expr_proba_compare($4, $11)); - CALL(@1, @14, property()); + CALL(@1, @14, expr_proba_compare($4, $11)); + CALL(@1, @14, property()); } | T_PROBA SMCBounds '(' PathType Expression ')' T_SUBJECT SubjectionList T_GEQ T_PROBA SMCBounds '(' PathType Expression ')' Subjection { - CALL(@1, @16, expr_proba_compare($4, $13)); - CALL(@1, @16, property()); + CALL(@1, @16, expr_proba_compare($4, $13)); + CALL(@1, @16, property()); }//T_SUBJECT SubjectionList | T_SIMULATE SMCBounds '{' NonEmptyExpressionList '}' Subjection { CALL(@1, @6, expr_simulate($4)); CALL(@1, @6, property()); } | T_SIMULATE SMCBounds '{' NonEmptyExpressionList '}' ':' Expression Subjection { - CALL(@1, @8, expr_simulate($4, true)); - CALL(@1, @8, property()); + CALL(@1, @8, expr_simulate($4, true)); + CALL(@1, @8, property()); } | T_SIMULATE SMCBounds '{' NonEmptyExpressionList '}' ':' T_NAT ':' Expression Subjection { CALL(@1, @10, expr_simulate($4, true, $7)); - CALL(@1, @10, property()); + CALL(@1, @10, property()); } | 'E' SMCBounds '(' Id ':' Expression ')' Subjection { CALL(@1, @8, expr_proba_expected($4)); - CALL(@1, @8, property()); + CALL(@1, @8, property()); } | T_PROBA Expression Subjection { - CALL(@1, @3, expr_MITL_formula()); - CALL(@1, @3, property()); + CALL(@1, @3, expr_MITL_formula()); + CALL(@1, @3, property()); } | T_SAVE_STRAT '(' Expression ',' Id ')' { CALL(@1, @6, subjection($5)); @@ -1880,7 +1862,7 @@ PropertyExpr: MITLExpression : '(' Expression 'U' '[' T_NAT ',' T_NAT ']' Expression ')' { - CALL(@1,@10, expr_MITL_until($5,$7)); + CALL(@1,@10, expr_MITL_until($5,$7)); } | '(' Expression 'R' '[' T_NAT ',' T_NAT ']' Expression ')' { CALL(@1,@10, expr_MITL_release($5,$7)); @@ -1889,7 +1871,7 @@ MITLExpression : CALL(@1,@4, expr_MITL_next()); } | '(' T_DIAMOND '[' T_NAT ',' T_NAT ']' Expression ')' { - CALL(@1,@4, expr_MITL_diamond($4,$6)); + CALL(@1,@4, expr_MITL_diamond($4,$6)); } | '(' T_BOX '[' T_NAT ',' T_NAT ']' Expression ')' { CALL(@1,@4, expr_MITL_box($4,$6)); @@ -1898,10 +1880,10 @@ MITLExpression : SMCBounds: '[' BoundType ']' { - CALL(@1, @1, expr_nat(-1)); + CALL(@1, @1, expr_nat(-1)); } | '[' BoundType ';' T_NAT ']' { - CALL(@1, @3, expr_nat($4)); + CALL(@1, @3, expr_nat($4)); }; BoundType: @@ -1916,21 +1898,21 @@ CmpGLE: ; PathType: - T_BOX { $$ = BOX; } - | T_DIAMOND { $$ = DIAMOND; } - ; + T_BOX { $$ = BOX; } + | T_DIAMOND { $$ = DIAMOND; } + ; BracketExprList: - '{' ExpressionList '}' { - CALL(@1, @3, expr_nary(LIST,$2)); - }; + '{' ExpressionList '}' { + CALL(@1, @3, expr_nary(LIST,$2)); + }; /* There is an ExprList but it's not a list, rather * a binary tree built with commas. */ ExpressionList: - /* nothing */ { $$ = 0; } + /* nothing */ { $$ = 0; } | NonEmptyExpressionList ; @@ -1941,24 +1923,24 @@ NonEmptyExpressionList: SupPrefix: T_SUP ':' { - CALL(@1, @2, expr_true()); - } - | T_SUP '{' Expression '}' ':' - ; + CALL(@1, @2, expr_true()); + } + | T_SUP '{' Expression '}' ':' + ; InfPrefix: - T_INF ':' { - CALL(@1, @2, expr_true()); - } - | T_INF '{' Expression '}' ':' - ; + T_INF ':' { + CALL(@1, @2, expr_true()); + } + | T_INF '{' Expression '}' ':' + ; BoundsPrefix: - T_BOUNDS ':' { - CALL(@1, @2, expr_true()); - } - | T_BOUNDS '{' Expression '}' ':' - ; + T_BOUNDS ':' { + CALL(@1, @2, expr_true()); + } + | T_BOUNDS '{' Expression '}' ':' + ; StrategyAssignment: @@ -1967,27 +1949,29 @@ StrategyAssignment: }; Property: - /* empty */ + /* empty */ | StrategyAssignment | PropertyExpr - | SupPrefix NonEmptyExpressionList Subjection { - CALL(@1, @2, expr_nary(LIST,$2)); - CALL(@1, @2, expr_binary(SUP_VAR)); - CALL(@1, @2, property()); - } - | InfPrefix NonEmptyExpressionList Subjection { - CALL(@1, @2, expr_nary(LIST,$2)); - CALL(@1, @2, expr_binary(INF_VAR)); - CALL(@1, @2, property()); - } - | BoundsPrefix NonEmptyExpressionList Subjection { - CALL(@1, @2, expr_nary(LIST,$2)); - CALL(@1, @2, expr_binary(BOUNDS_VAR)); - CALL(@1, @2, property()); - }; + | SupPrefix NonEmptyExpressionList Subjection { + CALL(@1, @2, expr_nary(LIST,$2)); + CALL(@1, @2, expr_binary(SUP_VAR)); + CALL(@1, @2, property()); + } + | InfPrefix NonEmptyExpressionList Subjection { + CALL(@1, @2, expr_nary(LIST,$2)); + CALL(@1, @2, expr_binary(INF_VAR)); + CALL(@1, @2, property()); + } + | BoundsPrefix NonEmptyExpressionList Subjection { + CALL(@1, @2, expr_nary(LIST,$2)); + CALL(@1, @2, expr_binary(BOUNDS_VAR)); + CALL(@1, @2, property()); + }; %% +// NOLINTEND + #include "lexer.cc" static void utap_error(const char* msg) @@ -2022,8 +2006,8 @@ static void setStartToken(xta_part_t part, bool newxta) syntax_token = newxta ? T_NEW_INVARIANT : T_OLD_INVARIANT; break; case S_EXPONENTIAL_RATE: - syntax_token = T_EXPONENTIAL_RATE; - break; + syntax_token = T_EXPONENTIAL_RATE; + break; case S_SELECT: syntax_token = T_NEW_SELECT; break; @@ -2068,7 +2052,7 @@ static void setStartToken(xta_part_t part, bool newxta) } static int32_t parse_XTA(ParserBuilder *aParserBuilder, - bool newxta, xta_part_t part, std::string xpath) + bool newxta, xta_part_t part, const std::string& xpath) { // Select syntax syntax = newxta ? syntax_t::NEW_GUIDING : syntax_t::OLD_GUIDING; @@ -2083,12 +2067,10 @@ static int32_t parse_XTA(ParserBuilder *aParserBuilder, // Parse string int res = 0; - if (utap_parse()) - { + if (utap_parse() != 0) res = -1; - } - ch = NULL; + ch = nullptr; return res; } @@ -2104,11 +2086,11 @@ static int32_t parseProperty(ParserBuilder *aParserBuilder, const std::string& x // Reset position tracking tracker.setPath(ch, xpath); - return utap_parse() ? -1 : 0; + return (utap_parse() != 0) ? -1 : 0; } int32_t parse_XTA(const char *str, ParserBuilder *builder, - bool newxta, xta_part_t part, std::string xpath) + bool newxta, xta_part_t part, const std::string& xpath) { utap__scan_string(str); int32_t res = parse_XTA(builder, newxta, part, xpath); diff --git a/src/position.cpp b/src/position.cpp index a9e5bdd1..e9821c32 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -26,7 +26,6 @@ #include using std::string; -using std::vector; using namespace UTAP; diff --git a/src/prettyprinter.cpp b/src/prettyprinter.cpp index 20f4cc05..23faae5b 100644 --- a/src/prettyprinter.cpp +++ b/src/prettyprinter.cpp @@ -195,7 +195,7 @@ void PrettyPrinter::decl_init_list(uint32_t num) { string s = st.back(); st.pop_back(); - while (--num) { + while (--num > 0) { s = st.back() + ", " + s; st.pop_back(); } @@ -219,7 +219,7 @@ void PrettyPrinter::expr_nary(kind_t kind, uint32_t num) string s = st.back(); st.pop_back(); - while (--num) { + while (--num > 0) { s = st.back() + opString + s; st.pop_back(); } @@ -228,7 +228,7 @@ void PrettyPrinter::expr_nary(kind_t kind, uint32_t num) void PrettyPrinter::decl_field_init(const char* name) { - if (name && strlen(name)) { + if (name != nullptr && strlen(name) > 0) { st.back() = string(name) + ": " + st.back(); } } @@ -322,7 +322,7 @@ void PrettyPrinter::for_end() // 3 expr, 1 stat st.pop_back(); string expr1 = st.back(); st.pop_back(); - ostringstream* s = (ostringstream*)o.top(); + auto* s = static_cast(o.top()); o.pop(); level--; @@ -334,14 +334,14 @@ void PrettyPrinter::for_end() // 3 expr, 1 stat void PrettyPrinter::while_begin() { level++; - o.push(new ostringstream()); + o.push(new ostringstream{}); } void PrettyPrinter::while_end() // 1 expr, 1 stat { string expr = st.back(); st.pop_back(); - ostringstream* s = (ostringstream*)o.top(); + auto* s = static_cast(o.top()); o.pop(); level--; @@ -370,9 +370,9 @@ void PrettyPrinter::if_then() void PrettyPrinter::if_end(bool hasElse) // 1 expr, 1 or 2 statements { - auto e = static_cast(o.top()); + auto* e = static_cast(o.top()); o.pop(); // ELSE - auto t = static_cast(o.top()); + auto* t = static_cast(o.top()); o.pop(); // THEN auto c = st.back(); st.pop_back(); // COND @@ -421,7 +421,7 @@ void PrettyPrinter::return_statement(bool hasValue) void PrettyPrinter::proc_begin(const char* id, const bool isTA, const string& type, const string& mode) { - *o.top() << "process " << (id ? id : "") << templateset << '(' << param << ")" << endl << "{" << endl; + *o.top() << "process " << ((id != nullptr) ? id : "") << templateset << '(' << param << ")" << endl << "{" << endl; param.clear(); templateset = ""; @@ -626,7 +626,7 @@ void PrettyPrinter::proc_end() *o.top() << '}' << endl << endl; } -void PrettyPrinter::expr_identifier(const char* id) { st.push_back(id); } +void PrettyPrinter::expr_identifier(const char* id) { st.emplace_back(id); } void PrettyPrinter::expr_nat(int32_t n) { @@ -634,12 +634,12 @@ void PrettyPrinter::expr_nat(int32_t n) if (20 <= snprintf(s, 20, "%d", n)) { fprintf(stderr, "Error: the integer number was truncated\n"); } - st.push_back(s); + st.emplace_back(s); } -void PrettyPrinter::expr_true() { st.push_back("true"); } +void PrettyPrinter::expr_true() { st.emplace_back("true"); } -void PrettyPrinter::expr_false() { st.push_back("false"); } +void PrettyPrinter::expr_false() { st.emplace_back("false"); } void PrettyPrinter::expr_double(double d) { @@ -662,7 +662,7 @@ void PrettyPrinter::expr_call_begin() { st.back() += "("; } void PrettyPrinter::expr_call_end(uint32_t n) { string s = ")"; - while (n--) { + while (n-- > 0) { s = st.back() + s; st.pop_back(); if (n > 0) { @@ -785,7 +785,7 @@ void PrettyPrinter::expr_assignment(kind_t op) string lhs = st.back(); st.pop_back(); - st.push_back(string()); + st.emplace_back(); switch (op) { case ASSIGN: st.back() = '(' + lhs + " = " + rhs + ')'; break; case ASS_PLUS: st.back() = '(' + lhs + " += " + rhs + ')'; break; @@ -807,7 +807,7 @@ void PrettyPrinter::expr_unary(kind_t op) string exp = st.back(); st.pop_back(); - st.push_back(string()); + st.emplace_back(); switch (op) { case MINUS: st.back() = '-' + exp; break; case NOT: st.back() = '!' + exp; break; @@ -827,7 +827,7 @@ void PrettyPrinter::expr_binary(kind_t op) string exp1 = st.back(); st.pop_back(); - st.push_back(string()); + st.emplace_back(); switch (op) { case PO_CONTROL: st.back() = exp1 + " control: " + exp2; break; case CONTROL_TOPT_DEF1: st.back() = "control_t*(" + exp1 + "): " + exp2; break; @@ -871,7 +871,7 @@ void PrettyPrinter::expr_ternary(kind_t op, bool firstMissing) st.pop_back(); } - st.push_back(string()); + st.emplace_back(); switch (op) { case CONTROL_TOPT: st.back() = "control_t*(" + exp1 + "," + exp2 + "): " + exp3; break; case SMC_CONTROL: st.back() = "control[" + exp1 + "<=" + exp2 + "]: " + exp3; break; @@ -888,7 +888,7 @@ void PrettyPrinter::expr_inline_if() string expr1 = st.back(); st.pop_back(); - st.push_back(string()); + st.emplace_back(); st.back() = expr1 + " ? " + expr2 + " : " + expr3; } @@ -899,7 +899,7 @@ void PrettyPrinter::expr_comma() string expr1 = st.back(); st.pop_back(); - st.push_back(string()); + st.emplace_back(); st.back() = expr1 + ", " + expr2; } @@ -907,7 +907,7 @@ void PrettyPrinter::expr_dot(const char* field) { st.back() = st.back() + "." + void PrettyPrinter::expr_location() { st.back() = st.back() + ".location"; } -void PrettyPrinter::expr_deadlock() { st.push_back("deadlock"); } +void PrettyPrinter::expr_deadlock() { st.emplace_back("deadlock"); } void PrettyPrinter::expr_forall_begin(const char* name) { @@ -976,7 +976,7 @@ void PrettyPrinter::instantiation_begin(const char* id, size_t, const char* temp void PrettyPrinter::instantiation_end(const char* id, size_t parameters, const char* templ, size_t arguments) { stack s; - while (arguments--) { + while (arguments-- > 0) { s.push(st.back()); st.pop_back(); } @@ -1117,12 +1117,12 @@ void PrettyPrinter::expr_simulate(int nbExpr, bool hasReach, int nbOfAcceptingRu void PrettyPrinter::query_begin() { *o.top() << "\n/** Query begin: */" << endl; } void PrettyPrinter::query_formula(const char* formula, const char* location) { - if (formula) + if (formula != nullptr) *o.top() << "/* Formula: " << formula << " */" << endl; } void PrettyPrinter::query_comment(const char* comment) { - if (comment) + if (comment != nullptr) *o.top() << "/* Comment: " << comment << " */" << endl; } void PrettyPrinter::query_end() { *o.top() << "/** Query end. */" << endl; } diff --git a/src/print.hpp b/src/print.hpp new file mode 100644 index 00000000..c46bfc73 --- /dev/null +++ b/src/print.hpp @@ -0,0 +1,88 @@ +// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*- +/////////////////////////////////////////////////////////////////////////////// +// +// This file is a part of UPPAAL. +// Copyright (c) 2023, Aalborg University. +// All right reserved. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_FORMATS_PRINT_HPP +#define INCLUDE_FORMATS_PRINT_HPP + +/** Idiomatic printing utilities. + * Avoid including it into headers as it includes , which slows down the builds. + * Instead, declare printing functions in headers with , and then implement them in cpp with . + * */ + +#include +#include + +/** Print delimiter-separated elements. + * @tparam View the type of element view, can be array, std container, etc. + * @param os the output stream + * @param view the view over the elements + * @param delim the delimeter to be put in between the elements into the output stream. + * @return the same output stream reference after printing + * */ +template +std::ostream& print_infix(std::ostream& os, const View& view, std::string_view delim = ",") +{ + auto b = std::begin(view), e = std::end(view); + if (b != e) { + os << *b; + while (++b != e) + os << delim << *b; + } + return os; +} + +/** Print delimiter-separated elements through custom element printer. + * @tparam View the type of element view, can be array, std container, etc. + * @tparam Print the print function type taking the output stream and the element in the view. + * @param os the output stream + * @param view the view over the elements + * @param print the custom print function + * @param delim the delimeter to be put in between the elements into the output stream. + * @return the same output stream reference after printing + * */ +template +std::ostream& print_infix_p(std::ostream& os, const View& view, Print&& print, std::string_view delim = ",") +{ + auto b = std::begin(view), e = std::end(view); + using E = typename std::iterator_traits::value_type; + static_assert(std::is_invocable_v, "print should accept istream and range element"); + if (b != e) { + print(os, *b); + while (++b != e) + print(os << delim, *b); + } + return os; +} + +/** Helper for infix printing into stream with infix separators. + * For example, print "1,2,3": std::cout << infix{{1,2,3}}; + * @tparam View the view over some printable elements, can be array, container, etc. + * */ +template +struct infix +{ + const View& view; + std::string_view sep; + infix(const View& view, std::string_view sep = ","): view{view}, sep{sep} {} + friend std::ostream& operator<<(std::ostream& os, const infix& f) { return print_infix(os, f.view, f.sep); } +}; + +template +infix(T&&) -> infix; + +template +infix(View&&, std::string_view) -> infix; + +template +infix(const std::initializer_list&) -> infix>; + +template +infix(const std::initializer_list&, std::string_view) -> infix>; + +#endif // INCLUDE_FORMATS_PRINT_HPP diff --git a/src/property.cpp b/src/property.cpp index 6f174190..0ffedced 100644 --- a/src/property.cpp +++ b/src/property.cpp @@ -38,7 +38,7 @@ using std::istringstream; using std::list; using std::string; -void PropertyBuilder::typeCheck(expression_t expr) { tc.visitProperty(std::move(expr)); } +void PropertyBuilder::typeCheck(expression_t& expr) { tc.visitProperty(expr); } void PropertyBuilder::clear() { properties.clear(); } diff --git a/src/symbols.cpp b/src/symbols.cpp index c6b123c3..73013fd2 100644 --- a/src/symbols.cpp +++ b/src/symbols.cpp @@ -74,7 +74,7 @@ frame_t symbol_t::get_frame() { return frame_t(data->frame); } /* Returns the type of this symbol. */ type_t symbol_t::get_type() const { return data->type; } -void symbol_t::set_type(type_t type) { data->type = type; } +void symbol_t::set_type(type_t type) { data->type = std::move(type); } position_t symbol_t::get_position() const { return data->position; } @@ -135,7 +135,7 @@ frame_t::iterator frame_t::end() { return std::end(data->symbols); } /* Adds a symbol of the given name and type to the frame */ symbol_t frame_t::add_symbol(const string& name, type_t type, position_t position, void* user) { - auto symbol = symbol_t{this, type, name, position, user}; + auto symbol = symbol_t{this, std::move(type), name, position, user}; data->symbols.push_back(symbol); if (!name.empty()) { data->mapping[symbol.get_name()] = data->symbols.size() - 1; @@ -149,9 +149,10 @@ symbol_t frame_t::add_symbol(const string& name, type_t type, position_t positio */ void frame_t::add(symbol_t symbol) { - data->symbols.push_back(symbol); - if (!symbol.get_name().empty()) { - data->mapping[symbol.get_name()] = data->symbols.size() - 1; + data->symbols.push_back(std::move(symbol)); + const auto& s = data->symbols.back(); + if (!s.get_name().empty()) { + data->mapping[s.get_name()] = data->symbols.size() - 1; } } @@ -159,9 +160,9 @@ void frame_t::add(symbol_t symbol) be in two frames at the same time, but the symbol will only "point back" to the first frame it was added to. */ -void frame_t::add(frame_t frame) +void frame_t::add(const frame_t& frame) { - for (auto& symbol : frame) + for (const auto& symbol : frame) add(symbol); } @@ -171,8 +172,7 @@ void frame_t::add(frame_t frame) */ void frame_t::move_to(frame_t frame) { - for (uint32_t i = 0; i < data->symbols.size(); i++) { - symbol_t symbol = data->symbols[i]; + for (const auto& symbol : data->symbols) { frame.add(symbol); symbol.data->frame = frame.data.get(); } @@ -181,13 +181,12 @@ void frame_t::move_to(frame_t frame) } /** removes the given symbol*/ -void frame_t::remove(symbol_t s) +void frame_t::remove(const symbol_t& s) { vector symbols = data->symbols; data->symbols.clear(); data->mapping.clear(); - for (uint32_t i = 0; i < symbols.size(); i++) { - symbol_t symbol = symbols[i]; + for (const auto& symbol : symbols) { if (symbol != s) { add(symbol); symbol.data->frame = data.get(); diff --git a/src/type.cpp b/src/type.cpp index def9be47..e7edae52 100644 --- a/src/type.cpp +++ b/src/type.cpp @@ -274,7 +274,7 @@ type_t type_t::rename(const std::string& from, const std::string& to) const return type; } -type_t type_t::subst(symbol_t symbol, expression_t expr) const +type_t type_t::subst(const symbol_t& symbol, const expression_t& expr) const { auto type = type_t{get_kind(), get_position(), size()}; for (size_t i = 0; i < size(); i++) { @@ -321,7 +321,7 @@ bool type_t::is_mutable() const } } -type_t type_t::create_range(type_t type, expression_t lower, expression_t upper, position_t pos) +type_t type_t::create_range(type_t type, const expression_t& lower, const expression_t& upper, position_t pos) { auto t = type_t{RANGE, pos, 3}; t.data->children[0].child = std::move(type); @@ -348,7 +348,7 @@ type_t type_t::create_function(type_t ret, const std::vector& parameters { assert(parameters.size() == labels.size()); auto type = type_t{FUNCTION, pos, parameters.size() + 1}; - type.data->children[0].child = ret; + type.data->children[0].child = std::move(ret); for (size_t i = 0; i < parameters.size(); i++) { type.data->children[i + 1].child = parameters[i]; type.data->children[i + 1].label = labels[i]; @@ -361,7 +361,7 @@ type_t type_t::create_external_function(type_t ret, const std::vector& p { assert(parameters.size() == labels.size()); auto type = type_t{FUNCTION_EXTERNAL, pos, parameters.size() + 1}; - type.data->children[0].child = ret; + type.data->children[0].child = std::move(ret); for (size_t i = 0; i < parameters.size(); i++) { type.data->children[i + 1].child = parameters[i]; type.data->children[i + 1].label = labels[i]; @@ -372,16 +372,16 @@ type_t type_t::create_external_function(type_t ret, const std::vector& p type_t type_t::create_array(type_t sub, type_t size, position_t pos) { auto type = type_t{ARRAY, pos, 2}; - type.data->children[0].child = sub; - type.data->children[1].child = size; + type.data->children[0].child = std::move(sub); + type.data->children[1].child = std::move(size); return type; } type_t type_t::create_typedef(std::string label, type_t type, position_t pos) { auto t = type_t{TYPEDEF, pos, 1}; - t.data->children[0].label = label; - t.data->children[0].child = type; + t.data->children[0].label = std::move(label); + t.data->children[0].child = std::move(type); return t; } @@ -415,7 +415,7 @@ type_t type_t::create_process(frame_t frame, position_t pos) return type; } -type_t type_t::create_process_set(type_t instance, position_t pos) +type_t type_t::create_process_set(const type_t& instance, position_t pos) { auto type = type_t{PROCESS_SET, pos, instance.size()}; for (size_t i = 0; i < instance.size(); ++i) { @@ -438,7 +438,7 @@ type_t type_t::create_label(string label, position_t pos) const { type_t type(LABEL, pos, 1); type.data->children[0].child = *this; - type.data->children[0].label = label; + type.data->children[0].label = std::move(label); return type; } diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 6897c7d5..6db4b248 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -33,11 +33,11 @@ using namespace Constants; /* The following are simple helper functions for testing the type of * expressions. */ -static bool isCost(expression_t expr) { return expr.get_type().is(COST); } +static bool isCost(const expression_t& expr) { return expr.get_type().is(COST); } -static bool is_void(expression_t expr) { return expr.get_type().is_void(); } +static bool is_void(const expression_t& expr) { return expr.get_type().is_void(); } -static bool is_double(expression_t expr) { return expr.get_type().is_double(); } +static bool is_double(const expression_t& expr) { return expr.get_type().is_double(); } /* static bool is_string(expression_t expr) @@ -50,35 +50,35 @@ static bool is_string(expression_t expr) // return expr.get_type().is_scalar(); // } -static bool is_integer(expression_t expr) { return expr.get_type().is_integer(); } +static bool is_integer(const expression_t& expr) { return expr.get_type().is_integer(); } -static bool isBound(expression_t expr) { return expr.get_type().is_integer() || expr.get_type().is_double(); } +static bool isBound(const expression_t& expr) { return expr.get_type().is_integer() || expr.get_type().is_double(); } -static bool is_integral(expression_t expr) { return expr.get_type().is_integral(); } +static bool is_integral(const expression_t& expr) { return expr.get_type().is_integral(); } -static bool is_clock(expression_t expr) { return expr.get_type().is_clock(); } +static bool is_clock(const expression_t& expr) { return expr.get_type().is_clock(); } -static bool is_diff(expression_t expr) { return expr.get_type().is_diff(); } +static bool is_diff(const expression_t& expr) { return expr.get_type().is_diff(); } -static bool is_double_value(expression_t expr) { return is_double(expr) || is_clock(expr) || is_diff(expr); } +static bool is_double_value(const expression_t& expr) { return is_double(expr) || is_clock(expr) || is_diff(expr); } -static bool is_number(expression_t expr) { return is_double_value(expr) || is_integral(expr); } +static bool is_number(const expression_t& expr) { return is_double_value(expr) || is_integral(expr); } -static bool is_const_integer(expression_t expr) { return expr.get_kind() == CONSTANT && is_integer(expr); } +static bool is_const_integer(const expression_t& expr) { return expr.get_kind() == CONSTANT && is_integer(expr); } -static bool is_const_double(expression_t expr) { return expr.get_kind() == CONSTANT && is_double(expr); } +static bool is_const_double(const expression_t& expr) { return expr.get_kind() == CONSTANT && is_double(expr); } -static bool is_invariant(expression_t expr) { return expr.get_type().is_invariant(); } +static bool is_invariant(const expression_t& expr) { return expr.get_type().is_invariant(); } -static bool is_guard(expression_t expr) { return expr.get_type().is_guard(); } +static bool is_guard(const expression_t& expr) { return expr.get_type().is_guard(); } -static bool is_probability(expression_t expr) { return expr.get_type().is_probability(); } +static bool is_probability(const expression_t& expr) { return expr.get_type().is_probability(); } -static bool is_constraint(expression_t expr) { return expr.get_type().is_constraint(); } +static bool is_constraint(const expression_t& expr) { return expr.get_type().is_constraint(); } -static bool is_formula(expression_t expr) { return expr.get_type().is_formula(); } +static bool is_formula(const expression_t& expr) { return expr.get_type().is_formula(); } -static bool is_formula_list(expression_t expr) +static bool is_formula_list(const expression_t& expr) { if (expr.get_kind() != LIST) { return false; @@ -93,7 +93,7 @@ static bool is_formula_list(expression_t expr) return true; } -static bool hasStrictLowerBound(expression_t expr) +static bool hasStrictLowerBound(const expression_t& expr) { for (size_t i = 0; i < expr.get_size(); ++i) { if (hasStrictLowerBound(expr[i])) { @@ -119,7 +119,7 @@ static bool hasStrictLowerBound(expression_t expr) return false; } -static bool hasStrictUpperBound(expression_t expr) +static bool hasStrictUpperBound(const expression_t& expr) { for (size_t i = 0; i < expr.get_size(); ++i) { if (hasStrictUpperBound(expr[i])) { @@ -149,14 +149,14 @@ static bool hasStrictUpperBound(expression_t expr) * Returns true iff type is a valid invariant. A valid invariant is * either an invariant expression or an integer expression. */ -static bool isInvariantWR(expression_t expr) { return is_invariant(expr) || (expr.get_type().is(INVARIANT_WR)); } +static bool isInvariantWR(const expression_t& expr) { return is_invariant(expr) || (expr.get_type().is(INVARIANT_WR)); } /** * Returns true if values of this type can be assigned. This is the * case for integers, booleans, clocks, cost, scalars and arrays and * records of these. E.g. channels and processes are not assignable. */ -static bool isAssignable(type_t type) +static bool isAssignable(const type_t& type) { switch (type.get_kind()) { case Constants::INT: @@ -200,9 +200,9 @@ void CompileTimeComputableValues::visitInstance(instance_t& temp) } } -void CompileTimeComputableValues::add_symbol(symbol_t symbol) { variables.insert(symbol); } +void CompileTimeComputableValues::add_symbol(symbol_t symbol) { variables.insert(std::move(symbol)); } -bool CompileTimeComputableValues::contains(symbol_t symbol) const +bool CompileTimeComputableValues::contains(const symbol_t& symbol) const { return (variables.find(symbol) != variables.end()); } @@ -218,10 +218,10 @@ class RateDecomposer bool hasStrictInvariant{false}, hasClockRates{false}; size_t countCostRates{0}; - void decompose(expression_t, bool inforall = false); + void decompose(const expression_t&, bool inforall = false); }; -void RateDecomposer::decompose(expression_t expr, bool inforall) +void RateDecomposer::decompose(const expression_t& expr, bool inforall) { assert(isInvariantWR(expr)); @@ -289,13 +289,13 @@ TypeChecker::TypeChecker(Document& document, bool refinement): document{document } template -void TypeChecker::handleWarning(T expr, const std::string& msg) +void TypeChecker::handleWarning(T expr, const std::string& msg) const { document.add_warning(expr.get_position(), msg, "(typechecking)"); } template -void TypeChecker::handleError(T expr, const std::string& msg) +void TypeChecker::handleError(T expr, const std::string& msg) const { document.add_error(expr.get_position(), msg, "(typechecking)"); } @@ -310,7 +310,7 @@ void TypeChecker::handleError(T expr, const std::string& msg) * this function accepts modifications of local variables as a * side-effect. */ -void TypeChecker::checkIgnoredValue(expression_t expr) +void TypeChecker::checkIgnoredValue(const expression_t& expr) const { if (!expr.changes_any_variable()) { handleWarning(expr, "$Expression_does_not_have_any_effect"); @@ -319,7 +319,7 @@ void TypeChecker::checkIgnoredValue(expression_t expr) } } -bool TypeChecker::isCompileTimeComputable(expression_t expr) const +bool TypeChecker::isCompileTimeComputable(const expression_t& expr) const { /* An expression is compile time computable if all identifers it * could possibly access during an evaluation are compile time @@ -351,7 +351,7 @@ bool TypeChecker::isCompileTimeComputable(expression_t expr) const * If \a initialisable is true, then this method also checks that \a * type is initialisable. */ -void TypeChecker::checkType(type_t type, bool initialisable, bool inStruct) +void TypeChecker::checkType(const type_t& type, bool initialisable, bool inStruct) const { expression_t l, u; type_t size; @@ -466,7 +466,7 @@ void TypeChecker::checkType(type_t type, bool initialisable, bool inStruct) void TypeChecker::visitDocAfter(Document& doc) { - for (const chan_priority_t& i : doc.get_chan_priorities()) { + for (chan_priority_t& i : doc.get_chan_priorities()) { bool i_default = (i.head == expression_t()); if (!i_default && checkExpression(i.head)) { expression_t expr = i.head; @@ -491,7 +491,7 @@ void TypeChecker::visitDocAfter(Document& doc) } } - for (const chan_priority_t::entry& j : i.tail) { + for (chan_priority_t::entry& j : i.tail) { bool j_default = (j.second == expression_t()); if (!j_default && checkExpression(j.second)) { expression_t expr = j.second; @@ -519,7 +519,7 @@ void TypeChecker::visitDocAfter(Document& doc) } } -void TypeChecker::visitHybridClock(expression_t e) +void TypeChecker::visitHybridClock(expression_t& e) { if (checkExpression(e)) { if (!is_clock(e)) { @@ -534,7 +534,7 @@ void TypeChecker::visitHybridClock(expression_t e) void TypeChecker::visitIODecl(iodecl_t& iodecl) { - for (const auto& e : iodecl.param) { + for (auto& e : iodecl.param) { if (checkExpression(e)) { if (!is_integer(e)) { handleError(e, "$Integer_expected"); @@ -617,7 +617,7 @@ void TypeChecker::visitIODecl(iodecl_t& iodecl) } } -bool isDefaultInt(type_t type) +bool isDefaultInt(const type_t& type) { if (type.is_integral()) { auto range = type.get_range(); @@ -696,7 +696,7 @@ void TypeChecker::visitLocation(location_t& loc) } } if (!loc.exp_rate.empty()) { - const auto& expr = loc.exp_rate; + auto& expr = loc.exp_rate; if (checkExpression(expr)) { if (!is_integral(expr) && expr.get_kind() != FRACTION && !expr.get_type().is_double()) { handleError(expr, "$Number_expected"); @@ -918,29 +918,22 @@ void TypeChecker::visitProgressMeasure(progress_t& progress) void TypeChecker::visitGanttChart(gantt_t& gc) { - size_t n = gc.parameters.get_size(); - for (size_t i = 0; i < n; ++i) { - checkType(gc.parameters[i].get_type()); - } + for (auto& p : gc.parameters) + checkType(p.get_type()); - std::list::const_iterator first, end = gc.mapping.end(); - for (first = gc.mapping.begin(); first != end; ++first) { - n = (*first).parameters.get_size(); - for (size_t i = 0; i < n; ++i) { - checkType((*first).parameters[i].get_type()); - } + for (auto& gm : gc.mapping) { + for (auto& p : gm.parameters) + checkType(p.get_type()); - const expression_t& p = (*first).predicate; + expression_t& p = gm.predicate; checkExpression(p); - if (!is_integral(p) && !is_constraint(p)) { + if (!is_integral(p) && !is_constraint(p)) handleError(p, "$Boolean_expected"); - } - const expression_t& m = (*first).mapping; + expression_t& m = gm.mapping; checkExpression(m); - if (!is_integral(m)) { + if (!is_integral(m)) handleError(m, "$Integer_expected"); - } } } @@ -990,7 +983,7 @@ void TypeChecker::visitInstance(instance_t& instance) } } -static bool isGameProperty(expression_t expr) +static bool isGameProperty(const expression_t& expr) { switch (expr.get_kind()) { case CONTROL: @@ -1004,7 +997,7 @@ static bool isGameProperty(expression_t expr) } } -static bool hasMITLInQuantifiedSub(expression_t expr) +static bool hasMITLInQuantifiedSub(const expression_t& expr) { bool hasIt = (expr.get_kind() == MITL_FORALL || expr.get_kind() == MITL_EXISTS); if (!hasIt) { @@ -1015,7 +1008,7 @@ static bool hasMITLInQuantifiedSub(expression_t expr) return hasIt; } -static bool hasSpawnOrExit(expression_t expr) +static bool hasSpawnOrExit(const expression_t& expr) { bool hasIt = (expr.get_kind() == SPAWN || expr.get_kind() == EXIT); if (!hasIt) { @@ -1026,7 +1019,7 @@ static bool hasSpawnOrExit(expression_t expr) return hasIt; } -void TypeChecker::visitProperty(expression_t expr) +void TypeChecker::visitProperty(expression_t& expr) { if (checkExpression(expr)) { if (expr.changes_any_variable()) { @@ -1099,7 +1092,7 @@ void TypeChecker::visitProperty(expression_t expr) * * - expression in the label field of an update (LSC) */ -bool TypeChecker::checkAssignmentExpression(expression_t expr) +bool TypeChecker::checkAssignmentExpression(expression_t& expr) { if (!checkExpression(expr)) { return false; @@ -1118,7 +1111,7 @@ bool TypeChecker::checkAssignmentExpression(expression_t expr) } /** Checks that the expression can be used as a condition (e.g. for if). */ -bool TypeChecker::checkConditionalExpressionInFunction(expression_t expr) +bool TypeChecker::checkConditionalExpressionInFunction(const expression_t& expr) { if (!(is_integral(expr) || is_constraint(expr))) { handleError(expr, "$Boolean_expected"); @@ -1127,7 +1120,7 @@ bool TypeChecker::checkConditionalExpressionInFunction(expression_t expr) return true; } -void TypeChecker::checkObservationConstraints(expression_t expr) +void TypeChecker::checkObservationConstraints(const expression_t& expr) { for (size_t i = 0; i < expr.get_size(); ++i) { checkObservationConstraints(expr[i]); @@ -1176,7 +1169,7 @@ void TypeChecker::checkObservationConstraints(expression_t expr) } } -static bool validReturnType(type_t type) +static bool validReturnType(const type_t& type) { frame_t frame; @@ -1320,7 +1313,7 @@ int32_t TypeChecker::visitBlockStatement(BlockStatement* stat) symbol_t symbol = frame[i]; checkType(symbol.get_type()); if (auto* d = symbol.get_data(); d) { - variable_t* var = static_cast(d); + auto* var = static_cast(d); if (!var->init.empty() && checkExpression(var->init)) { if (var->init.changes_any_variable()) { /* This is stronger than C. However side-effects in @@ -1375,22 +1368,20 @@ int32_t TypeChecker::visitReturnStatement(ReturnStatement* stat) * is 1, and in all other cases 2. An argument to a channel parameter * must have at least the same capability as the parameter. */ -static int channelCapability(type_t type) +static int channelCapability(const type_t& type) { assert(type.is_channel()); - if (type.is(URGENT)) { + if (type.is(URGENT)) return 0; - } - if (type.is(BROADCAST)) { + if (type.is(BROADCAST)) return 1; - } return 2; } /** * Returns true if two scalar types are name-equivalent. */ -static bool isSameScalarType(type_t t1, type_t t2) +static bool isSameScalarType(const type_t& t1, const type_t& t2) { if (t1.get_kind() == REF || t1.get_kind() == CONSTANT || t1.get_kind() == SYSTEM_META) { return isSameScalarType(t1[0], t2); @@ -1411,7 +1402,7 @@ static bool isSameScalarType(type_t t1, type_t t2) /** * Returns true iff argument type is compatible with parameter type. */ -bool TypeChecker::isParameterCompatible(type_t paramType, expression_t arg) +bool TypeChecker::isParameterCompatible(const type_t& paramType, const expression_t& arg) const { bool ref = paramType.is(REF); bool constant = paramType.is_constant(); @@ -1435,7 +1426,7 @@ bool TypeChecker::isParameterCompatible(type_t paramType, expression_t arg) /** * Checks whether argument type is compatible with parameter type. */ -bool TypeChecker::checkParameterCompatible(type_t paramType, expression_t arg) +bool TypeChecker::checkParameterCompatible(const type_t& paramType, const expression_t& arg) const { if (!isParameterCompatible(paramType, arg)) { handleError(arg, "$Incompatible_argument"); @@ -1451,7 +1442,7 @@ bool TypeChecker::checkParameterCompatible(type_t paramType, expression_t arg) * returned. REVISIT: Can a record initialiser have side-effects? Then * such reordering is not valid. */ -expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) +expression_t TypeChecker::checkInitialiser(const type_t& type, const expression_t& init) { if (areAssignmentCompatible(type, init.get_type(), true)) { return init; @@ -1497,8 +1488,8 @@ expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) } // Check that all fields do have an initialiser. - for (size_t i = 0; i < result.size(); i++) { - if (result[i].empty()) { + for (const auto& res : result) { + if (res.empty()) { handleError(init, "$Incomplete_initialiser"); break; } @@ -1516,7 +1507,7 @@ expression_t TypeChecker::checkInitialiser(type_t type, expression_t init) same size and the subtypes must be compatible. In case of records, they must have the same type name. */ -bool TypeChecker::areInlineIfCompatible(type_t result_type, type_t t1, type_t t2) const +bool TypeChecker::areInlineIfCompatible(const type_t& result_type, const type_t& t1, const type_t& t2) const { if (areAssignmentCompatible(result_type, t1) && areAssignmentCompatible(result_type, t1)) return true; @@ -1547,7 +1538,7 @@ type_t TypeChecker::getInlineIfCommonType(type_t t1, type_t t2) const * equivalent. However, CONST, SYSTEM_META, and REF are ignored. Scalar sets * are checked using named equivalence. */ -bool TypeChecker::areEquivalent(type_t a, type_t b) +bool TypeChecker::areEquivalent(const type_t& a, const type_t& b) { if (a.is_integer() && b.is_integer()) { return !a.is(RANGE) || !b.is(RANGE) || @@ -1597,7 +1588,7 @@ bool TypeChecker::areEquivalent(type_t a, type_t b) actually a left-hand side value. In case of integers, it does not check the range of the expressions. */ -bool TypeChecker::areAssignmentCompatible(type_t lvalue, type_t rvalue, bool init) const +bool TypeChecker::areAssignmentCompatible(const type_t& lvalue, const type_t& rvalue, bool init) const { if (init ? ((lvalue.is_clock() && (rvalue.is_double() || rvalue.is_integral())) || (lvalue.is_double() && (rvalue.is_integral() || rvalue.is_double()))) @@ -1623,7 +1614,7 @@ bool TypeChecker::areAssignmentCompatible(type_t lvalue, type_t rvalue, bool ini * then false is returned. * REVISIT: This should be updated. */ -bool TypeChecker::areEqCompatible(type_t t1, type_t t2) const +bool TypeChecker::areEqCompatible(const type_t& t1, const type_t& t2) const { if (t1.is_integral() && t2.is_integral()) { return true; @@ -1646,7 +1637,7 @@ bool TypeChecker::areEqCompatible(type_t t1, type_t t2) const out-of-range errors or warnings. Returns true if no type errors were found, false otherwise. */ -bool TypeChecker::checkExpression(expression_t expr) +bool TypeChecker::checkExpression(expression_t& expr) const { /* Do not check empty expressions. */ @@ -1780,7 +1771,7 @@ bool TypeChecker::checkExpression(expression_t expr) case SPAWN: { template_t* temp = document.find_dynamic_template(expr[0].get_symbol().get_name()); - if (!temp) { + if (temp == nullptr) { handleError(expr, "It appears your trying to spawn a non-dynamic template"); return false; } @@ -1805,7 +1796,7 @@ bool TypeChecker::checkExpression(expression_t expr) case NUMOF: { template_t* temp = document.find_dynamic_template(expr[0].get_symbol().get_name()); - if (temp) { + if (temp != nullptr) { type = type_t::create_primitive(Constants::INT); } else { handleError(expr, "Not a dynamic template"); @@ -2470,7 +2461,7 @@ bool TypeChecker::checkExpression(expression_t expr) /** * Returns true if expression evaluates to a modifiable l-value. */ -bool TypeChecker::isModifiableLValue(expression_t expr) const +bool TypeChecker::isModifiableLValue(const expression_t& expr) const { type_t t, f; switch (expr.get_kind()) { @@ -2520,7 +2511,7 @@ bool TypeChecker::isModifiableLValue(expression_t expr) const /** * Returns true iff \a expr evaluates to an lvalue. */ -bool TypeChecker::isLValue(expression_t expr) const +bool TypeChecker::isLValue(const expression_t& expr) const { type_t t, f; switch (expr.get_kind()) { @@ -2561,7 +2552,7 @@ bool TypeChecker::isLValue(expression_t expr) const expressions. Thus i[v] is a l-value, but if v is a non-constant variable, then it does not result in a unique reference. */ -bool TypeChecker::isUniqueReference(expression_t expr) const +bool TypeChecker::isUniqueReference(const expression_t& expr) const { switch (expr.get_kind()) { case IDENTIFIER: return true; @@ -2622,11 +2613,8 @@ int32_t parse_XML_buffer(const char* buffer, Document* doc, bool newxta, const std::vector& paths) { auto builder = DocumentBuilder{*doc, paths}; - int err = parse_XML_buffer(buffer, &builder, newxta); - - if (err) { + if (int err = parse_XML_buffer(buffer, &builder, newxta); err != 0) return err; - } if (!doc->has_errors()) { TypeChecker checker(*doc); @@ -2641,10 +2629,8 @@ int32_t parse_XML_buffer(const char* buffer, Document* doc, bool newxta, int32_t parse_XML_file(const char* file, Document* doc, bool newxta, const std::vector& paths) { auto builder = DocumentBuilder{*doc, paths}; - int err = parse_XML_file(file, &builder, newxta); - if (err) { + if (int err = parse_XML_file(file, &builder, newxta); err != 0) return err; - } if (!doc->has_errors()) { TypeChecker checker(*doc); @@ -2657,10 +2643,8 @@ int32_t parse_XML_file(const char* file, Document* doc, bool newxta, const std:: int32_t parse_XML_fd(int fd, Document* doc, bool newxta, const std::vector& paths) { auto builder = DocumentBuilder{*doc, paths}; - int err = parse_XML_fd(fd, &builder, newxta); - if (err) { + if (int err = parse_XML_fd(fd, &builder, newxta); err != 0) return err; - } if (!doc->has_errors()) { TypeChecker checker(*doc); @@ -2695,7 +2679,7 @@ bool TypeChecker::visitTemplateBefore(template_t& t) return true; } -bool TypeChecker::checkSpawnParameterCompatible(type_t param, expression_t arg) +bool TypeChecker::checkSpawnParameterCompatible(const type_t& param, const expression_t& arg) const { return checkParameterCompatible(param, arg); } @@ -2713,7 +2697,7 @@ bool TypeChecker::checkDynamicExpressions(Statement* stat) return ok; } -bool TypeChecker::checkNrOfRuns(const expression_t& runs) +bool TypeChecker::checkNrOfRuns(const expression_t& runs) const { if (!isCompileTimeComputable(runs)) { handleError(runs, "$Must_be_computable_at_compile_time"); @@ -2726,7 +2710,7 @@ bool TypeChecker::checkNrOfRuns(const expression_t& runs) return true; } -bool TypeChecker::checkBoundTypeOrBoundedExpr(const expression_t& boundTypeOrExpr) +bool TypeChecker::checkBoundTypeOrBoundedExpr(const expression_t& boundTypeOrExpr) const { if (!is_const_integer(boundTypeOrExpr) && !is_clock(boundTypeOrExpr)) { handleError(boundTypeOrExpr, "$Clock_expected"); @@ -2735,7 +2719,7 @@ bool TypeChecker::checkBoundTypeOrBoundedExpr(const expression_t& boundTypeOrExp return true; } -bool TypeChecker::checkBound(const expression_t& bound) +bool TypeChecker::checkBound(const expression_t& bound) const { if (!isCompileTimeComputable(bound)) { handleError(bound, "$Must_be_computable_at_compile_time"); @@ -2748,7 +2732,7 @@ bool TypeChecker::checkBound(const expression_t& bound) return true; } -bool TypeChecker::checkPredicate(const expression_t& predicate) +bool TypeChecker::checkPredicate(const expression_t& predicate) const { if (!is_integral(predicate) && !is_constraint(predicate)) { // check reachability expression is a boolean handleError(predicate, "$Boolean_expected"); @@ -2761,7 +2745,7 @@ bool TypeChecker::checkPredicate(const expression_t& predicate) return true; } -bool TypeChecker::checkProbBound(const expression_t& probBound) +bool TypeChecker::checkProbBound(const expression_t& probBound) const { if (!is_const_double(probBound)) { handleError(probBound, "Floating point number expected as probability bound"); @@ -2770,7 +2754,7 @@ bool TypeChecker::checkProbBound(const expression_t& probBound) return true; } -bool TypeChecker::checkUntilCond(kind_t kind, const expression_t& untilCond) +bool TypeChecker::checkUntilCond(kind_t kind, const expression_t& untilCond) const { bool ok = true; if (kind == PROBA_DIAMOND && !is_integral(untilCond) && !is_constraint(untilCond)) { @@ -2784,7 +2768,7 @@ bool TypeChecker::checkUntilCond(kind_t kind, const expression_t& untilCond) return ok; } -bool TypeChecker::checkMonitoredExpr(const expression_t& expr) +bool TypeChecker::checkMonitoredExpr(const expression_t& expr) const { if (!is_integral(expr) && !is_clock(expr) && !is_double_value(expr) && !expr.get_type().is(Constants::DOUBLE_INV_GUARD) && !is_constraint(expr)) { @@ -2798,7 +2782,7 @@ bool TypeChecker::checkMonitoredExpr(const expression_t& expr) return true; } -bool TypeChecker::checkPathQuant(const expression_t& expr) +bool TypeChecker::checkPathQuant(const expression_t& expr) const { if (!is_const_integer(expr)) { handleError(expr, "Bug: bad path quantifier"); @@ -2807,7 +2791,7 @@ bool TypeChecker::checkPathQuant(const expression_t& expr) return true; } -bool TypeChecker::checkAggregationOp(const expression_t& expr) +bool TypeChecker::checkAggregationOp(const expression_t& expr) const { if (!is_const_integer(expr)) { handleError(expr, "Bug: bad aggregation operator expression"); diff --git a/src/xmlreader.cpp b/src/xmlreader.cpp index 08bf03c7..92aa4a20 100644 --- a/src/xmlreader.cpp +++ b/src/xmlreader.cpp @@ -150,9 +150,9 @@ static bool is_blank(std::string_view str) { return std::all_of(str.cbegin(), st static inline bool is_blank(const xmlChar* str) { return is_blank((const char*)str); } -static inline bool is_alpha(unsigned char c) { return std::isalpha(c) || c == '_'; } +static inline bool is_alpha(unsigned char c) { return std::isalpha(c) != 0 || c == '_'; } -static bool is_id_char(unsigned char c) { return std::isalnum(c) || c == '_' || c == '$' || c == '#'; } +static bool is_id_char(unsigned char c) { return std::isalnum(c) != 0 || c == '_' || c == '$' || c == '#'; } struct id_expected_error : std::logic_error { @@ -169,35 +169,36 @@ struct xpath_corrupt_error : std::logic_error xpath_corrupt_error(): std::logic_error{"XPath is corrupted"} {} }; +std::string_view trim(std::string_view text) +{ + static constexpr auto ws = "\t\n\v\f\r "; + auto res = text.substr(0, 0); + if (auto b = text.find_first_not_of(ws); b != std::string_view::npos) { + auto e = text.find_last_not_of(ws); + res = text.substr(b, e - b + 1); + } + return res; +} + /** * Extracts the alpha-numerical symbol used for variable/type * identifiers. Identifier starts with alpha and further might * contain digits, white spaces are ignored. - * - * Throws a TypeException is identifier is invalid or a newly - * allocated string to be destroyed with delete []. + * @param text a potential identifier as a character string. + * @return valid identifier trimmed + * @throws std::logic_error if identifier is invalid. */ -static std::string_view symbol(std::string_view sv) -{ // TODO: LSC revisit: this is very similar to trimming whitespace - if (sv.empty()) - throw id_expected_error{}; - auto first = std::begin(sv); - const auto end = std::end(sv); - while (first != end && std::isspace(*first)) - ++first; - if (first == end) +static std::string_view symbol(std::string_view text) +{ + text = trim(text); + if (text.empty()) throw id_expected_error{}; - if (!is_alpha(*first)) + if (!is_alpha(text[0])) throw id_expected_error{}; - auto last = first; - while (last != end && is_id_char(*last)) - ++last; - auto p = last; - while (p != end && std::isspace(*p)) - ++p; - if (p != end) - throw invalid_id_error{}; - return std::string_view(first, std::distance(first, last)); + for (const auto& c : text) + if (!is_id_char(c)) + throw invalid_id_error{}; + return text; } /** @@ -547,7 +548,7 @@ void XMLReader::read() const std::string& XMLReader::get_name(const char* id) const { - if (id) { + if (id != nullptr) { if (auto l = names.find(id); l != names.end()) return l->second; } @@ -644,8 +645,7 @@ std::string XMLReader::readText(bool instanceLine) { if (getNodeType() == XML_READER_TYPE_TEXT) { // text content of a node xmlChar* text = xmlTextReaderValue(reader.get()); - auto len = text ? std::strlen((const char*)text) : 0; - auto text_sv = std::string_view{(const char*)text, len}; + auto text_sv = std::string_view{text != nullptr ? (const char*)text : ""}; tracker.setPath(parser, path.str()); tracker.increment(parser, text_sv.size()); try { @@ -981,7 +981,7 @@ bool XMLReader::init() /* Get reference attribute. */ char* ref = getAttribute("ref"); /* Find location name for the reference. */ - if (ref) { + if (ref != nullptr) { std::string name = get_name(ref); try { parser->proc_location_init(name.c_str()); @@ -1036,7 +1036,7 @@ std::vector XMLReader::anchors() while (begin(tag_t::ANCHOR, false)) { res.push_back(reference("instanceid")); } - if (res.size() == 0) + if (res.empty()) throw TypeException{"Missing anchor element"}; return res; } @@ -1051,7 +1051,7 @@ bool XMLReader::transition() xmlFree(type); char* id = getAttribute("action"); - auto actname = std::string{id ? id : "SKIP"}; + auto actname = std::string{id != nullptr ? id : "SKIP"}; xmlFree(id); read(); @@ -1273,8 +1273,8 @@ bool XMLReader::comment() bool XMLReader::option() { if (begin(tag_t::OPTION, false)) { - auto key = getAttribute("key"); - auto value = getAttribute("value"); + char* key = getAttribute("key"); + char* value = getAttribute("value"); parser->query_options(key, value); xmlFree(key); xmlFree(value); @@ -1289,9 +1289,9 @@ bool XMLReader::expectation() if (begin(tag_t::EXPECT, false)) { if (!isEmpty()) { parser->expectation_begin(); - auto outcome = getAttribute("outcome"); - auto type = getAttribute("type"); - auto value = getAttribute("value"); + char* outcome = getAttribute("outcome"); + char* type = getAttribute("type"); + char* value = getAttribute("value"); parser->expectation_value(outcome, type, value); zero_or_more(tag_t::EXPECT, [this] { if (begin(tag_t::RESOURCE, false)) { @@ -1345,8 +1345,8 @@ bool XMLReader::model_options() { while (begin(tag_t::OPTION)) { read(); - auto key = getAttribute("key"); - auto value = getAttribute("value"); + char* key = getAttribute("key"); + char* value = getAttribute("value"); parser->model_option(key, value); close(tag_t::OPTION); } @@ -1409,7 +1409,7 @@ std::string getXMLElement(xmlDocPtr docPtr, const std::string& path) // used in // The first point of the xml node xmlNodePtr node = nodeset->nodeTab[0]; xmlChar* s = xmlNodeListGetString(docPtr, node->xmlChildrenNode, 1); - if (s) + if (s != nullptr) res = (char*)s; xmlFree(s); } diff --git a/src/xmlwriter.cpp b/src/xmlwriter.cpp index d6eb3dec..bc1653e0 100644 --- a/src/xmlwriter.cpp +++ b/src/xmlwriter.cpp @@ -30,9 +30,7 @@ #include // M_PI #include // strlen -using std::vector; using std::list; -using std::map; using std::string; using namespace UTAP; using namespace UTAP::Constants; @@ -325,14 +323,14 @@ void XMLWriter::taTempl(const template_t& templ) writeElement("declaration", declarations.c_str()); // locations - for (auto& loc : templ.locations) { + for (const auto& loc : templ.locations) { location(loc); selfLoops[loc.nr] = 0; } // initial location init(templ); // transitions - for (auto& e : templ.edges) + for (const auto& e : templ.edges) transition(e); endElement(); // end of the "template" tag } @@ -406,8 +404,8 @@ xmlChar* UTAP::ConvertInput(const char* in, const char* encoding) return nullptr; handler = xmlFindCharEncodingHandler(encoding); - if (!handler) { - printf("ConvertInput: no encoding handler found for '%s'\n", encoding ? encoding : ""); + if (handler == nullptr) { + printf("ConvertInput: no encoding handler found for '%s'\n", (encoding != nullptr) ? encoding : ""); return nullptr; } @@ -418,7 +416,7 @@ xmlChar* UTAP::ConvertInput(const char* in, const char* encoding) if (out != nullptr) { temp = size - 1; ret = handler->input(out, &out_size, (const xmlChar*)in, &temp); - if ((ret < 0) || (temp - size + 1)) { + if ((ret < 0) || (temp - size + 1 != 0)) { if (ret < 0) { printf("ConvertInput: conversion wasn't successful.\n"); } else { diff --git a/test/syntaxcheck.cpp b/test/syntaxcheck.cpp index 5e788b38..29d46d5a 100644 --- a/test/syntaxcheck.cpp +++ b/test/syntaxcheck.cpp @@ -27,9 +27,7 @@ using UTAP::Document; using std::endl; -using std::cout; using std::cerr; -using std::vector; int main(int argc, char* argv[]) { @@ -48,7 +46,7 @@ int main(int argc, char* argv[]) parse_XML_file(name.c_str(), &system, !old); } else { FILE* file = fopen(name.c_str(), "r"); - if (!file) { + if (file == nullptr) { perror("check"); return 1; } diff --git a/test/test_parser.cpp b/test/test_parser.cpp index c11e47ab..0412da1f 100644 --- a/test/test_parser.cpp +++ b/test/test_parser.cpp @@ -26,9 +26,9 @@ TEST_CASE("Double Serialization Test") { auto doc = read_document("if_statement.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); - auto& warnings = doc->get_warnings(); + const auto& warnings = doc->get_warnings(); CHECK(warnings.size() == 0); } @@ -36,9 +36,9 @@ TEST_CASE("Power expressions") { auto doc = read_document("powers.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); - auto& warnings = doc->get_warnings(); + const auto& warnings = doc->get_warnings(); CHECK(warnings.size() == 0); } @@ -46,8 +46,8 @@ TEST_CASE("External functions") { auto doc = read_document("external_fn.xml"); REQUIRE(doc); - auto& errs = doc->get_errors(); - auto& warns = doc->get_warnings(); + const auto& errs = doc->get_errors(); + const auto& warns = doc->get_warnings(); REQUIRE(errs.size() == 3); // "libbad" not found (x2), "absent" undefined. CHECK(warns.size() == 0); } @@ -56,8 +56,8 @@ TEST_CASE("Error location") { auto doc = read_document("smc_non-deterministic_input2.xml"); REQUIRE(doc); - auto& errs = doc->get_errors(); - auto& warns = doc->get_warnings(); + const auto& errs = doc->get_errors(); + const auto& warns = doc->get_warnings(); REQUIRE(errs.size() == 0); CHECK(warns.size() == 0); const auto& templates = doc->get_templates(); @@ -259,7 +259,7 @@ TEST_CASE("Sim region cleanup causes memory errors (run with ASAN)") { auto doc = read_document("lsc_example.xml"); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); auto& templ = doc->get_templates().back(); @@ -272,7 +272,7 @@ TEST_CASE("Struct int,int initialization") auto doc = document_fixture{}.add_default_process().add_global_decl("const struct { int x; int y; } s = {1, 1};").parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -284,7 +284,7 @@ TEST_CASE("Struct int,double initialization") .add_global_decl("const struct { int x; double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -296,7 +296,7 @@ TEST_CASE("Struct double,double initialization") .add_global_decl("const struct { double x; double y; } s = {1.0, 1};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -309,7 +309,7 @@ TEST_CASE("Nested struct int,double initialization") .add_global_decl("typedef struct { int x; double y; } S; struct { S s1; S s2; } s = {{5,5.5},{2,2.25}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -321,7 +321,7 @@ TEST_CASE("Meta struct") .add_global_decl("meta struct { int x; double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -333,7 +333,7 @@ TEST_CASE("Struct meta field") .add_global_decl("meta struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -345,7 +345,7 @@ TEST_CASE("Initializing doubles in struct with ints") .add_global_decl("meta struct { double x; meta double y; } s = {1, 1};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -355,7 +355,7 @@ TEST_CASE("Initializing ints with double value") auto doc = document_fixture{}.add_default_process().add_global_decl("struct { int x; int y; } s = {1.1, 1.2};").parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 2); CHECK(doc->get_warnings().size() == 0); } @@ -367,7 +367,7 @@ TEST_CASE("Meta field in non meta struct") .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -379,7 +379,7 @@ TEST_CASE("Meta field in non meta struct") .add_global_decl("struct { int x; meta double y; } s = {1, 1.0};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -391,7 +391,7 @@ TEST_CASE("Nested structs") .add_global_decl("struct { int x; struct { int y; double d;} data; } s = {1, {5, 5.0}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -403,7 +403,7 @@ TEST_CASE("Structs with arrays") .add_global_decl("struct { int x[2]; double y[2]; } s = {{1,1}, {5.0, 5.0}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK(errors.size() == 0); CHECK(doc->get_warnings().size() == 0); } @@ -415,9 +415,9 @@ TEST_CASE("Array of structs") .add_global_decl("struct { int x; double y;} s[2] = {{1,5.0}, {1,2.5}};") .parse(); REQUIRE(doc); - auto& errors = doc->get_errors(); + const auto& errors = doc->get_errors(); CHECK_MESSAGE(errors.size() == 0, errors.at(0).msg); - CHECK(doc->get_warnings().size() == 0); + CHECK(doc->get_warnings().size() == 0); } TEST_CASE("Pre increment precedence bug")