Fixed "maybe-uninitialized" warning (fixes #1217)

This commit is contained in:
Benoit Blanchon
2020-03-25 08:37:57 +01:00
parent 8b3d861a9d
commit fc9e609ab5
7 changed files with 91 additions and 25 deletions

View File

@ -1,6 +1,11 @@
ArduinoJson: change log ArduinoJson: change log
======================= =======================
HEAD
----
* Fixed "maybe-uninitialized" warning (issue #1217)
v6.15.0 (2020-03-22) v6.15.0 (2020-03-22)
------- -------

View File

@ -8,8 +8,29 @@ project(ArduinoJson)
enable_testing() enable_testing()
add_definitions(-DARDUINOJSON_DEBUG=1) 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() endif()
if(${COVERAGE}) if(${COVERAGE})

View File

@ -6,7 +6,7 @@
#include "ArduinoJson/Configuration.hpp" #include "ArduinoJson/Configuration.hpp"
#if ARDUINOJSON_DEBUG #if !ARDUINOJSON_DEBUG
#ifdef __clang__ #ifdef __clang__
#pragma clang system_header #pragma clang system_header
#elif defined __GNUC__ #elif defined __GNUC__

View File

@ -22,6 +22,15 @@ class JsonDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder typedef typename remove_reference<TStringStorage>::type::StringBuilder
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: public:
JsonDeserializer(MemoryPool &pool, TReader reader, JsonDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage) TStringStorage stringStorage)
@ -216,8 +225,8 @@ class JsonDeserializer {
// Read each key value pair // Read each key value pair
for (;;) { for (;;) {
// Parse key // Parse key
const char *key; StringOrError key = parseKey();
err = parseKey(key); err = key.err; // <- this trick saves 62 bytes on AVR
if (err) if (err)
return err; return err;
@ -228,17 +237,17 @@ class JsonDeserializer {
if (!eat(':')) if (!eat(':'))
return DeserializationError::InvalidInput; return DeserializationError::InvalidInput;
TFilter memberFilter = filter[key]; TFilter memberFilter = filter[key.value];
if (memberFilter.allow()) { if (memberFilter.allow()) {
VariantData *variant = object.getMember(adaptString(key)); VariantData *variant = object.getMember(adaptString(key.value));
if (!variant) { if (!variant) {
// Allocate slot in object // Allocate slot in object
VariantSlot *slot = object.addSlot(_pool); VariantSlot *slot = object.addSlot(_pool);
if (!slot) if (!slot)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
slot->setOwnedKey(make_not_null(key)); slot->setOwnedKey(make_not_null(key.value));
variant = slot->data(); variant = slot->data();
} }
@ -248,7 +257,7 @@ class JsonDeserializer {
if (err) if (err)
return err; return err;
} else { } else {
_stringStorage.reclaim(key); _stringStorage.reclaim(key.value);
err = skipVariant(nestingLimit.decrement()); err = skipVariant(nestingLimit.decrement());
if (err) if (err)
return err; return err;
@ -323,24 +332,23 @@ class JsonDeserializer {
} }
} }
DeserializationError parseKey(const char *&key) { StringOrError parseKey() {
if (isQuote(current())) { if (isQuote(current())) {
return parseQuotedString(key); return parseQuotedString();
} else { } else {
return parseNonQuotedString(key); return parseNonQuotedString();
} }
} }
DeserializationError parseStringValue(VariantData &variant) { DeserializationError parseStringValue(VariantData &variant) {
const char *value; StringOrError result = parseQuotedString();
DeserializationError err = parseQuotedString(value); if (result.err)
if (err) return result.err;
return err; variant.setOwnedString(make_not_null(result.value));
variant.setOwnedString(make_not_null(value));
return DeserializationError::Ok; return DeserializationError::Ok;
} }
DeserializationError parseQuotedString(const char *&result) { StringOrError parseQuotedString() {
StringBuilder builder = _stringStorage.startString(); StringBuilder builder = _stringStorage.startString();
#if ARDUINOJSON_DECODE_UNICODE #if ARDUINOJSON_DECODE_UNICODE
Utf16::Codepoint codepoint; Utf16::Codepoint codepoint;
@ -385,13 +393,13 @@ class JsonDeserializer {
builder.append(c); builder.append(c);
} }
result = builder.complete(); const char *result = builder.complete();
if (!result) if (!result)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
return DeserializationError::Ok; return result;
} }
DeserializationError parseNonQuotedString(const char *&result) { StringOrError parseNonQuotedString() {
StringBuilder builder = _stringStorage.startString(); StringBuilder builder = _stringStorage.startString();
char c = current(); char c = current();
@ -407,10 +415,10 @@ class JsonDeserializer {
return DeserializationError::InvalidInput; return DeserializationError::InvalidInput;
} }
result = builder.complete(); const char *result = builder.complete();
if (!result) if (!result)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
return DeserializationError::Ok; return result;
} }
DeserializationError skipString() { DeserializationError skipString() {

View File

@ -8,6 +8,16 @@
#include <stdint.h> // uint16_t, uint32_t #include <stdint.h> // 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 ARDUINOJSON_NAMESPACE {
namespace Utf16 { namespace Utf16 {
@ -47,3 +57,9 @@ class Codepoint {
}; };
} // namespace Utf16 } // namespace Utf16
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__GNUC__)
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -233,7 +233,7 @@ class MsgPackDeserializer {
} }
DeserializationError readString(VariantData &variant, size_t n) { 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); DeserializationError err = readString(s, n);
if (!err) if (!err)
variant.setOwnedString(make_not_null(s)); variant.setOwnedString(make_not_null(s));
@ -300,7 +300,7 @@ class MsgPackDeserializer {
if (!slot) if (!slot)
return DeserializationError::NoMemory; return DeserializationError::NoMemory;
const char *key; const char *key = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR)
DeserializationError err = parseKey(key); DeserializationError err = parseKey(key);
if (err) if (err)
return err; return err;

View File

@ -10,6 +10,16 @@
#include <ArduinoJson/Strings/RamStringAdapter.hpp> #include <ArduinoJson/Strings/RamStringAdapter.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp> #include <ArduinoJson/Variant/VariantContent.hpp>
// 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 { namespace ARDUINOJSON_NAMESPACE {
class VariantData { class VariantData {
@ -383,3 +393,9 @@ class VariantData {
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__GNUC__)
#if __GNUC__ >= 8
#pragma GCC diagnostic pop
#endif
#endif