diff --git a/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/BaseCppTest.java b/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/BaseCppTest.java index 4b13b7ce43..6e2d356472 100644 --- a/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/BaseCppTest.java +++ b/runtime-testsuite/test/org/antlr/v4/test/runtime/cpp/BaseCppTest.java @@ -303,7 +303,7 @@ public String execModule(String fileName) { } try { - List command2 = new ArrayList(Arrays.asList("clang++", "-std=c++11", "-I", includePath, "-L.", "-lantlr4-runtime", "-o", "a.out")); + List command2 = new ArrayList(Arrays.asList("clang++", "-std=c++11", "-I", includePath, "-L.", "-lantlr4-runtime", "-pthread", "-o", "a.out")); command2.addAll(allCppFiles(getTempDirPath())); if (runCommand(command2.toArray(new String[0]), getTempDirPath(), "building test binary", true) == null) { return null; diff --git a/runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp b/runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp index 97cda87b58..8c84a91e66 100755 --- a/runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNConfigSet.cpp @@ -99,8 +99,8 @@ std::vector ATNConfigSet::getStates() { BitSet ATNConfigSet::getAlts() { BitSet alts; - for (const ATNConfig &config : configs) { - alts.set(config.alt); + for (const auto &config : configs) { + alts.set(config->alt); } return alts; } diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp b/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp index d070cd9d61..7743d89d89 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.cpp @@ -4,61 +4,51 @@ */ #include "atn/ATNDeserializationOptions.h" +#include "Exceptions.h" +#include +#include + +using namespace antlr4; using namespace antlr4::atn; -const ATNDeserializationOptions ATNDeserializationOptions::defaultOptions; +namespace { -ATNDeserializationOptions::ATNDeserializationOptions() { - InitializeInstanceFields(); -} +std::once_flag defaultATNDeserializationOptionsOnceFlag; +std::unique_ptr defaultATNDeserializationOptions; -ATNDeserializationOptions::ATNDeserializationOptions(ATNDeserializationOptions *options) : ATNDeserializationOptions() { - this->verifyATN = options->verifyATN; - this->generateRuleBypassTransitions = options->generateRuleBypassTransitions; +void initializeDefaultATNDeserializationOptions() { + defaultATNDeserializationOptions.reset(new ATNDeserializationOptions()); } -ATNDeserializationOptions::~ATNDeserializationOptions() { } -const ATNDeserializationOptions& ATNDeserializationOptions::getDefaultOptions() { - return defaultOptions; -} +ATNDeserializationOptions::ATNDeserializationOptions(ATNDeserializationOptions *options) + : _readOnly(false), _verifyATN(options->_verifyATN), + _generateRuleBypassTransitions(options->_generateRuleBypassTransitions) {} -bool ATNDeserializationOptions::isReadOnly() { - return readOnly; +const ATNDeserializationOptions& ATNDeserializationOptions::getDefaultOptions() { + std::call_once(defaultATNDeserializationOptionsOnceFlag, + initializeDefaultATNDeserializationOptions); + return *defaultATNDeserializationOptions; } void ATNDeserializationOptions::makeReadOnly() { - readOnly = true; -} - -bool ATNDeserializationOptions::isVerifyATN() { - return verifyATN; + _readOnly = true; } void ATNDeserializationOptions::setVerifyATN(bool verify) { throwIfReadOnly(); - verifyATN = verify; -} - -bool ATNDeserializationOptions::isGenerateRuleBypassTransitions() { - return generateRuleBypassTransitions; + _verifyATN = verify; } void ATNDeserializationOptions::setGenerateRuleBypassTransitions(bool generate) { throwIfReadOnly(); - generateRuleBypassTransitions = generate; + _generateRuleBypassTransitions = generate; } -void ATNDeserializationOptions::throwIfReadOnly() { +void ATNDeserializationOptions::throwIfReadOnly() const { if (isReadOnly()) { - throw "The object is read only."; + throw IllegalStateException("ATNDeserializationOptions is read only."); } } - -void ATNDeserializationOptions::InitializeInstanceFields() { - readOnly = false; - verifyATN = true; - generateRuleBypassTransitions = false; -} diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h b/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h index f03bdb39ad..8b1f9850b7 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializationOptions.h @@ -10,41 +10,39 @@ namespace antlr4 { namespace atn { - class ANTLR4CPP_PUBLIC ATNDeserializationOptions { - private: - static const ATNDeserializationOptions defaultOptions; +class ANTLR4CPP_PUBLIC ATNDeserializationOptions final { +public: + ATNDeserializationOptions() + : _readOnly(false), _verifyATN(true), _generateRuleBypassTransitions(false) {} - bool readOnly; - bool verifyATN; - bool generateRuleBypassTransitions; + // TODO: Is this useful? If so we should mark it as explicit, otherwise remove it. + ATNDeserializationOptions(ATNDeserializationOptions *options); - public: - ATNDeserializationOptions(); - ATNDeserializationOptions(ATNDeserializationOptions *options); - ATNDeserializationOptions(ATNDeserializationOptions const&) = default; - virtual ~ATNDeserializationOptions(); - ATNDeserializationOptions& operator=(ATNDeserializationOptions const&) = default; + ATNDeserializationOptions(const ATNDeserializationOptions&) = default; - static const ATNDeserializationOptions& getDefaultOptions(); + ATNDeserializationOptions& operator=(const ATNDeserializationOptions&) = default; - bool isReadOnly(); + static const ATNDeserializationOptions& getDefaultOptions(); - void makeReadOnly(); + bool isReadOnly() const { return _readOnly; } - bool isVerifyATN(); + void makeReadOnly(); - void setVerifyATN(bool verify); + bool isVerifyATN() const { return _verifyATN; } - bool isGenerateRuleBypassTransitions(); + void setVerifyATN(bool verify); - void setGenerateRuleBypassTransitions(bool generate); + bool isGenerateRuleBypassTransitions() const { return _generateRuleBypassTransitions; } - protected: - virtual void throwIfReadOnly(); + void setGenerateRuleBypassTransitions(bool generate); - private: - void InitializeInstanceFields(); - }; +private: + void throwIfReadOnly() const; + + bool _readOnly; + bool _verifyATN; + bool _generateRuleBypassTransitions; +}; } // namespace atn } // namespace antlr4 diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp index 00d745d0b4..684cf300ca 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp @@ -51,7 +51,9 @@ #include "atn/ATNDeserializer.h" +#include #include +#include using namespace antlr4; using namespace antlr4::atn; @@ -59,8 +61,37 @@ using namespace antlrcpp; namespace { +struct WellKnownUuids final { + WellKnownUuids() = default; + + WellKnownUuids(const WellKnownUuids&) = delete; + + WellKnownUuids(WellKnownUuids&&) = delete; + + antlrcpp::Guid addedPrecedenceTransitions; + antlrcpp::Guid addedLexerActions; + antlrcpp::Guid addedUnicodeSmp; + antlrcpp::Guid baseSerialized; + std::vector supported; +}; + +std::once_flag wellKnownUuidsOnceFlag; +std::unique_ptr wellKnownUuids; + +void initializeWellKnownUuids() { + wellKnownUuids.reset(new WellKnownUuids()); + wellKnownUuids->addedPrecedenceTransitions = antlrcpp::Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61"); + wellKnownUuids->addedLexerActions = antlrcpp::Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E"); + wellKnownUuids->addedUnicodeSmp = antlrcpp::Guid("59627784-3BE5-417A-B9EB-8131A7286089"); + wellKnownUuids->baseSerialized = antlrcpp::Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3"); + wellKnownUuids->supported.assign({ + wellKnownUuids->baseSerialized, wellKnownUuids->addedPrecedenceTransitions, + wellKnownUuids->addedLexerActions, wellKnownUuids->addedUnicodeSmp}); + wellKnownUuids->supported.shrink_to_fit(); +} + uint32_t deserializeInt32(const std::vector& data, size_t offset) { - return (uint32_t)data[offset] | ((uint32_t)data[offset + 1] << 16); + return static_cast(data[offset]) | (static_cast(data[offset + 1]) << 16); } ssize_t readUnicodeInt(const std::vector& data, int& p) { @@ -105,7 +136,7 @@ void deserializeSets( ATNDeserializer::ATNDeserializer(): ATNDeserializer(ATNDeserializationOptions::getDefaultOptions()) { } -ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso): deserializationOptions(dso) { +ATNDeserializer::ATNDeserializer(const ATNDeserializationOptions& dso): _deserializationOptions(dso) { } ATNDeserializer::~ATNDeserializer() { @@ -116,15 +147,18 @@ ATNDeserializer::~ATNDeserializer() { * reflected as change in the unique ID SERIALIZED_UUID. */ antlrcpp::Guid ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() { - return antlrcpp::Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61"); + std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids); + return wellKnownUuids->addedPrecedenceTransitions; } antlrcpp::Guid ATNDeserializer::ADDED_LEXER_ACTIONS() { - return antlrcpp::Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E"); + std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids); + return wellKnownUuids->addedLexerActions; } antlrcpp::Guid ATNDeserializer::ADDED_UNICODE_SMP() { - return antlrcpp::Guid("59627784-3BE5-417A-B9EB-8131A7286089"); + std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids); + return wellKnownUuids->addedUnicodeSmp; } antlrcpp::Guid ATNDeserializer::SERIALIZED_UUID() { @@ -132,12 +166,13 @@ antlrcpp::Guid ATNDeserializer::SERIALIZED_UUID() { } antlrcpp::Guid ATNDeserializer::BASE_SERIALIZED_UUID() { - return antlrcpp::Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3"); + std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids); + return wellKnownUuids->baseSerialized; } -std::vector& ATNDeserializer::SUPPORTED_UUIDS() { - static std::vector singleton = { BASE_SERIALIZED_UUID(), ADDED_PRECEDENCE_TRANSITIONS(), ADDED_LEXER_ACTIONS(), ADDED_UNICODE_SMP() }; - return singleton; +const std::vector& ATNDeserializer::SUPPORTED_UUIDS() { + std::call_once(wellKnownUuidsOnceFlag, initializeWellKnownUuids); + return wellKnownUuids->supported; } bool ATNDeserializer::isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid) { @@ -433,11 +468,11 @@ ATN ATNDeserializer::deserialize(const std::vector& input) { markPrecedenceDecisions(atn); - if (deserializationOptions.isVerifyATN()) { + if (_deserializationOptions.isVerifyATN()) { verifyATN(atn); } - if (deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType::PARSER) { + if (_deserializationOptions.isGenerateRuleBypassTransitions() && atn.grammarType == ATNType::PARSER) { atn.ruleToTokenType.resize(atn.ruleToStartState.size()); for (size_t i = 0; i < atn.ruleToStartState.size(); i++) { atn.ruleToTokenType[i] = int(atn.maxTokenType + i + 1); @@ -521,7 +556,7 @@ ATN ATNDeserializer::deserialize(const std::vector& input) { bypassStart->addTransition(new EpsilonTransition(matchState)); /* mem check: freed in ATNState d-tor */ } - if (deserializationOptions.isVerifyATN()) { + if (_deserializationOptions.isVerifyATN()) { // reverify after modification verifyATN(atn); } @@ -537,7 +572,7 @@ ATN ATNDeserializer::deserialize(const std::vector& input) { * * @param atn The ATN. */ -void ATNDeserializer::markPrecedenceDecisions(const ATN &atn) { +void ATNDeserializer::markPrecedenceDecisions(const ATN &atn) const { for (ATNState *state : atn.states) { if (!is(state)) { continue; @@ -723,7 +758,7 @@ ATNState* ATNDeserializer::stateFactory(size_t type, size_t ruleIndex) { return s; } -Ref ATNDeserializer::lexerActionFactory(LexerActionType type, int data1, int data2) { +Ref ATNDeserializer::lexerActionFactory(LexerActionType type, int data1, int data2) const { switch (type) { case LexerActionType::CHANNEL: return std::make_shared(data1); diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.h b/runtime/Cpp/runtime/src/atn/ATNDeserializer.h index 57b6c7b285..8c989efed4 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.h +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.h @@ -11,81 +11,83 @@ namespace antlr4 { namespace atn { - class ANTLR4CPP_PUBLIC ATNDeserializer { - public: +class ANTLR4CPP_PUBLIC ATNDeserializer { +public: #if __cplusplus >= 201703L - static constexpr size_t SERIALIZED_VERSION = 3; + static constexpr size_t SERIALIZED_VERSION = 3; #else - enum : size_t { - SERIALIZED_VERSION = 3, - }; + enum : size_t { + SERIALIZED_VERSION = 3, + }; #endif - /// This is the current serialized UUID. - // ml: defined as function to avoid the “static initialization order fiasco”. - static antlrcpp::Guid SERIALIZED_UUID(); - - ATNDeserializer(); - ATNDeserializer(const ATNDeserializationOptions& dso); - virtual ~ATNDeserializer(); - - static antlrcpp::Guid toUUID(const unsigned short *data, size_t offset); - - virtual ATN deserialize(const std::vector &input); - virtual void verifyATN(const ATN &atn); - - static void checkCondition(bool condition); - static void checkCondition(bool condition, const std::string &message); - - static Transition *edgeFactory(const ATN &atn, size_t type, size_t src, size_t trg, size_t arg1, size_t arg2, - size_t arg3, const std::vector &sets); - - static ATNState *stateFactory(size_t type, size_t ruleIndex); - - protected: - /// Determines if a particular serialized representation of an ATN supports - /// a particular feature, identified by the used for serializing - /// the ATN at the time the feature was first introduced. - /// - /// The marking the first time the feature was - /// supported in the serialized ATN. - /// The of the actual serialized ATN which is - /// currently being deserialized. - /// {@code true} if the {@code actualUuid} value represents a - /// serialized ATN at or after the feature identified by {@code feature} was - /// introduced; otherwise, {@code false}. - virtual bool isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid); - void markPrecedenceDecisions(const ATN &atn); - Ref lexerActionFactory(LexerActionType type, int data1, int data2); - - private: - /// This is the earliest supported serialized UUID. - static antlrcpp::Guid BASE_SERIALIZED_UUID(); - - /// This UUID indicates an extension of for the - /// addition of precedence predicates. - static antlrcpp::Guid ADDED_PRECEDENCE_TRANSITIONS(); - - /** - * This UUID indicates an extension of ADDED_PRECEDENCE_TRANSITIONS - * for the addition of lexer actions encoded as a sequence of - * LexerAction instances. - */ - static antlrcpp::Guid ADDED_LEXER_ACTIONS(); - - /** - * This UUID indicates the serialized ATN contains two sets of - * IntervalSets, where the second set's values are encoded as - * 32-bit integers to support the full Unicode SMP range up to U+10FFFF. - */ - static antlrcpp::Guid ADDED_UNICODE_SMP(); - - /// This list contains all of the currently supported UUIDs, ordered by when - /// the feature first appeared in this branch. - static std::vector& SUPPORTED_UUIDS(); - - ATNDeserializationOptions deserializationOptions; - }; + /// This is the current serialized UUID. + // ml: defined as function to avoid the “static initialization order fiasco”. + static antlrcpp::Guid SERIALIZED_UUID(); + + ATNDeserializer(); + + explicit ATNDeserializer(const ATNDeserializationOptions& dso); + + virtual ~ATNDeserializer(); + + static antlrcpp::Guid toUUID(const unsigned short *data, size_t offset); + + virtual ATN deserialize(const std::vector &input); + virtual void verifyATN(const ATN &atn); + + static void checkCondition(bool condition); + static void checkCondition(bool condition, const std::string &message); + + static Transition *edgeFactory(const ATN &atn, size_t type, size_t src, size_t trg, size_t arg1, size_t arg2, + size_t arg3, const std::vector &sets); + + static ATNState *stateFactory(size_t type, size_t ruleIndex); + +protected: + /// Determines if a particular serialized representation of an ATN supports + /// a particular feature, identified by the used for serializing + /// the ATN at the time the feature was first introduced. + /// + /// The marking the first time the feature was + /// supported in the serialized ATN. + /// The of the actual serialized ATN which is + /// currently being deserialized. + /// {@code true} if the {@code actualUuid} value represents a + /// serialized ATN at or after the feature identified by {@code feature} was + /// introduced; otherwise, {@code false}. + virtual bool isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid); + void markPrecedenceDecisions(const ATN &atn) const; + Ref lexerActionFactory(LexerActionType type, int data1, int data2) const; + +private: + /// This is the earliest supported serialized UUID. + static antlrcpp::Guid BASE_SERIALIZED_UUID(); + + /// This UUID indicates an extension of for the + /// addition of precedence predicates. + static antlrcpp::Guid ADDED_PRECEDENCE_TRANSITIONS(); + + /** + * This UUID indicates an extension of ADDED_PRECEDENCE_TRANSITIONS + * for the addition of lexer actions encoded as a sequence of + * LexerAction instances. + */ + static antlrcpp::Guid ADDED_LEXER_ACTIONS(); + + /** + * This UUID indicates the serialized ATN contains two sets of + * IntervalSets, where the second set's values are encoded as + * 32-bit integers to support the full Unicode SMP range up to U+10FFFF. + */ + static antlrcpp::Guid ADDED_UNICODE_SMP(); + + /// This list contains all of the currently supported UUIDs, ordered by when + /// the feature first appeared in this branch. + static const std::vector& SUPPORTED_UUIDS(); + + const ATNDeserializationOptions _deserializationOptions; +}; } // namespace atn } // namespace antlr4