From 70243796af841d558d3160c5ab94698671d017b3 Mon Sep 17 00:00:00 2001 From: Marc Auberer Date: Sun, 26 May 2024 00:42:46 +0200 Subject: [PATCH] Do not mark anonymous symbols as fields (#566) --- src/SourceFile.h | 16 ++++++++-------- src/symboltablebuilder/Lifecycle.h | 2 +- src/symboltablebuilder/Scope.cpp | 2 ++ src/symboltablebuilder/SymbolTable.cpp | 18 ++++++++++-------- src/symboltablebuilder/SymbolTable.h | 6 +++--- src/symboltablebuilder/SymbolTableEntry.cpp | 6 ++++-- src/symboltablebuilder/SymbolTableEntry.h | 2 +- src/typechecker/TypeChecker.cpp | 2 +- src/typechecker/TypeCheckerImplicit.cpp | 1 + .../symbol-table.json | 2 +- 10 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/SourceFile.h b/src/SourceFile.h index 3d3140452..e20dde997 100644 --- a/src/SourceFile.h +++ b/src/SourceFile.h @@ -6,14 +6,6 @@ #include #include -// Ignore some warnings in ANTLR generated code -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverloaded-virtual" -#include -#include -#include -#pragma GCC diagnostic pop - #include #include #include @@ -26,6 +18,14 @@ #include "../lib/thread-pool/thread-pool-utils.hpp" #include "../lib/thread-pool/thread-pool.hpp" +// Ignore some warnings in ANTLR generated code +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Woverloaded-virtual" +#include +#include +#include +#pragma GCC diagnostic pop + namespace spice::compiler { // Forward declarations diff --git a/src/symboltablebuilder/Lifecycle.h b/src/symboltablebuilder/Lifecycle.h index d7eb0f7cc..444ace10b 100644 --- a/src/symboltablebuilder/Lifecycle.h +++ b/src/symboltablebuilder/Lifecycle.h @@ -23,7 +23,7 @@ enum LifecycleState : uint8_t { */ struct LifecycleEvent { LifecycleState state; - ASTNode *issuer; + const ASTNode *issuer; }; /** diff --git a/src/symboltablebuilder/Scope.cpp b/src/symboltablebuilder/Scope.cpp index 0eb180793..b869f8762 100644 --- a/src/symboltablebuilder/Scope.cpp +++ b/src/symboltablebuilder/Scope.cpp @@ -298,6 +298,8 @@ size_t Scope::getFieldCount() const { assert(type == ScopeType::STRUCT); size_t fieldCount = 0; for (const auto &symbol : symbolTable.symbols) { + if (symbol.second.anonymous) + continue; const QualType &symbolType = symbol.second.getQualType(); if (symbolType.is(TY_IMPORT)) continue; diff --git a/src/symboltablebuilder/SymbolTable.cpp b/src/symboltablebuilder/SymbolTable.cpp index e3709e507..97a2b4d60 100644 --- a/src/symboltablebuilder/SymbolTable.cpp +++ b/src/symboltablebuilder/SymbolTable.cpp @@ -18,9 +18,11 @@ namespace spice::compiler { * @param declNode AST node where the symbol is declared * @return Inserted entry */ -SymbolTableEntry *SymbolTable::insert(const std::string &name, ASTNode *declNode) { - bool isGlobal = parent == nullptr; - size_t orderIndex = symbols.size(); +SymbolTableEntry *SymbolTable::insert(const std::string &name, ASTNode *declNode, bool isAnonymousSymbol) { + const bool isGlobal = parent == nullptr; + size_t orderIndex = SIZE_MAX; + if (!isAnonymousSymbol) + orderIndex = std::ranges::count_if(symbols, [](const auto &entry) { return !entry.second.anonymous; }); // Insert into symbols map. The type is 'dyn', because concrete types are determined by the type checker later on symbols.insert({name, SymbolTableEntry(name, QualType(TY_INVALID), scope, declNode, orderIndex, isGlobal)}); // Set entry to declared @@ -40,11 +42,11 @@ SymbolTableEntry *SymbolTable::insert(const std::string &name, ASTNode *declNode * Insert a new anonymous symbol into the current symbol table. * The anonymous symbol will be identified via the definition code location * - * @param type Type of the symbol + * @param qualType Type of the symbol * @param declNode AST node where the anonymous symbol is declared * @return Inserted entry */ -SymbolTableEntry *SymbolTable::insertAnonymous(const QualType &type, ASTNode *declNode, size_t numericSuffix) { +SymbolTableEntry *SymbolTable::insertAnonymous(const QualType &qualType, ASTNode *declNode, size_t numericSuffix) { // Check if the anonymous entry already exists if (SymbolTableEntry *anonSymbol = lookupAnonymous(declNode->codeLoc, numericSuffix)) return anonSymbol; @@ -53,8 +55,8 @@ SymbolTableEntry *SymbolTable::insertAnonymous(const QualType &type, ASTNode *de name << "anon." << declNode->codeLoc.toString(); if (numericSuffix > 0) name << "." << std::to_string(numericSuffix); - SymbolTableEntry *anonSymbol = insert(name.str(), declNode); - anonSymbol->updateType(type, false); + SymbolTableEntry *anonSymbol = insert(name.str(), declNode, true); + anonSymbol->updateType(qualType, false); anonSymbol->updateState(DECLARED, declNode); anonSymbol->updateState(INITIALIZED, declNode); anonSymbol->anonymous = true; @@ -67,6 +69,7 @@ SymbolTableEntry *SymbolTable::insertAnonymous(const QualType &type, ASTNode *de * * @param originalName Original symbol name * @param newName New symbol name + * @return Copied entry */ SymbolTableEntry *SymbolTable::copySymbol(const std::string &originalName, const std::string &newName) { SymbolTableEntry *entryToCopy = lookupStrict(originalName); @@ -106,7 +109,6 @@ SymbolTableEntry *SymbolTable::lookup(const std::string &name) { // NOLINT(misc- captures.insert({name, Capture(entry)}); } } - return entry; } diff --git a/src/symboltablebuilder/SymbolTable.h b/src/symboltablebuilder/SymbolTable.h index 1f2326b3a..fa4443a1f 100644 --- a/src/symboltablebuilder/SymbolTable.h +++ b/src/symboltablebuilder/SymbolTable.h @@ -22,7 +22,7 @@ class Type; struct CodeLoc; using CaptureMap = std::unordered_map; -using SymbolMap = std::unordered_map; +using SymbolMap = std::unordered_map; /** * Class for storing information about symbols of the program. @@ -38,8 +38,8 @@ class SymbolTable { friend class Scope; // Public methods - SymbolTableEntry *insert(const std::string &name, ASTNode *declNode); - SymbolTableEntry *insertAnonymous(const QualType &type, ASTNode *declNode, size_t numericSuffix = 0); + SymbolTableEntry *insert(const std::string &name, ASTNode *declNode, bool isAnonymousSymbol = false); + SymbolTableEntry *insertAnonymous(const QualType &qualType, ASTNode *declNode, size_t numericSuffix = 0); SymbolTableEntry *copySymbol(const std::string &originalName, const std::string &newName); SymbolTableEntry *lookup(const std::string &symbolName); SymbolTableEntry *lookupStrict(const std::string &symbolName); diff --git a/src/symboltablebuilder/SymbolTableEntry.cpp b/src/symboltablebuilder/SymbolTableEntry.cpp index 3aa80d060..c9d4170c1 100644 --- a/src/symboltablebuilder/SymbolTableEntry.cpp +++ b/src/symboltablebuilder/SymbolTableEntry.cpp @@ -37,7 +37,7 @@ void SymbolTableEntry::updateType(const QualType &newType, [[maybe_unused]] bool * @param node AST node where the update takes place * @param force Force update. This can only be used compiler-internal */ -void SymbolTableEntry::updateState(const LifecycleState &newState, ASTNode *node, bool force) { +void SymbolTableEntry::updateState(const LifecycleState &newState, const ASTNode *node, bool force) { const LifecycleState oldState = lifecycle.getCurrentState(); // Check if this is a constant variable and is already initialized if (newState != DEAD && oldState != DECLARED && qualType.isConst() && !force) // GCOV_EXCL_LINE @@ -102,7 +102,9 @@ void SymbolTableEntry::popAddress() { * * @return Struct field or not */ -bool SymbolTableEntry::isField() const { return scope->type == ScopeType::STRUCT && orderIndex < scope->getFieldCount(); } +bool SymbolTableEntry::isField() const { + return scope->type == ScopeType::STRUCT && orderIndex < scope->getFieldCount() && !anonymous; +} /** * Stringify the current symbol to a human-readable form. Used to dump whole symbol tables with their contents. diff --git a/src/symboltablebuilder/SymbolTableEntry.h b/src/symboltablebuilder/SymbolTableEntry.h index b418a4f68..4d0762896 100644 --- a/src/symboltablebuilder/SymbolTableEntry.h +++ b/src/symboltablebuilder/SymbolTableEntry.h @@ -35,7 +35,7 @@ class SymbolTableEntry { // Public methods [[nodiscard]] const QualType &getQualType() const; void updateType(const QualType &newType, bool overwriteExistingType); - void updateState(const LifecycleState &newState, ASTNode *node, bool force = false); + void updateState(const LifecycleState &newState, const ASTNode *node, bool force = false); [[nodiscard]] const CodeLoc &getDeclCodeLoc() const; [[nodiscard]] virtual llvm::Value *getAddress() const; void updateAddress(llvm::Value *address); diff --git a/src/typechecker/TypeChecker.cpp b/src/typechecker/TypeChecker.cpp index d640851a8..1affed176 100644 --- a/src/typechecker/TypeChecker.cpp +++ b/src/typechecker/TypeChecker.cpp @@ -1378,7 +1378,7 @@ std::any TypeChecker::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) { const QualType memberType = memberEntry->getQualType(); // Check for insufficient visibility - if (structScope->isImportedBy(rootScope) && !memberEntry->getQualType().isPublic()) + if (structScope->isImportedBy(rootScope) && !memberEntry->getQualType().getBase().isPublic()) SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Cannot access field '" + fieldName + "' due to its private visibility") // Set field to used diff --git a/src/typechecker/TypeCheckerImplicit.cpp b/src/typechecker/TypeCheckerImplicit.cpp index 306cd6fcb..2a3f0be38 100644 --- a/src/typechecker/TypeCheckerImplicit.cpp +++ b/src/typechecker/TypeCheckerImplicit.cpp @@ -81,6 +81,7 @@ void TypeChecker::createDefaultCtorIfRequired(const Struct &spiceStruct, Scope * bool hasFieldsToConstruct = false; for (size_t i = 0; i < fieldCount; i++) { SymbolTableEntry *fieldSymbol = structScope->symbolTable.lookupStrictByIndex(i); + assert(fieldSymbol != nullptr); const QualType &thisType = fieldSymbol->getQualType(); // Abort if we have a field, that is a reference diff --git a/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json b/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json index 0426482ca..237939add 100644 --- a/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json +++ b/test/test-files/typechecker/foreach-loops/success-foreach-item-type-inference/symbol-table.json @@ -353,7 +353,7 @@ "isGlobal": false, "isVolatile": false, "name": "anon.L30C24", - "orderIndex": 1, + "orderIndex": 18446744073709551615, "state": "initialized", "type": "MockIterator" },