diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 51554a648..12feb2f11 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -743,6 +743,7 @@ openthread_core_files = [ "utils/slaac_address.hpp", "utils/srp_client_buffers.cpp", "utils/srp_client_buffers.hpp", + "utils/static_counter.hpp", "utils/verhoeff_checksum.cpp", "utils/verhoeff_checksum.hpp", ] diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 6255a463c..eb6fdfe0c 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -38,6 +38,7 @@ #include "crypto/aes_ccm.hpp" #include "crypto/sha256.hpp" #include "instance/instance.hpp" +#include "utils/static_counter.hpp" namespace ot { namespace Mac { @@ -2210,19 +2211,24 @@ const char *Mac::OperationToString(Operation aOperation) #endif }; - static_assert(kOperationIdle == 0, "kOperationIdle value is incorrect"); - static_assert(kOperationActiveScan == 1, "kOperationActiveScan value is incorrect"); - static_assert(kOperationEnergyScan == 2, "kOperationEnergyScan value is incorrect"); - static_assert(kOperationTransmitBeacon == 3, "kOperationTransmitBeacon value is incorrect"); - static_assert(kOperationTransmitDataDirect == 4, "kOperationTransmitDataDirect value is incorrect"); - static_assert(kOperationTransmitPoll == 5, "kOperationTransmitPoll value is incorrect"); - static_assert(kOperationWaitingForData == 6, "kOperationWaitingForData value is incorrect"); + struct OperationChecker + { + InitEnumValidatorCounter(); + + ValidateNextEnum(kOperationIdle); + ValidateNextEnum(kOperationActiveScan); + ValidateNextEnum(kOperationEnergyScan); + ValidateNextEnum(kOperationTransmitBeacon); + ValidateNextEnum(kOperationTransmitDataDirect); + ValidateNextEnum(kOperationTransmitPoll); + ValidateNextEnum(kOperationWaitingForData); #if OPENTHREAD_FTD - static_assert(kOperationTransmitDataIndirect == 7, "kOperationTransmitDataIndirect value is incorrect"); + ValidateNextEnum(kOperationTransmitDataIndirect); #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - static_assert(kOperationTransmitDataCsl == 8, "TransmitDataCsl value is incorrect"); + ValidateNextEnum(kOperationTransmitDataCsl); #endif #endif + }; return kOperationStrings[aOperation]; } diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp index 67323bed4..eaecd8410 100644 --- a/src/core/mac/sub_mac.cpp +++ b/src/core/mac/sub_mac.cpp @@ -39,6 +39,7 @@ #include "common/code_utils.hpp" #include "instance/instance.hpp" +#include "utils/static_counter.hpp" namespace ot { namespace Mac { @@ -1010,32 +1011,26 @@ const char *SubMac::StateToString(State aState) #endif }; - static_assert(kStateDisabled == 0, "kStateDisabled value is not correct"); - static_assert(kStateSleep == 1, "kStateSleep value is not correct"); - static_assert(kStateReceive == 2, "kStateReceive value is not correct"); - static_assert(kStateCsmaBackoff == 3, "kStateCsmaBackoff value is not correct"); - static_assert(kStateTransmit == 4, "kStateTransmit value is not correct"); - static_assert(kStateEnergyScan == 5, "kStateEnergyScan value is not correct"); + struct StateValueChecker + { + InitEnumValidatorCounter(); + ValidateNextEnum(kStateDisabled); + ValidateNextEnum(kStateSleep); + ValidateNextEnum(kStateReceive); + ValidateNextEnum(kStateCsmaBackoff); + ValidateNextEnum(kStateTransmit); + ValidateNextEnum(kStateEnergyScan); #if OPENTHREAD_CONFIG_MAC_ADD_DELAY_ON_NO_ACK_ERROR_BEFORE_RETRY - static_assert(kStateDelayBeforeRetx == 6, "kStateDelayBeforeRetx value is not correct"); + ValidateNextEnum(kStateDelayBeforeRetx); +#endif #if !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - static_assert(kStateCslTransmit == 7, "kStateCslTransmit value is not correct"); + ValidateNextEnum(kStateCslTransmit); +#endif #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - static_assert(kStateCslSample == 8, "kStateCslSample value is not correct"); -#endif -#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - static_assert(kStateCslSample == 7, "kStateCslSample value is not correct"); -#endif - -#elif !OPENTHREAD_MTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - static_assert(kStateCslTransmit == 6, "kStateCslTransmit value is not correct"); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - static_assert(kStateCslSample == 7, "kStateCslSample value is not correct"); -#endif -#elif OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - static_assert(kStateCslSample == 6, "kStateCslSample value is not correct"); + ValidateNextEnum(kStateCslSample); #endif + }; return kStateStrings[aState]; } diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp index 8e182df16..c1df35128 100644 --- a/src/core/net/dns_client.cpp +++ b/src/core/net/dns_client.cpp @@ -31,6 +31,7 @@ #if OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE #include "instance/instance.hpp" +#include "utils/static_counter.hpp" /** * @file @@ -738,21 +739,22 @@ Client::Client(Instance &aInstance) , mUserDidSetDefaultAddress(false) #endif { - static_assert(kIp6AddressQuery == 0, "kIp6AddressQuery value is not correct"); + struct QueryTypeChecker + { + InitEnumValidatorCounter(); + + ValidateNextEnum(kIp6AddressQuery); #if OPENTHREAD_CONFIG_DNS_CLIENT_NAT64_ENABLE - static_assert(kIp4AddressQuery == 1, "kIp4AddressQuery value is not correct"); + ValidateNextEnum(kIp4AddressQuery); +#endif #if OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE - static_assert(kBrowseQuery == 2, "kBrowseQuery value is not correct"); - static_assert(kServiceQuerySrvTxt == 3, "kServiceQuerySrvTxt value is not correct"); - static_assert(kServiceQuerySrv == 4, "kServiceQuerySrv value is not correct"); - static_assert(kServiceQueryTxt == 5, "kServiceQueryTxt value is not correct"); -#endif -#elif OPENTHREAD_CONFIG_DNS_CLIENT_SERVICE_DISCOVERY_ENABLE - static_assert(kBrowseQuery == 1, "kBrowseQuery value is not correct"); - static_assert(kServiceQuerySrvTxt == 2, "kServiceQuerySrvTxt value is not correct"); - static_assert(kServiceQuerySrv == 3, "kServiceQuerySrv value is not correct"); - static_assert(kServiceQueryTxt == 4, "kServiceQuerySrv value is not correct"); + ValidateNextEnum(kBrowseQuery); + ValidateNextEnum(kServiceQuerySrvTxt); + ValidateNextEnum(kServiceQuerySrv); + ValidateNextEnum(kServiceQueryTxt); #endif + }; + #if OPENTHREAD_CONFIG_DNS_CLIENT_OVER_TCP_ENABLE ClearAllBytes(mSendLink); #endif diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index d2395d3e7..b288e5cd4 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -34,6 +34,7 @@ #include "mesh_forwarder.hpp" #include "instance/instance.hpp" +#include "utils/static_counter.hpp" namespace ot { @@ -1770,23 +1771,24 @@ const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aE const char *string = kMessageActionStrings[aAction]; - static_assert(kMessageReceive == 0, "kMessageReceive value is incorrect"); - static_assert(kMessageTransmit == 1, "kMessageTransmit value is incorrect"); - static_assert(kMessagePrepareIndirect == 2, "kMessagePrepareIndirect value is incorrect"); - static_assert(kMessageDrop == 3, "kMessageDrop value is incorrect"); - static_assert(kMessageReassemblyDrop == 4, "kMessageReassemblyDrop value is incorrect"); - static_assert(kMessageEvict == 5, "kMessageEvict value is incorrect"); + struct MessageActionChecker + { + InitEnumValidatorCounter(); + + ValidateNextEnum(kMessageReceive); + ValidateNextEnum(kMessageTransmit); + ValidateNextEnum(kMessagePrepareIndirect); + ValidateNextEnum(kMessageDrop); + ValidateNextEnum(kMessageReassemblyDrop); + ValidateNextEnum(kMessageEvict); #if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE - static_assert(kMessageMarkEcn == 6, "kMessageMarkEcn is incorrect"); - static_assert(kMessageQueueMgmtDrop == 7, "kMessageQueueMgmtDrop is incorrect"); + ValidateNextEnum(kMessageMarkEcn); + ValidateNextEnum(kMessageQueueMgmtDrop); +#endif #if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) - static_assert(kMessageFullQueueDrop == 8, "kMessageFullQueueDrop is incorrect"); -#endif -#else -#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0) - static_assert(kMessageFullQueueDrop == 6, "kMessageFullQueueDrop is incorrect"); -#endif + ValidateNextEnum(kMessageFullQueueDrop); #endif + }; if ((aAction == kMessageTransmit) && (aError != kErrorNone)) { diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 609cc4206..b2bd0a57d 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -34,6 +34,7 @@ #include "mle.hpp" #include "instance/instance.hpp" +#include "utils/static_counter.hpp" namespace ot { namespace Mle { @@ -4029,61 +4030,49 @@ const char *Mle::MessageTypeToString(MessageType aType) #endif }; - static_assert(kTypeAdvertisement == 0, "kTypeAdvertisement value is incorrect"); - static_assert(kTypeAnnounce == 1, "kTypeAnnounce value is incorrect"); - static_assert(kTypeChildIdRequest == 2, "kTypeChildIdRequest value is incorrect"); - static_assert(kTypeChildIdRequestShort == 3, "kTypeChildIdRequestShort value is incorrect"); - static_assert(kTypeChildIdResponse == 4, "kTypeChildIdResponse value is incorrect"); - static_assert(kTypeChildUpdateRequestAsChild == 5, "kTypeChildUpdateRequestAsChild value is incorrect"); - static_assert(kTypeChildUpdateResponseAsChild == 6, "kTypeChildUpdateResponseAsChild value is incorrect"); - static_assert(kTypeDataRequest == 7, "kTypeDataRequest value is incorrect"); - static_assert(kTypeDataResponse == 8, "kTypeDataResponse value is incorrect"); - static_assert(kTypeDiscoveryRequest == 9, "kTypeDiscoveryRequest value is incorrect"); - static_assert(kTypeDiscoveryResponse == 10, "kTypeDiscoveryResponse value is incorrect"); - static_assert(kTypeGenericDelayed == 11, "kTypeGenericDelayed value is incorrect"); - static_assert(kTypeGenericUdp == 12, "kTypeGenericUdp value is incorrect"); - static_assert(kTypeParentRequestToRouters == 13, "kTypeParentRequestToRouters value is incorrect"); - static_assert(kTypeParentRequestToRoutersReeds == 14, "kTypeParentRequestToRoutersReeds value is incorrect"); - static_assert(kTypeParentResponse == 15, "kTypeParentResponse value is incorrect"); + struct MessageTypeChecker + { + InitEnumValidatorCounter(); + + ValidateNextEnum(kTypeAdvertisement); + ValidateNextEnum(kTypeAnnounce); + ValidateNextEnum(kTypeChildIdRequest); + ValidateNextEnum(kTypeChildIdRequestShort); + ValidateNextEnum(kTypeChildIdResponse); + ValidateNextEnum(kTypeChildUpdateRequestAsChild); + ValidateNextEnum(kTypeChildUpdateResponseAsChild); + ValidateNextEnum(kTypeDataRequest); + ValidateNextEnum(kTypeDataResponse); + ValidateNextEnum(kTypeDiscoveryRequest); + ValidateNextEnum(kTypeDiscoveryResponse); + ValidateNextEnum(kTypeGenericDelayed); + ValidateNextEnum(kTypeGenericUdp); + ValidateNextEnum(kTypeParentRequestToRouters); + ValidateNextEnum(kTypeParentRequestToRoutersReeds); + ValidateNextEnum(kTypeParentResponse); #if OPENTHREAD_FTD - static_assert(kTypeAddressRelease == 16, "kTypeAddressRelease value is incorrect"); - static_assert(kTypeAddressReleaseReply == 17, "kTypeAddressReleaseReply value is incorrect"); - static_assert(kTypeAddressReply == 18, "kTypeAddressReply value is incorrect"); - static_assert(kTypeAddressSolicit == 19, "kTypeAddressSolicit value is incorrect"); - static_assert(kTypeChildUpdateRequestOfChild == 20, "kTypeChildUpdateRequestOfChild value is incorrect"); - static_assert(kTypeChildUpdateResponseOfChild == 21, "kTypeChildUpdateResponseOfChild value is incorrect"); - static_assert(kTypeChildUpdateResponseOfUnknownChild == 22, "kTypeChildUpdateResponseOfUnknownChild is incorrect"); - static_assert(kTypeLinkAccept == 23, "kTypeLinkAccept value is incorrect"); - static_assert(kTypeLinkAcceptAndRequest == 24, "kTypeLinkAcceptAndRequest value is incorrect"); - static_assert(kTypeLinkReject == 25, "kTypeLinkReject value is incorrect"); - static_assert(kTypeLinkRequest == 26, "kTypeLinkRequest value is incorrect"); - static_assert(kTypeParentRequest == 27, "kTypeParentRequest value is incorrect"); + ValidateNextEnum(kTypeAddressRelease); + ValidateNextEnum(kTypeAddressReleaseReply); + ValidateNextEnum(kTypeAddressReply); + ValidateNextEnum(kTypeAddressSolicit); + ValidateNextEnum(kTypeChildUpdateRequestOfChild); + ValidateNextEnum(kTypeChildUpdateResponseOfChild); + ValidateNextEnum(kTypeChildUpdateResponseOfUnknownChild); + ValidateNextEnum(kTypeLinkAccept); + ValidateNextEnum(kTypeLinkAcceptAndRequest); + ValidateNextEnum(kTypeLinkReject); + ValidateNextEnum(kTypeLinkRequest); + ValidateNextEnum(kTypeParentRequest); +#endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - static_assert(kTypeLinkMetricsManagementRequest == 28, "kTypeLinkMetricsManagementRequest value is incorrect)"); - static_assert(kTypeLinkMetricsManagementResponse == 29, "kTypeLinkMetricsManagementResponse value is incorrect)"); - static_assert(kTypeLinkProbe == 30, "kTypeLinkProbe value is incorrect)"); + ValidateNextEnum(kTypeLinkMetricsManagementRequest); + ValidateNextEnum(kTypeLinkMetricsManagementResponse); + ValidateNextEnum(kTypeLinkProbe); +#endif #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - static_assert(kTypeTimeSync == 31, "kTypeTimeSync value is incorrect"); + ValidateNextEnum(kTypeTimeSync); #endif -#else -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - static_assert(kTypeTimeSync == 28, "kTypeTimeSync value is incorrect"); -#endif -#endif -#else // OPENTHREAD_FTD -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - static_assert(kTypeLinkMetricsManagementRequest == 16, "kTypeLinkMetricsManagementRequest value is incorrect)"); - static_assert(kTypeLinkMetricsManagementResponse == 17, "kTypeLinkMetricsManagementResponse value is incorrect)"); - static_assert(kTypeLinkProbe == 18, "kTypeLinkProbe value is incorrect)"); -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - static_assert(kTypeTimeSync == 19, "kTypeTimeSync value is incorrect"); -#endif -#else -#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - static_assert(kTypeTimeSync == 16, "kTypeTimeSync value is incorrect"); -#endif -#endif -#endif // OPENTHREAD_FTD + }; return kMessageTypeStrings[aType]; } diff --git a/src/core/utils/static_counter.hpp b/src/core/utils/static_counter.hpp new file mode 100644 index 000000000..3c0713ab6 --- /dev/null +++ b/src/core/utils/static_counter.hpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file provides a compile time counter and utilities based on it. + */ + +#ifndef OT_UTILS_STATIC_COUNTER_HPP_ +#define OT_UTILS_STATIC_COUNTER_HPP_ + +namespace ot { + +template struct StaticInt : public StaticInt +{ +public: + static constexpr int kValue = N; +}; + +template <> struct StaticInt<0> +{ +public: + static constexpr int kValue = 0; +}; + +#define StaticCounterInit(N) static constexpr StaticInt StaticCounter(StaticInt) + +#define StaticCounterValue() decltype(StaticCounter(StaticInt<255>{}))::kValue + +#define StaticCounterIncr() \ + static constexpr StaticInt StaticCounter(StaticInt) + +#define InitEnumValidatorCounter() StaticCounterInit(0) + +#define ValidateNextEnum(kEnumartor) \ + static_assert(kEnumartor == StaticCounterValue(), #kEnumartor " value is incorrect"); \ + StaticCounterIncr() + +} // namespace ot + +#endif // OT_UTILS_STATIC_COUNTER_HPP_