From fc9e609ab5eab5cccc9cc6e947be8cf6d057e8d4 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Wed, 25 Mar 2020 08:37:57 +0100 Subject: [PATCH] Fixed "maybe-uninitialized" warning (fixes #1217) --- CHANGELOG.md | 5 ++ CMakeLists.txt | 25 +++++++++- src/ArduinoJson.hpp | 2 +- src/ArduinoJson/Json/JsonDeserializer.hpp | 48 +++++++++++-------- src/ArduinoJson/Json/Utf16.hpp | 16 +++++++ .../MsgPack/MsgPackDeserializer.hpp | 4 +- src/ArduinoJson/Variant/VariantData.hpp | 16 +++++++ 7 files changed, 91 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e8ecaa3..b4a72062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ ArduinoJson: change log ======================= +HEAD +---- + +* Fixed "maybe-uninitialized" warning (issue #1217) + v6.15.0 (2020-03-22) ------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c80733f..796d63c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,29 @@ project(ArduinoJson) enable_testing() add_definitions(-DARDUINOJSON_DEBUG=1) -if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-g -O0) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8) + add_compile_options(-g -Og) + else() + add_compile_options(-g -O0) + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.0) + add_compile_options(-g -Og) + else() + add_compile_options(-g -O0) + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 9.0) + add_compile_options(-g -Og) + else() + add_compile_options(-g -O0) + endif() endif() if(${COVERAGE}) diff --git a/src/ArduinoJson.hpp b/src/ArduinoJson.hpp index a1592f5c..d2a1f630 100644 --- a/src/ArduinoJson.hpp +++ b/src/ArduinoJson.hpp @@ -6,7 +6,7 @@ #include "ArduinoJson/Configuration.hpp" -#if ARDUINOJSON_DEBUG +#if !ARDUINOJSON_DEBUG #ifdef __clang__ #pragma clang system_header #elif defined __GNUC__ diff --git a/src/ArduinoJson/Json/JsonDeserializer.hpp b/src/ArduinoJson/Json/JsonDeserializer.hpp index 4009431e..276a30a7 100644 --- a/src/ArduinoJson/Json/JsonDeserializer.hpp +++ b/src/ArduinoJson/Json/JsonDeserializer.hpp @@ -22,6 +22,15 @@ class JsonDeserializer { typedef typename remove_reference::type::StringBuilder StringBuilder; + struct StringOrError { + DeserializationError err; + const char *value; + + StringOrError(DeserializationError e) : err(e) {} + StringOrError(DeserializationError::Code c) : err(c) {} + StringOrError(const char *s) : err(DeserializationError::Ok), value(s) {} + }; + public: JsonDeserializer(MemoryPool &pool, TReader reader, TStringStorage stringStorage) @@ -216,8 +225,8 @@ class JsonDeserializer { // Read each key value pair for (;;) { // Parse key - const char *key; - err = parseKey(key); + StringOrError key = parseKey(); + err = key.err; // <- this trick saves 62 bytes on AVR if (err) return err; @@ -228,17 +237,17 @@ class JsonDeserializer { if (!eat(':')) return DeserializationError::InvalidInput; - TFilter memberFilter = filter[key]; + TFilter memberFilter = filter[key.value]; if (memberFilter.allow()) { - VariantData *variant = object.getMember(adaptString(key)); + VariantData *variant = object.getMember(adaptString(key.value)); if (!variant) { // Allocate slot in object VariantSlot *slot = object.addSlot(_pool); if (!slot) return DeserializationError::NoMemory; - slot->setOwnedKey(make_not_null(key)); + slot->setOwnedKey(make_not_null(key.value)); variant = slot->data(); } @@ -248,7 +257,7 @@ class JsonDeserializer { if (err) return err; } else { - _stringStorage.reclaim(key); + _stringStorage.reclaim(key.value); err = skipVariant(nestingLimit.decrement()); if (err) return err; @@ -323,24 +332,23 @@ class JsonDeserializer { } } - DeserializationError parseKey(const char *&key) { + StringOrError parseKey() { if (isQuote(current())) { - return parseQuotedString(key); + return parseQuotedString(); } else { - return parseNonQuotedString(key); + return parseNonQuotedString(); } } DeserializationError parseStringValue(VariantData &variant) { - const char *value; - DeserializationError err = parseQuotedString(value); - if (err) - return err; - variant.setOwnedString(make_not_null(value)); + StringOrError result = parseQuotedString(); + if (result.err) + return result.err; + variant.setOwnedString(make_not_null(result.value)); return DeserializationError::Ok; } - DeserializationError parseQuotedString(const char *&result) { + StringOrError parseQuotedString() { StringBuilder builder = _stringStorage.startString(); #if ARDUINOJSON_DECODE_UNICODE Utf16::Codepoint codepoint; @@ -385,13 +393,13 @@ class JsonDeserializer { builder.append(c); } - result = builder.complete(); + const char *result = builder.complete(); if (!result) return DeserializationError::NoMemory; - return DeserializationError::Ok; + return result; } - DeserializationError parseNonQuotedString(const char *&result) { + StringOrError parseNonQuotedString() { StringBuilder builder = _stringStorage.startString(); char c = current(); @@ -407,10 +415,10 @@ class JsonDeserializer { return DeserializationError::InvalidInput; } - result = builder.complete(); + const char *result = builder.complete(); if (!result) return DeserializationError::NoMemory; - return DeserializationError::Ok; + return result; } DeserializationError skipString() { diff --git a/src/ArduinoJson/Json/Utf16.hpp b/src/ArduinoJson/Json/Utf16.hpp index aaf9f6f3..33721a63 100644 --- a/src/ArduinoJson/Json/Utf16.hpp +++ b/src/ArduinoJson/Json/Utf16.hpp @@ -8,6 +8,16 @@ #include // uint16_t, uint32_t +// The high surrogate may be uninitialized if the pair is invalid, +// we choose to ignore the problem to reduce the size of the code +// Garbage in => Garbage out +#if defined(__GNUC__) +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif +#endif + namespace ARDUINOJSON_NAMESPACE { namespace Utf16 { @@ -47,3 +57,9 @@ class Codepoint { }; } // namespace Utf16 } // namespace ARDUINOJSON_NAMESPACE + +#if defined(__GNUC__) +#if __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif +#endif diff --git a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index c48f85b4..ed328913 100644 --- a/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -233,7 +233,7 @@ class MsgPackDeserializer { } DeserializationError readString(VariantData &variant, size_t n) { - const char *s; + const char *s = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR) DeserializationError err = readString(s, n); if (!err) variant.setOwnedString(make_not_null(s)); @@ -300,7 +300,7 @@ class MsgPackDeserializer { if (!slot) return DeserializationError::NoMemory; - const char *key; + const char *key = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR) DeserializationError err = parseKey(key); if (err) return err; diff --git a/src/ArduinoJson/Variant/VariantData.hpp b/src/ArduinoJson/Variant/VariantData.hpp index 3c6d7a8c..79ac0fba 100644 --- a/src/ArduinoJson/Variant/VariantData.hpp +++ b/src/ArduinoJson/Variant/VariantData.hpp @@ -10,6 +10,16 @@ #include #include +// VariantData can't have a constructor (to be a POD), so we have no way to fix +// this warning +#if defined(__GNUC__) +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif +#endif + namespace ARDUINOJSON_NAMESPACE { class VariantData { @@ -383,3 +393,9 @@ class VariantData { }; } // namespace ARDUINOJSON_NAMESPACE + +#if defined(__GNUC__) +#if __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif +#endif