/******************************************************************************** * Copyright (c) 2025-2026 ZF Friedrichshafen AG * * This program and the accompanying materials are made available under the * terms of the Apache License Version 2.0 which is available at * https://www.apache.org/licenses/LICENSE-2.0 * * SPDX-License-Identifier: Apache-2.0 * * Contributors: * Erik Verhoeven - initial API and implementation ********************************************************************************/ #include "enum_entity.h" #include "entity_value.h" #include "typedef_entity.h" #include "../exception.h" #include CEnumEntry::CEnumEntry(const CContextPtr& rptrContext, CEntityPtr ptrParent) : CDeclarationEntity(rptrContext, ptrParent) {} std::string CEnumEntry::GetDeclTypeStr(bool /*bResolveTypedef*/) const { return GetScopedName(); } void CEnumEntry::Process() { // Get the base type of the enum entity and insert it in front of the declaration. const CEnumEntity* pEnumEntity = GetParentEntity()->Get(); if (!pEnumEntity) throw CCompileException("Internal error: expected an enum entity as parent."); CToken token(DeclTypeToString(pEnumEntity->GetEnumType())); PrependToken(token); // Process as if normal declaration CDeclarationEntity::Process(); } CEnumEntity::CEnumEntity(const CContextPtr& rptrContext, CEntityPtr ptrParent) : CDefinitionEntity(rptrContext, ptrParent) { m_typedecl.SetBaseType(sdv::idl::EDeclType::decltype_long); } sdv::interface_t CEnumEntity::GetInterface(sdv::interface_id idInterface) { if (idInterface == sdv::GetInterfaceId()) return static_cast(this); if (idInterface == sdv::GetInterfaceId()) return static_cast(this); return CDefinitionEntity::GetInterface(idInterface); } std::string CEnumEntity::GetDeclTypeStr(bool /*bResolveTypedef*/) const { return std::string("enum ") + GetScopedName(); } void CEnumEntity::GetBaseType(sdv::idl::EDeclType& reType, sdv::IInterfaceAccess*& rpType) const { reType = m_typedecl.GetBaseType(); rpType = m_typedecl.GetTypeDefinition(); } void CEnumEntity::Process() { // The definition and declaration can be defined: // enum ; --> forward declaration // enum {...}; --> enum definition // ; --> enum variable declaration // = ; --> enum variable declaration and assignment // enum ; --> enum variable declaration // enum = ; --> enum variable declaration and assignment // enum {...} ; --> enum definition and variable declaration // enum {...} = ; --> enum definition, variable declaration and assignment // enum {...} ; --> anonymous enum definition and variable declaration // enum {...} = ; --> anonymous enum definition, variable declaration and assignment // const enum = ; // const = ; // const enum {...} = ; // typedef ; // typedef enum {...} ; // typedef ; // typedef enum {...} ; // typedef enum {...} ; CDefinitionEntity::Process(); // If supported create the value node for the definition (this allows assignments of values to this entity). CreateValueNode(); } void CEnumEntity::ProcessDefinitionAddendum() { // Check for inheritance CToken token = GetToken(); if (token != ":") { PrependToken(token); return; } CLog log("Processing inheritance type..."); // Process the type m_typedecl = ProcessType(); // The base type must be an integral type and not an enum. if (!IsIntegralDeclType(m_typedecl.GetBaseType()) && m_typedecl.GetBaseType() != sdv::idl::EDeclType::decltype_enum) throw CCompileException("Expecting an integral type to inherit from."); } void CEnumEntity::ProcessContent() { CLog log("Processing definition content..."); // An enum definition consists of one declaration statement with entries separated by a comma. CToken token = PeekToken(); if (!token) return; if (token == "}") return; // Expecting an enum entry CEntityPtr ptrEntry = CreateChild(token.GetContext(), this); if (!ptrEntry) throw CCompileException("Internal error: could not create enum entry."); ptrEntry->Process(); // The entries should reside in the const members list // Check the values and create values where none is declared. // Separate between signed and unsigned. int64_t iSignedNext = 0; std::set setSigned; uint64_t uiUnsignedNext = 0; std::set setUnsigned; for (CEntityPtr ptrMember : m_lstConstMembers) { CEnumEntry* pEntry = ptrMember->Get(); if (!pEntry) throw CCompileException("Internal error: expected only enum entries in an enumeration."); // Do post processing pEntry->PostProcess(); // Get the value from the entity; if one was assigned. CSimpleTypeValueNode* pValue = pEntry->ValueRef() ? pEntry->ValueRef()->Get() : nullptr; if (!pValue) throw CCompileException("The value for '", ptrEntry->GetName(), "' must be a system type value."); // Deal with signed and unsigned values if (IsSignedDeclType(m_typedecl.GetBaseType())) { // Is a value assigned? if (pValue->IsDefined()) { // Check whether the value is already in use. int64_t iValue = pValue->Variant().Get(); if (setSigned.find(iValue) != setSigned.end()) throw CCompileException("The value for '", ptrEntry->GetName(), "' is already defined for another entry."); // Store the value setSigned.insert(iValue); iSignedNext = iValue + 1; } else { // Get the next available value while (setSigned.find(iSignedNext) != setSigned.end()) iSignedNext++; // Create a value assignment CTokenList lstValueTokens; lstValueTokens.push_back(CToken(std::to_string(iSignedNext), ETokenLiteralType::token_literal_dec_integer)); pValue->SetFixedValue(iSignedNext, lstValueTokens); // Store the value setSigned.insert(iSignedNext); iSignedNext++; } } else { // Is a value assigned? if (pValue->IsDefined()) { // Check whether the value is already in use. uint64_t uiValue = pValue->Variant().Get(); if (setUnsigned.find(uiValue) != setUnsigned.end()) throw CCompileException("The value for '", ptrEntry->GetName(), "' is already defined for another entry."); // Store the value setUnsigned.insert(uiValue); uiUnsignedNext = uiValue + 1; } else { // Get the next available value while (setUnsigned.find(uiUnsignedNext) != setUnsigned.end()) uiUnsignedNext++; // Create a value assignment CTokenList lstValueTokens; lstValueTokens.push_back(CToken(std::to_string(uiUnsignedNext), ETokenLiteralType::token_literal_dec_integer)); pValue->SetFixedValue(uiUnsignedNext, lstValueTokens); // Store the value setUnsigned.insert(uiUnsignedNext); iSignedNext++; } } } } bool CEnumEntity::Supports(EDefinitionSupport eSupport) const { switch (eSupport) { case EDefinitionSupport::support_enum_entry: return true; default: return false; } } void CEnumEntity::CreateValueNode() { // Create a simple type value node for this definition. ValueRef() = std::make_shared(shared_from_this(), nullptr); }