diff --git a/C/CMakeLists.txt b/C/CMakeLists.txt index 9cd8c0fc..5213493f 100644 --- a/C/CMakeLists.txt +++ b/C/CMakeLists.txt @@ -174,13 +174,14 @@ set(CFE_SOURCES ${PROJECT_SOURCE_DIR}/binder/Binder.cpp ${PROJECT_SOURCE_DIR}/binder/Binder_Declarators.cpp ${PROJECT_SOURCE_DIR}/binder/Binder_Specifiers.cpp + ${PROJECT_SOURCE_DIR}/binder/Binder_End.cpp ${PROJECT_SOURCE_DIR}/binder/DiagnosticsReporter_Binder.cpp ${PROJECT_SOURCE_DIR}/binder/NameSpace.h ${PROJECT_SOURCE_DIR}/binder/Scope.h ${PROJECT_SOURCE_DIR}/binder/Scope.cpp ${PROJECT_SOURCE_DIR}/binder/ScopeKind.h - ${PROJECT_SOURCE_DIR}/binder/DeclarationResolver.h - ${PROJECT_SOURCE_DIR}/binder/DeclarationResolver.cpp + ${PROJECT_SOURCE_DIR}/binder/TypeResolver.h + ${PROJECT_SOURCE_DIR}/binder/TypeResolver.cpp # Types ${PROJECT_SOURCE_DIR}/types/Type.h @@ -191,6 +192,8 @@ set(CFE_SOURCES ${PROJECT_SOURCE_DIR}/types/Type_Basic.cpp ${PROJECT_SOURCE_DIR}/types/Type_Function.h ${PROJECT_SOURCE_DIR}/types/Type_Function.cpp + ${PROJECT_SOURCE_DIR}/types/Type_Qualified.h + ${PROJECT_SOURCE_DIR}/types/Type_Qualified.cpp ${PROJECT_SOURCE_DIR}/types/Type_Pointer.h ${PROJECT_SOURCE_DIR}/types/Type_Pointer.cpp ${PROJECT_SOURCE_DIR}/types/Type_Typedef.h @@ -234,8 +237,8 @@ set(CFE_SOURCES ${PROJECT_SOURCE_DIR}/tests/ParserTester_3000_3999.cpp ${PROJECT_SOURCE_DIR}/tests/ReparserTester.h ${PROJECT_SOURCE_DIR}/tests/ReparserTester.cpp - ${PROJECT_SOURCE_DIR}/tests/DeclarationResolverTester.h - ${PROJECT_SOURCE_DIR}/tests/DeclarationResolverTester.cpp + ${PROJECT_SOURCE_DIR}/tests/TypeResolverTester.h + ${PROJECT_SOURCE_DIR}/tests/TypeResolverTester.cpp ${PROJECT_SOURCE_DIR}/tests/SemanticModelTester.h ${PROJECT_SOURCE_DIR}/tests/SemanticModelTester.cpp ${PROJECT_SOURCE_DIR}/tests/TestExpectation.h diff --git a/C/Fwds.h b/C/Fwds.h index c8fe7b6b..1357737c 100644 --- a/C/Fwds.h +++ b/C/Fwds.h @@ -240,6 +240,7 @@ class PointerType; class TypedefType; class TagType; class VoidType; +class QualifiedType; /* Scopes */ class Scope; diff --git a/C/binder/Binder.cpp b/C/binder/Binder.cpp index cf5ffdff..15f1bb94 100644 --- a/C/binder/Binder.cpp +++ b/C/binder/Binder.cpp @@ -174,45 +174,24 @@ SyntaxVisitor::Action Binder::visitStructOrUnionDeclaration(const StructOrUnionD return visitStructOrUnionDeclaration_AtSpecifier(node); } -SyntaxVisitor::Action Binder::visitStructOrUnionDeclaration_AtEnd(const StructOrUnionDeclarationSyntax* node) -{ - return visitDeclaration_AtEnd_COMMON(node); -} - SyntaxVisitor::Action Binder::visitTypedefDeclaration(const TypedefDeclarationSyntax* node) { return visitTypedefDeclaration_AtSpecifier(node); } -SyntaxVisitor::Action Binder::visitTypedefDeclaration_AtEnd(const TypedefDeclarationSyntax* node) -{ - popTy(); - - return Action::Skip; -} - SyntaxVisitor::Action Binder::visitEnumDeclaration(const EnumDeclarationSyntax* node) { return visitEnumDeclaration_AtSpecifier(node); } -SyntaxVisitor::Action Binder::visitEnumDeclaration_AtEnd(const EnumDeclarationSyntax* node) -{ - return visitDeclaration_AtEnd_COMMON(node); -} - SyntaxVisitor::Action Binder::visitVariableAndOrFunctionDeclaration( const VariableAndOrFunctionDeclarationSyntax* node) { - return visitVariableAndOrFunctionDeclaration_AtSpecifiers(node); -} - -SyntaxVisitor::Action Binder::visitVariableAndOrFunctionDeclaration_AtEnd( - const VariableAndOrFunctionDeclarationSyntax* node) -{ - popTy(); - - return Action::Skip; + TyContT tys; + std::swap(tys_, tys); + auto action = visitVariableAndOrFunctionDeclaration_AtSpecifiers(node); + std::swap(tys_, tys); + return action; } SyntaxVisitor::Action Binder::visitFieldDeclaration(const FieldDeclarationSyntax* node) @@ -220,34 +199,16 @@ SyntaxVisitor::Action Binder::visitFieldDeclaration(const FieldDeclarationSyntax return visitFieldDeclaration_AtSpecifiers(node); } -SyntaxVisitor::Action Binder::visitFieldDeclaration_AtEnd(const FieldDeclarationSyntax* node) -{ - popTy(); - - return Action::Skip; -} - SyntaxVisitor::Action Binder::visitEnumeratorDeclaration(const EnumeratorDeclarationSyntax* node) { return visitEnumeratorDeclaration_AtImplicitSpecifier(node); } -SyntaxVisitor::Action Binder::visitEnumeratorDeclaration_AtEnd(const EnumeratorDeclarationSyntax* node) -{ - popTy(); - return visitDeclaration_AtEnd_COMMON(node); -} - SyntaxVisitor::Action Binder::visitParameterDeclaration(const ParameterDeclarationSyntax* node) { return visitParameterDeclaration_AtSpecifiers(node); } -SyntaxVisitor::Action Binder::visitParameterDeclaration_AtEnd(const ParameterDeclarationSyntax* node) -{ - return visitDeclaration_AtEnd_COMMON(node); -} - SyntaxVisitor::Action Binder::visitStaticAssertDeclaration(const StaticAssertDeclarationSyntax*) { return Action::Skip; @@ -258,21 +219,6 @@ SyntaxVisitor::Action Binder::visitFunctionDefinition(const FunctionDefinitionSy return visitFunctionDefinition_AtSpecifiers(node); } -SyntaxVisitor::Action Binder::visitFunctionDefinition_AtEnd(const FunctionDefinitionSyntax* node) -{ - return Action::Skip; -} - -SyntaxVisitor::Action Binder::visitDeclaration_AtEnd_COMMON(const DeclarationSyntax* node) -{ - auto decl = popSymAsDecl(); - PSY_ASSERT(decl, return Action::Quit); - SCOPE_AT_TOP(scope); - scope->addDeclaration(decl->asDeclarationSymbol()); - - return Action::Skip; -} - //------------// // Statements // //------------// diff --git a/C/binder/Binder.h b/C/binder/Binder.h index a5da7a4b..9f22f2de 100644 --- a/C/binder/Binder.h +++ b/C/binder/Binder.h @@ -90,6 +90,7 @@ class PSY_C_INTERNAL_API Binder final : protected SyntaxVisitor std::stack pendingFunTys_; Type* popTy(); void pushTy(Type*); + template TyT* makeTy(TyTArgs... args); bool decltorIsOfTydef_; @@ -219,7 +220,7 @@ SymT* Binder::makeAndBindSym(const SyntaxNode* node, SymTArgs... args) syms_.top(), scopes_.top(), std::forward(args)...)); - return static_cast(semaModel_->keepAndBindDecl(node, std::move(sym))); + return static_cast(semaModel_->keepBinding(node, std::move(sym))); } template diff --git a/C/binder/Binder_Declarators.cpp b/C/binder/Binder_Declarators.cpp index bb4b7314..041e514c 100644 --- a/C/binder/Binder_Declarators.cpp +++ b/C/binder/Binder_Declarators.cpp @@ -59,8 +59,10 @@ SyntaxVisitor::Action Binder::typeSymAtTopAndPopIt() TY_AT_TOP(ty); - if (!pendingFunTys_.empty()) + if (!pendingFunTys_.empty()) { + PSY_ASSERT(!pendingFunTys_.empty(), return Action::Quit); pendingFunTys_.top()->addParameterType(ty); + } switch (ty->kind()) { case TypeKind::Array: @@ -73,6 +75,7 @@ SyntaxVisitor::Action Binder::typeSymAtTopAndPopIt() case TypeKind::Tag: case TypeKind::Basic: case TypeKind::Void: + case TypeKind::Qualified: break; } @@ -208,12 +211,14 @@ SyntaxVisitor::Action Binder::visitArrayOrFunctionDeclarator(const ArrayOrFuncti case TypeKind::Pointer: case TypeKind::Basic: case TypeKind::Void: + case TypeKind::Qualified: case TypeKind::Tag: case TypeKind::Typedef: break; } - pushTy(makeTy(ty)); - pendingFunTys_.push(tys_.top()->asFunctionType()); + auto funcTy = makeTy(ty); + pushTy(funcTy); + pendingFunTys_.push(funcTy); break; } @@ -285,6 +290,8 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod case TypeKind::Array: case TypeKind::Pointer: case TypeKind::Basic: + case TypeKind::Void: + case TypeKind::Qualified: case TypeKind::Typedef: case TypeKind::Tag: { SYM_AT_TOP(sym); @@ -325,9 +332,6 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod } break; } - - default: - PSY_ESCAPE_VIA_RETURN(Action::Quit); } break; } @@ -346,8 +350,8 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod */ popTy(); TY_AT_TOP(otherTy); - pushTy(makeTy(otherTy)); - auto ptrTy = tys_.top()->asPointerType(); + auto ptrTy = makeTy(otherTy); + pushTy(ptrTy); ptrTy->markAsArisingFromArrayDecay(); break; } @@ -358,8 +362,8 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod * A declaration of a parameter as “function returning type” * shall be adjusted to “pointer to function returning type”... */ - pushTy(makeTy(ty)); - auto ptrTy = tys_.top()->asPointerType(); + auto ptrTy = makeTy(ty); + pushTy(ptrTy); ptrTy->markAsArisingFromFunctionDecay(); break; } @@ -367,6 +371,7 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod case TypeKind::Pointer: case TypeKind::Basic: case TypeKind::Void: + case TypeKind::Qualified: case TypeKind::Typedef: case TypeKind::Tag: break; @@ -385,9 +390,10 @@ SyntaxVisitor::Action Binder::visitSimpleDeclarator_COMMON(const SyntaxNode* nod SyntaxVisitor::Action Binder::visitIdentifierDeclarator(const IdentifierDeclaratorSyntax* node) { if (decltorIsOfTydef_) { - auto tydefTy = makeTy(lexemeOrEmptyIdent(node->identifierToken())); - auto tydef = makeAndBindSym(node, tydefTy); + TY_AT_TOP(ty); SCOPE_AT_TOP(scope); + auto tydefTy = makeTy(lexemeOrEmptyIdent(node->identifierToken())); + auto tydef = makeAndBindSym(node, tydefTy, ty); scope->addDeclaration(tydef); } else { diff --git a/C/binder/Binder_End.cpp b/C/binder/Binder_End.cpp new file mode 100644 index 00000000..18ac2d5c --- /dev/null +++ b/C/binder/Binder_End.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2021/22 Leandro T. C. Melo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "Binder.h" +#include "Binder__MACROS__.inc" + +#include "SyntaxTree.h" + +#include "binder/Scope.h" +#include "compilation/Compilation.h" +#include "symbols/Symbol_ALL.h" +#include "syntax/SyntaxFacts.h" +#include "syntax/Lexeme_ALL.h" +#include "syntax/SyntaxNodes.h" +#include "syntax/SyntaxUtilities.h" +#include "types/Type_ALL.h" + +#include "../common/infra/Assertions.h" + +#include + +using namespace psy; +using namespace C; + +SyntaxVisitor::Action Binder::visitStructOrUnionDeclaration_AtEnd(const StructOrUnionDeclarationSyntax* node) +{ + return visitDeclaration_AtEnd_COMMON(node); +} + +SyntaxVisitor::Action Binder::visitEnumDeclaration_AtEnd(const EnumDeclarationSyntax* node) +{ + return visitDeclaration_AtEnd_COMMON(node); +} + +SyntaxVisitor::Action Binder::visitTypedefDeclaration_AtEnd(const TypedefDeclarationSyntax* node) +{ + popTy(); + return Action::Skip; +} + +SyntaxVisitor::Action Binder::visitVariableAndOrFunctionDeclaration_AtEnd( + const VariableAndOrFunctionDeclarationSyntax* node) +{ + popTy(); + return Action::Skip; +} + +SyntaxVisitor::Action Binder::visitFieldDeclaration_AtEnd(const FieldDeclarationSyntax* node) +{ + popTy(); + return Action::Skip; +} + +SyntaxVisitor::Action Binder::visitEnumeratorDeclaration_AtEnd(const EnumeratorDeclarationSyntax* node) +{ + popTy(); + return visitDeclaration_AtEnd_COMMON(node); +} + +SyntaxVisitor::Action Binder::visitParameterDeclaration_AtEnd(const ParameterDeclarationSyntax* node) +{ + return visitDeclaration_AtEnd_COMMON(node); +} + +SyntaxVisitor::Action Binder::visitDeclaration_AtEnd_COMMON(const DeclarationSyntax* node) +{ + auto decl = popSymAsDecl(); + PSY_ASSERT(decl, return Action::Quit); + SCOPE_AT_TOP(scope); + scope->addDeclaration(decl->asDeclarationSymbol()); + + return Action::Skip; +} + +SyntaxVisitor::Action Binder::visitFunctionDefinition_AtEnd(const FunctionDefinitionSyntax* node) +{ + return Action::Skip; +} diff --git a/C/binder/Binder_Specifiers.cpp b/C/binder/Binder_Specifiers.cpp index fed7aca8..3878f7bf 100644 --- a/C/binder/Binder_Specifiers.cpp +++ b/C/binder/Binder_Specifiers.cpp @@ -215,7 +215,7 @@ SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSy return Action::Skip; } - auto ty = tys_.top(); + TY_AT_TOP(ty); if (ty->kind() != TypeKind::Basic) { //diagReporter_. return Action::Skip; @@ -402,26 +402,39 @@ SyntaxVisitor::Action Binder::visitTypedefName(const TypedefNameSyntax* node) SyntaxVisitor::Action Binder::visitTypeQualifier(const TypeQualifierSyntax* node) { + QualifiedType* qualTy = nullptr; TY_AT_TOP(ty); + switch (ty->kind()) { + case TypeKind::Qualified: + qualTy = ty->asQualifiedType(); + break; + + default: + qualTy = makeTy(ty); + pushTy(qualTy); + break; + } + PSY_ASSERT(qualTy, return Action::Quit); + const auto tyQualTk = node->qualifierKeyword(); switch (tyQualTk.kind()) { case SyntaxKind::Keyword_const: - ty->qualifyWithConst(); + qualTy->qualifyWithConst(); break; case SyntaxKind::Keyword_volatile: - ty->qualifyWithVolatile(); + qualTy->qualifyWithVolatile(); break; case SyntaxKind::Keyword_restrict: - if (ty->kind() == TypeKind::Pointer) - ty->qualifyWithRestrict(); + if (qualTy->unqualifiedType()->kind() == TypeKind::Pointer) + qualTy->qualifyWithRestrict(); else diagReporter_.InvalidUseOfRestrict(tyQualTk); break; case SyntaxKind::Keyword__Atomic: - ty->qualifyWithAtomic(); + qualTy->qualifyWithAtomic(); break; default: diff --git a/C/binder/DeclarationResolver.cpp b/C/binder/DeclarationResolver.cpp deleted file mode 100644 index 70b53a40..00000000 --- a/C/binder/DeclarationResolver.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2024 Leandro T. C. Melo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include "DeclarationResolver.h" - -#include "binder/Scope.h" -#include "compilation/SemanticModel.h" -#include "symbols/Symbol_ALL.h" -#include "syntax/Lexeme_Identifier.h" -#include "syntax/SyntaxNodes.h" -#include "types/Type_ALL.h" - -#include - -using namespace psy; -using namespace C; - -DeclarationResolver::DeclarationResolver(SemanticModel* semaModel, const SyntaxTree* tree) - : SyntaxVisitor(tree) - , semaModel_(semaModel) -{} - -void DeclarationResolver::resolveDeclarations() -{ - visit(tree_->root()); -} - -SyntaxVisitor::Action DeclarationResolver::visitTranslationUnit(const TranslationUnitSyntax* node) -{ - for (auto declIt = node->declarations(); declIt; declIt = declIt->next) - visit(declIt->value); - - return Action::Skip; -} - -SyntaxVisitor::Action DeclarationResolver::visitVariableAndOrFunctionDeclaration(const VariableAndOrFunctionDeclarationSyntax* node) -{ - for (auto decltorIt = node->declarators(); decltorIt; decltorIt = decltorIt->next) { - visit(decltorIt->value); - } - - return Action::Skip; -} - -SyntaxVisitor::Action DeclarationResolver::visitIdentifierDeclarator(const IdentifierDeclaratorSyntax* node) -{ - auto decl = semaModel_->declarationOf(node); - if (decl) { - switch (decl->kind()) { - case DeclarationSymbolKind::Function: - break; - - case DeclarationSymbolKind::Object: { - auto objDecl = decl->asObjectDeclarationSymbol(); - auto ty = objDecl->type(); - switch (ty->kind()) { - case TypeKind::Typedef: { - auto tydefName = ty->asTypedefType()->typedefName(); - auto tyDecl = decl->enclosingScope()->searchForDeclaration( - tydefName, - NameSpace::OrdinaryIdentifiers); - if (tyDecl) { - // TODO - std::cout << "got it " << std::endl; - } - break; - } - - default: - break; - } - break; - } - - case DeclarationSymbolKind::Type: - break; - } - } - - return Action::Skip; -} diff --git a/C/binder/TypeResolver.cpp b/C/binder/TypeResolver.cpp new file mode 100644 index 00000000..63dd4eef --- /dev/null +++ b/C/binder/TypeResolver.cpp @@ -0,0 +1,178 @@ +// Copyright (c) 2024 Leandro T. C. Melo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "TypeResolver.h" + +#include "binder/Scope.h" +#include "compilation/SemanticModel.h" +#include "symbols/Symbol_ALL.h" +#include "syntax/Lexeme_Identifier.h" +#include "syntax/SyntaxNodes.h" +#include "types/Type_ALL.h" + +#include + +using namespace psy; +using namespace C; + +TypeResolver::TypeResolver(SemanticModel* semaModel, const SyntaxTree* tree) + : SyntaxVisitor(tree) + , semaModel_(semaModel) +{} + +void TypeResolver::resolveTypes() +{ + visit(tree_->root()); +} + +SyntaxVisitor::Action TypeResolver::visitTranslationUnit(const TranslationUnitSyntax* node) +{ + for (auto declIt = node->declarations(); declIt; declIt = declIt->next) + visit(declIt->value); + + return Action::Skip; +} + +SyntaxVisitor::Action TypeResolver::visitVariableAndOrFunctionDeclaration( + const VariableAndOrFunctionDeclarationSyntax* node) +{ + for (auto decltorIt = node->declarators(); decltorIt; decltorIt = decltorIt->next) { + visit(decltorIt->value); + } + + return Action::Skip; +} + +SyntaxVisitor::Action TypeResolver::visitDeclarator_COMMON(const DeclaratorSyntax* node) +{ + auto decl = semaModel_->declaredDeclaration(node); + if (decl) { + switch (decl->kind()) { + case DeclarationSymbolKind::Function: + break; + + case DeclarationSymbolKind::Object: { + auto objDecl = decl->asObjectDeclarationSymbol(); + auto ty = objDecl->type(); + auto resolvedTy = resolveType(ty, decl->enclosingScope()); + if (resolvedTy != ty) { + objDecl->setType(resolvedTy); + semaModel_->dropType(ty); + } + break; + } + + case DeclarationSymbolKind::Type: { + auto tyDecl = decl->asTypeDeclarationSymbol(); + PSY_ASSERT(tyDecl->kind() == TypeDeclarationSymbolKind::Typedef, + return Action::Quit); + break; + } + } + } + + return Action::Skip; +} + +SyntaxVisitor::Action TypeResolver::visitPointerDeclarator( + const PointerDeclaratorSyntax* node) +{ + return visitDeclarator_COMMON(node); +} + +SyntaxVisitor::Action TypeResolver::visitParenthesizedDeclarator( + const ParenthesizedDeclaratorSyntax* node) +{ + return visitDeclarator_COMMON(node->innerDeclarator()); +} + +SyntaxVisitor::Action TypeResolver::visitIdentifierDeclarator(const IdentifierDeclaratorSyntax* node) +{ + return visitDeclarator_COMMON(node); +} + +const Type* TypeResolver::resolveType(const Type* ty, const Scope* scope) const +{ + switch (ty->kind()) { + case TypeKind::Array: { + auto arrTy = ty->asArrayType(); + auto elemTy = arrTy->elementType(); + auto resolvedTy = resolveType(elemTy, scope); + if (resolvedTy != elemTy) + arrTy->resetElementType(resolvedTy); + break; + } + + case TypeKind::Basic: + case TypeKind::Void: + break; + + case TypeKind::Function: + break; + + case TypeKind::Pointer: { + auto ptrTy = ty->asPointerType(); + auto refedTy = ptrTy->referencedType(); + auto resolvedTy = resolveType(refedTy, scope); + if (resolvedTy != refedTy) + ptrTy->resetReferencedType(resolvedTy); + break; + } + + case TypeKind::Typedef: { + auto tydefName = ty->asTypedefType()->typedefName(); + auto decl = scope->searchForDeclaration( + tydefName, + NameSpace::OrdinaryIdentifiers); + if (decl) { + if (decl->kind() == DeclarationSymbolKind::Type) { + auto tyDecl = decl->asTypeDeclarationSymbol(); + PSY_ASSERT(tyDecl->kind() == TypeDeclarationSymbolKind::Typedef, + return nullptr); + auto tydef = tyDecl->asTypedef(); + return tydef->synonymizedType(); + } else { + // report: not a type declaration + } + } else { + // report: declaration not found + } + //return nullptr; + return ty; + } + + case TypeKind::Tag: + break; + + case TypeKind::Qualified: { + auto qualTy = ty->asQualifiedType(); + auto unqualTy = qualTy->unqualifiedType(); + auto resolvedTy = resolveType(unqualTy, scope); + if (resolvedTy != unqualTy) { + qualTy->resetUnqualifiedType( + resolvedTy->kind() == TypeKind::Qualified + ? resolvedTy->asQualifiedType()->unqualifiedType() + : resolvedTy); + } + break; + } + } + return ty; +} diff --git a/C/binder/DeclarationResolver.h b/C/binder/TypeResolver.h similarity index 76% rename from C/binder/DeclarationResolver.h rename to C/binder/TypeResolver.h index f5b5d9fc..927a8485 100644 --- a/C/binder/DeclarationResolver.h +++ b/C/binder/TypeResolver.h @@ -31,20 +31,22 @@ namespace psy { namespace C { -class PSY_C_INTERNAL_API DeclarationResolver final : protected SyntaxVisitor +class PSY_C_INTERNAL_API TypeResolver final : protected SyntaxVisitor { PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(SemanticModel); - DeclarationResolver(SemanticModel* semaModel, const SyntaxTree* tree); - DeclarationResolver(const DeclarationResolver&) = delete; - void operator=(const DeclarationResolver&) = delete; + TypeResolver(SemanticModel* semaModel, const SyntaxTree* tree); + TypeResolver(const TypeResolver&) = delete; + void operator=(const TypeResolver&) = delete; - void resolveDeclarations(); + void resolveTypes(); private: SemanticModel* semaModel_; + const Type* resolveType(const Type* ty, const Scope* scope) const; + //--------------// // Declarations // //--------------// @@ -52,6 +54,9 @@ class PSY_C_INTERNAL_API DeclarationResolver final : protected SyntaxVisitor virtual Action visitVariableAndOrFunctionDeclaration(const VariableAndOrFunctionDeclarationSyntax*) override; /* Declarators */ + Action visitDeclarator_COMMON(const DeclaratorSyntax*); + virtual Action visitPointerDeclarator(const PointerDeclaratorSyntax*) override; + virtual Action visitParenthesizedDeclarator(const ParenthesizedDeclaratorSyntax*) override; virtual Action visitIdentifierDeclarator(const IdentifierDeclaratorSyntax*) override; }; diff --git a/C/compilation/Compilation.cpp b/C/compilation/Compilation.cpp index b1f9a29a..9c671761 100644 --- a/C/compilation/Compilation.cpp +++ b/C/compilation/Compilation.cpp @@ -108,11 +108,11 @@ std::vector Compilation::syntaxTrees() const const SemanticModel* Compilation::computeSemanticModel(const SyntaxTree* tree) const { if (P->isDirty_[tree]) { - // TODO: Remove from the program the symbols associated - // with the given syntax tree. - P->semaModels_[tree].reset(new SemanticModel(tree, const_cast(this))); + std::unique_ptr semaModel(new SemanticModel(tree, const_cast(this))); + semaModel->applyBinder(); + semaModel->applyTypeResolver(); + P->semaModels_[tree] = std::move(semaModel); P->isDirty_[tree] = false; } - return P->semaModels_[tree].get(); } diff --git a/C/compilation/SemanticModel.cpp b/C/compilation/SemanticModel.cpp index 10178ef2..2190c7f7 100644 --- a/C/compilation/SemanticModel.cpp +++ b/C/compilation/SemanticModel.cpp @@ -23,7 +23,7 @@ #include "Compilation.h" #include "binder/Binder.h" -#include "binder/DeclarationResolver.h" +#include "binder/TypeResolver.h" #include "syntax/SyntaxNodes.h" #include "syntax/SyntaxUtilities.h" #include "symbols/Symbol_ALL.h" @@ -42,31 +42,38 @@ using namespace C; struct SemanticModel::SemanticModelImpl { SemanticModelImpl(const SyntaxTree* tree, Compilation* compilation) - : expectValidSyms_(true) + : bindingIsOK_(true) , tree_(tree) , compilation_(compilation) {} - bool expectValidSyms_; + bool bindingIsOK_; const SyntaxTree* tree_; Compilation* compilation_; std::unique_ptr unit_; std::vector> decls_; - std::vector> tys_; + std::unordered_map> tys_; std::unordered_map declsBySyntax_; }; SemanticModel::SemanticModel(const SyntaxTree* tree, Compilation* compilation) : P(new SemanticModelImpl(tree, compilation)) +{} + +SemanticModel::~SemanticModel() +{} + +void SemanticModel::applyBinder() { - Binder binder(this, tree); + Binder binder(this, P->tree_); binder.bind(); - DeclarationResolver declResolver(this, tree); - declResolver.resolveDeclarations(); } -SemanticModel::~SemanticModel() -{} +void SemanticModel::applyTypeResolver() +{ + TypeResolver tyResolver(this, P->tree_); + tyResolver.resolveTypes(); +} const SyntaxTree* SemanticModel::syntaxTree() const { @@ -92,7 +99,7 @@ TranslationUnit* SemanticModel::keepTranslationUnit( return P->unit_.get(); } -DeclarationSymbol* SemanticModel::keepAndBindDecl( +DeclarationSymbol* SemanticModel::keepBinding( const SyntaxNode* node, std::unique_ptr decl) { @@ -105,8 +112,14 @@ DeclarationSymbol* SemanticModel::keepAndBindDecl( Type* SemanticModel::keepType(std::unique_ptr ty) { - P->tys_.emplace_back(ty.release()); - return P->tys_.back().get(); + auto p = P->tys_.insert(std::make_pair(ty.get(), std::move(ty))); + PSY_ASSERT(p.second, return nullptr); + return p.first->second.get(); +} + +void SemanticModel::dropType(const Type* ty) +{ + P->tys_.erase(ty); } template @@ -115,107 +128,178 @@ const CastT* SemanticModel::castDecl(const OrigT* origDecl, { auto decl = ((origDecl)->*(cast))(); if (!decl) { - PSY_ASSERT_NO_STMT(!P->expectValidSyms_); + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; } return decl; } -const Function* SemanticModel::declarationOf(const FunctionDefinitionSyntax* node) const +Function* SemanticModel::declaredFunction(const FunctionDefinitionSyntax* node) { - auto decl = declarationOf(node->declarator()); - if (!decl) + auto decl = declaredDeclaration(node->declarator()); + if (!decl) { + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; - auto funcSym = castDecl(decl, &DeclarationSymbol::asFunction); - return funcSym; + } + PSY_ASSERT(decl->kind() == DeclarationSymbolKind::Function, return nullptr); + auto funcDecl = decl->asFunction(); + return funcDecl; } -const Parameter* SemanticModel::declarationOf(const ParameterDeclarationSyntax* node) const +const Function* SemanticModel::declaredFunction(const FunctionDefinitionSyntax* node) const { - auto decl = declarationOf(node->declarator()); - if (!decl) - return nullptr; - auto objDecl = castDecl(decl, &DeclarationSymbol::asObjectDeclarationSymbol); - if (!objDecl) + return const_cast(this)->declaredFunction(node); +} + +Parameter* SemanticModel::declaredParameter(const ParameterDeclarationSyntax* node) +{ + auto decl = declaredDeclaration(node->declarator()); + if (!decl) { + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; - auto parmDecl = castDecl(objDecl, &ObjectDeclarationSymbol::asParameter); + } + PSY_ASSERT(decl->kind() == DeclarationSymbolKind::Object, return nullptr); + auto objDecl = decl->asObjectDeclarationSymbol(); + PSY_ASSERT(objDecl->kind() == ObjectDeclarationSymbolKind::Parameter, return nullptr); + auto parmDecl = objDecl->asParameter(); return parmDecl; } -const TypeDeclarationSymbol* SemanticModel::declarationOf(const TypeDeclarationSyntax* node) const +const Parameter* SemanticModel::declaredParameter(const ParameterDeclarationSyntax* node) const +{ + return const_cast(this)->declaredParameter(node); +} + +const TypeDeclarationSymbol* SemanticModel::declaredTypeDeclaration(const TypeDeclarationSyntax* node) const { auto it = P->declsBySyntax_.find(node); if (it == P->declsBySyntax_.end()) { - PSY_ASSERT_NO_STMT(!P->expectValidSyms_); + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; } - auto tyDecl = castDecl( - it->second->asDeclarationSymbol(), - &DeclarationSymbol::asTypeDeclarationSymbol); + PSY_ASSERT(it->second->kind() == DeclarationSymbolKind::Type, return nullptr); + auto tyDecl = it->second->asTypeDeclarationSymbol(); return tyDecl; } -const Enumerator* SemanticModel::declarationOf(const EnumeratorDeclarationSyntax* node) const +const Struct* SemanticModel::declaredStruct(const StructOrUnionDeclarationSyntax* node) const +{ + auto tyDecl = declaredTypeDeclaration(node); + PSY_ASSERT(tyDecl->kind() == TypeDeclarationSymbolKind::Struct, return nullptr); + return tyDecl->asStruct(); +} + +const Union* SemanticModel::declaredUnion(const StructOrUnionDeclarationSyntax* node) const +{ + auto tyDecl = declaredTypeDeclaration(node); + PSY_ASSERT(tyDecl->kind() == TypeDeclarationSymbolKind::Union, return nullptr); + return tyDecl->asUnion(); +} + +const Enum* SemanticModel::declaredEnum(const EnumDeclarationSyntax* node) const +{ + auto tyDecl = declaredTypeDeclaration(node); + PSY_ASSERT(tyDecl->kind() == TypeDeclarationSymbolKind::Enum, return nullptr); + return tyDecl->asEnum(); +} + +Enumerator* SemanticModel::declaredEnumerator(const EnumeratorDeclarationSyntax* node) { auto it = P->declsBySyntax_.find(node); if (it == P->declsBySyntax_.end()) { - PSY_ASSERT_NO_STMT(!P->expectValidSyms_); + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; } - auto objDecl = castDecl(it->second->asDeclarationSymbol(), &DeclarationSymbol::asObjectDeclarationSymbol); - if (!objDecl) - return nullptr; - auto enumeratorDecl = castDecl(objDecl, &ObjectDeclarationSymbol::asEnumerator); - if (!enumeratorDecl) - return nullptr; + auto decl = it->second->asDeclarationSymbol(); + PSY_ASSERT(decl->kind() == DeclarationSymbolKind::Object, return nullptr); + auto objDecl = decl->asObjectDeclarationSymbol(); + PSY_ASSERT(objDecl->kind() == ObjectDeclarationSymbolKind::Enumerator, return nullptr); + auto enumeratorDecl = objDecl->asEnumerator(); return enumeratorDecl; } -std::vector SemanticModel::declarationsOf(const FieldDeclarationSyntax* node) const +const Enumerator* SemanticModel::declaredEnumerator(const EnumeratorDeclarationSyntax* node) const +{ + return const_cast(this)->declaredEnumerator(node); +} + +template VecT SemanticModel::declaredFields_CORE( + const FieldDeclarationSyntax* node, + VecT&& decls) { - std::vector fldDecls; for (auto decltorIt = node->declarators(); decltorIt; decltorIt = decltorIt->next) { - auto decl = declarationOf(decltorIt->value); - if (!decl) - continue; - auto objDecl = castDecl(decl, &DeclarationSymbol::asObjectDeclarationSymbol); - if (!objDecl) - continue; - auto fldDecl = castDecl(objDecl, &ObjectDeclarationSymbol::asField); - if (!fldDecl) + auto decl = declaredDeclaration(decltorIt->value); + if (!decl) { + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); continue; - fldDecls.push_back(fldDecl); + } + PSY_ASSERT(decl->kind() == DeclarationSymbolKind::Object, continue); + auto objDecl = decl->asObjectDeclarationSymbol(); + PSY_ASSERT(objDecl->kind() == ObjectDeclarationSymbolKind::Field, continue); + auto fldDecl = objDecl->asField(); + decls.push_back(fldDecl); } - return fldDecls; + return std::move(decls); } -std::vector SemanticModel::declarationsOf( - const VariableAndOrFunctionDeclarationSyntax* node) const +std::vector SemanticModel::declaredFields(const FieldDeclarationSyntax* node) +{ + std::vector decls; + return declaredFields_CORE(node, std::move(decls)); +} + +std::vector SemanticModel::declaredFields(const FieldDeclarationSyntax* node) const +{ + std::vector decls; + return const_cast(this)->declaredFields_CORE(node, std::move(decls)); +} + +template VecT SemanticModel::declaredDeclarations_CORE( + const VariableAndOrFunctionDeclarationSyntax* node, + VecT&& decls) { - std::vector decls; for (auto decltorIt = node->declarators(); decltorIt; decltorIt = decltorIt->next) { - auto decl = declarationOf(decltorIt->value); + auto decl = declaredDeclaration(decltorIt->value); if (!decl) { - PSY_ASSERT_NO_STMT(!P->expectValidSyms_); + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); continue; } decls.push_back(decl); } - return decls; + return std::move(decls); } -const DeclarationSymbol* SemanticModel::declarationOf(const DeclaratorSyntax* node) const +std::vector SemanticModel::declaredDeclarations( + const VariableAndOrFunctionDeclarationSyntax* node) +{ + std::vector decls; + return declaredDeclarations_CORE(node, std::move(decls)); +} + +std::vector SemanticModel::declaredDeclarations( + const VariableAndOrFunctionDeclarationSyntax* node) const +{ + std::vector decls; + return const_cast(this)->declaredDeclarations_CORE(node, std::move(decls)); +} + +DeclarationSymbol* SemanticModel::declaredDeclaration(const DeclaratorSyntax* node) { auto node_P = SyntaxUtilities::strippedDeclaratorOrSelf(node); auto node_PP = SyntaxUtilities::innermostDeclaratorOrSelf(node_P); auto it = P->declsBySyntax_.find(node_PP); if (it == P->declsBySyntax_.end()) { - PSY_ASSERT_NO_STMT(!P->expectValidSyms_); + PSY_ASSERT_NO_STMT(!P->bindingIsOK_); return nullptr; } return it->second->asDeclarationSymbol(); } +const DeclarationSymbol* SemanticModel::declaredDeclaration(const DeclaratorSyntax* node) const +{ + return const_cast(this)->declaredDeclaration(node); +} + DeclarationSymbol* SemanticModel::searchForDecl( std::function&)> pred) const { diff --git a/C/compilation/SemanticModel.h b/C/compilation/SemanticModel.h index a559c3f5..a9d482b9 100644 --- a/C/compilation/SemanticModel.h +++ b/C/compilation/SemanticModel.h @@ -68,7 +68,7 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - const Function* declarationOf(const FunctionDefinitionSyntax* node) const; + const Function* declaredFunction(const FunctionDefinitionSyntax* node) const; /** * The Parameter declared by the given ParameterDeclarationSyntax \c node. @@ -76,7 +76,31 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - const Parameter* declarationOf(const ParameterDeclarationSyntax* node) const; + const Parameter* declaredParameter(const ParameterDeclarationSyntax* node) const; + + /** + * The Struct declared by the given StructOrUnionDeclarationSyntax \c node. + * + * \note Similar to: + * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. + */ + const Struct* declaredStruct(const StructOrUnionDeclarationSyntax* node) const; + + /** + * The Union declared by the given StructOrUnionDeclarationSyntax \c node. + * + * \note Similar to: + * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. + */ + const Union* declaredUnion(const StructOrUnionDeclarationSyntax* node) const; + + /** + * The Enum declared by the given EnumDeclarationSyntax \c node. + * + * \note Similar to: + * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. + */ + const Enum* declaredEnum(const EnumDeclarationSyntax* node) const; /** * The TypeDeclarationSymbol declared by the given TypeDeclarationSyntax \c node. @@ -84,7 +108,7 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - const TypeDeclarationSymbol* declarationOf(const TypeDeclarationSyntax* node) const; + const TypeDeclarationSymbol* declaredTypeDeclaration(const TypeDeclarationSyntax* node) const; /** * The Enumerator declared by the given EnumeratorDeclarationSyntax \c node. @@ -92,7 +116,7 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - const Enumerator* declarationOf(const EnumeratorDeclarationSyntax* node) const; + const Enumerator* declaredEnumerator(const EnumeratorDeclarationSyntax* node) const; /** * The Field(s) declared by the given FieldDeclarationSyntax \c node. @@ -100,7 +124,7 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - std::vector declarationsOf(const FieldDeclarationSyntax* node) const; + std::vector declaredFields(const FieldDeclarationSyntax* node) const; /** * The DeclarationSymbol(s) declared by the given VariableAndOrFunctionDeclarationSyntax \c node. @@ -108,7 +132,7 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - std::vector declarationsOf(const VariableAndOrFunctionDeclarationSyntax* node) const; + std::vector declaredDeclarations(const VariableAndOrFunctionDeclarationSyntax* node) const; /** * The DeclarationSymbol declared by the given DeclaratorSyntax \c node. @@ -116,23 +140,28 @@ class PSY_C_API SemanticModel * \note Similar to: * - \c Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol of Roslyn. */ - const DeclarationSymbol* declarationOf(const DeclaratorSyntax* node) const; + const DeclarationSymbol* declaredDeclaration(const DeclaratorSyntax* node) const; //!@} - PSY_INTERNAL: - PSY_GRANT_INTERNAL_ACCESS(Binder); +PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Compilation); + PSY_GRANT_INTERNAL_ACCESS(Binder); + PSY_GRANT_INTERNAL_ACCESS(TypeResolver); PSY_GRANT_INTERNAL_ACCESS(InternalsTestSuite); SemanticModel(const SyntaxTree* tree, Compilation* compilation); + void applyBinder(); + void applyTypeResolver(); + TranslationUnit* keepTranslationUnit( const TranslationUnitSyntax* node, std::unique_ptr unitSym); - DeclarationSymbol* keepAndBindDecl( + DeclarationSymbol* keepBinding( const SyntaxNode* node, std::unique_ptr sym); Type* keepType(std::unique_ptr ty); + void dropType(const Type* ty); DeclarationSymbol* searchForDecl( std::function&)> pred) const; @@ -141,6 +170,18 @@ class PSY_C_API SemanticModel const OrigT* origDecl, const CastT* (OrigT::*cast)() const) const; + Function* declaredFunction(const FunctionDefinitionSyntax* node); + Parameter* declaredParameter(const ParameterDeclarationSyntax* node); + TypeDeclarationSymbol* declaredDeclaration(const TypeDeclarationSyntax* node); // TODO + Enumerator* declaredEnumerator(const EnumeratorDeclarationSyntax* node); + std::vector declaredFields(const FieldDeclarationSyntax* node); + template VecT declaredFields_CORE(const FieldDeclarationSyntax* node, VecT&& decls); + std::vector declaredDeclarations(const VariableAndOrFunctionDeclarationSyntax* node); + template VecT declaredDeclarations_CORE( + const VariableAndOrFunctionDeclarationSyntax* node, + VecT&& decls); + DeclarationSymbol* declaredDeclaration(const DeclaratorSyntax* node); + private: SemanticModel(const SemanticModel&) = delete; SemanticModel& operator=(const SemanticModel&) = delete; diff --git a/C/symbols/DeclarationSymbol_Object.h b/C/symbols/DeclarationSymbol_Object.h index 59b05b27..3e89d937 100644 --- a/C/symbols/DeclarationSymbol_Object.h +++ b/C/symbols/DeclarationSymbol_Object.h @@ -90,6 +90,7 @@ class PSY_C_API ObjectDeclarationSymbol PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Binder); + PSY_GRANT_INTERNAL_ACCESS(TypeResolver); virtual void setName(const Identifier* name) override; virtual void setType(const Type* ty) override; diff --git a/C/symbols/ObjectDeclarationSymbol_Parameter.cpp b/C/symbols/ObjectDeclarationSymbol_Parameter.cpp index d35a8412..88c9d610 100644 --- a/C/symbols/ObjectDeclarationSymbol_Parameter.cpp +++ b/C/symbols/ObjectDeclarationSymbol_Parameter.cpp @@ -51,9 +51,9 @@ namespace C { std::string to_string(const Parameter& parm) { std::ostringstream oss; - oss << "valueText(); - oss << "type:" << to_string(*parm.type()); + oss << "valueText(); + oss << " type:" << to_string(*parm.type()); oss << ">"; return oss.str(); } diff --git a/C/symbols/TypeDeclarationSymbol_Typedef.cpp b/C/symbols/TypeDeclarationSymbol_Typedef.cpp index ae0d4721..d136dbea 100644 --- a/C/symbols/TypeDeclarationSymbol_Typedef.cpp +++ b/C/symbols/TypeDeclarationSymbol_Typedef.cpp @@ -32,7 +32,8 @@ using namespace C; Typedef::Typedef(const SyntaxTree* tree, const Symbol* containingSym, const Scope* enclosingScope, - TypedefType* tydefTy) + TypedefType* tydefTy, + const Type* synonymizedTy) : TypeDeclarationSymbol( new TypeDeclarationSymbolImpl(tree, containingSym, @@ -40,6 +41,7 @@ Typedef::Typedef(const SyntaxTree* tree, NameSpace::OrdinaryIdentifiers, tydefTy, TypeDeclarationSymbolKind::Typedef)) + , synonymizedTy_(synonymizedTy) { } @@ -54,6 +56,11 @@ const Identifier* Typedef::identifier() const return P_CAST->ty_->asTypedefType()->typedefName(); } +const Type* Typedef::synonymizedType() const +{ + return synonymizedTy_; +} + namespace psy { namespace C { diff --git a/C/symbols/TypeDeclarationSymbol_Typedef.h b/C/symbols/TypeDeclarationSymbol_Typedef.h index 358d3f0c..9558b984 100644 --- a/C/symbols/TypeDeclarationSymbol_Typedef.h +++ b/C/symbols/TypeDeclarationSymbol_Typedef.h @@ -47,13 +47,22 @@ class PSY_C_API Typedef final : public TypeDeclarationSymbol */ virtual const Identifier* identifier() const override; + /** + * The Type synonymized by \c this Typedef. + */ + const Type* synonymizedType() const; + PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Binder); Typedef(const SyntaxTree* tree, const Symbol* containingSym, const Scope* enclosingScope, - TypedefType* tydefTy); + TypedefType* tydefTy, + const Type* synonymizedTy); + +private: + const Type* synonymizedTy_; }; std::string PSY_C_API to_string(const Typedef& tydef); diff --git a/C/tests/BinderTester.h b/C/tests/BinderTester.h index b915b793..6dfc7950 100644 --- a/C/tests/BinderTester.h +++ b/C/tests/BinderTester.h @@ -88,9 +88,9 @@ class BinderTester final : public Tester Types + 3000-0049 -> structures and unions + 3050-0099 -> enumerations (and enumerators) - + 3100-3149 -> typedefs - + ... - + 3500- -> scope + + 3100-3199 -> typedefs + + 3300-...-> mixed + + 3500 -> scope */ void case0001(); diff --git a/C/tests/BinderTester_1000_1999.cpp b/C/tests/BinderTester_1000_1999.cpp index 9b4d2dc8..f74882df 100644 --- a/C/tests/BinderTester_1000_1999.cpp +++ b/C/tests/BinderTester_1000_1999.cpp @@ -318,7 +318,18 @@ void BinderTester::case1059() .ty_.Basic(BasicTypeKind::Int, CVR::Atomic))); } -void BinderTester::case1060() {} +void BinderTester::case1060() +{ + bind("int const x , y ;", + Expectation() + .declaration(Decl() + .Object("x", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int, CVR::Const)) + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int, CVR::Const))); +} + void BinderTester::case1061() {} void BinderTester::case1062() {} void BinderTester::case1063() {} @@ -443,7 +454,17 @@ void BinderTester::case1107() .ty_.Derived(TypeKind::Pointer, CVR::None))); } -void BinderTester::case1108() {} +void BinderTester::case1108() +{ + bind("int * x , y ;", + Expectation() + .declaration(Decl().Object("x", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int) + .ty_.Derived(TypeKind::Pointer)) + .declaration(Decl().Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int))); +} + void BinderTester::case1109() {} void BinderTester::case1110() {} void BinderTester::case1111() {} diff --git a/C/tests/BinderTester_3000_3999.cpp b/C/tests/BinderTester_3000_3999.cpp index 0c89d0c8..4427d889 100644 --- a/C/tests/BinderTester_3000_3999.cpp +++ b/C/tests/BinderTester_3000_3999.cpp @@ -514,10 +514,59 @@ void BinderTester::case3297(){} void BinderTester::case3298(){} void BinderTester::case3299(){} -void BinderTester::case3300(){} -void BinderTester::case3301(){} -void BinderTester::case3302(){} -void BinderTester::case3303(){} +void BinderTester::case3300() +{ + bind("typedef int x ; x z ;", + Expectation() + .declaration(Decl() + .Type("x", TypeDeclarationSymbolKind::Typedef) + .inNameSpace(NameSpace::OrdinaryIdentifiers) + .withScopeKind(ScopeKind::File)) + .declaration(Decl() + .Object("z", ObjectDeclarationSymbolKind::Variable) + .ty_.Typedef("x"))); +} + +void BinderTester::case3301() +{ + bind("typedef int * x ; x z ;", + Expectation() + .declaration(Decl() + .Type("x", TypeDeclarationSymbolKind::Typedef) + .inNameSpace(NameSpace::OrdinaryIdentifiers) + .withScopeKind(ScopeKind::File)) + .declaration(Decl().Object("z", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int) + .ty_.Typedef("x"))); +} + +void BinderTester::case3302() +{ + bind("int * x ; int y ;", + Expectation() + .declaration(Decl() + .Object("x", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int) + .ty_.Derived(TypeKind::Pointer)) + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int))); +} + +void BinderTester::case3303() +{ + bind("int * * x ; int y ;", + Expectation() + .declaration(Decl() + .Object("x", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int) + .ty_.Derived(TypeKind::Pointer) + .ty_.Derived(TypeKind::Pointer)) + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Int))); +} + void BinderTester::case3304(){} void BinderTester::case3305(){} void BinderTester::case3306(){} diff --git a/C/tests/DeclarationResolverTester.cpp b/C/tests/DeclarationResolverTester.cpp deleted file mode 100644 index 14b24279..00000000 --- a/C/tests/DeclarationResolverTester.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2024 Leandro T. C. Melo -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#include "DeclarationResolverTester.h" - -using namespace psy; -using namespace C; - -const std::string DeclarationResolverTester::Name = "DECLARATION-RESOLVER"; - -void DeclarationResolverTester::testDeclarationResolver() -{ - return run(tests_); -} - -void DeclarationResolverTester::resolve(std::string text, Expectation X) -{ - (static_cast(suite_)->resolve(text, X)); -} - -void DeclarationResolverTester::case0000() -{ - auto s = R"( -typedef int x ; -x y; -)"; - - resolve(s, - Expectation() - .declaration(Decl().Object("y", ObjectDeclarationSymbolKind::Variable) - .ty_.Typedef("x")) -// .declaration(Decl() -// .Type("x", TypeDeclarationSymbolKind::Typedef) -// .inNameSpace(NameSpace::OrdinaryIdentifiers) -// .withScopeKind(ScopeKind::File)) - ); -} - -void DeclarationResolverTester::case0001(){} -void DeclarationResolverTester::case0002(){} -void DeclarationResolverTester::case0003(){} -void DeclarationResolverTester::case0004(){} -void DeclarationResolverTester::case0005(){} -void DeclarationResolverTester::case0006(){} -void DeclarationResolverTester::case0007(){} -void DeclarationResolverTester::case0008(){} -void DeclarationResolverTester::case0009(){} -void DeclarationResolverTester::case0010(){} -void DeclarationResolverTester::case0011(){} -void DeclarationResolverTester::case0012(){} -void DeclarationResolverTester::case0013(){} -void DeclarationResolverTester::case0014(){} -void DeclarationResolverTester::case0015(){} -void DeclarationResolverTester::case0016(){} -void DeclarationResolverTester::case0017(){} -void DeclarationResolverTester::case0018(){} -void DeclarationResolverTester::case0019(){} -void DeclarationResolverTester::case0020(){} -void DeclarationResolverTester::case0021(){} -void DeclarationResolverTester::case0022(){} -void DeclarationResolverTester::case0023(){} -void DeclarationResolverTester::case0024(){} -void DeclarationResolverTester::case0025(){} -void DeclarationResolverTester::case0026(){} -void DeclarationResolverTester::case0027(){} -void DeclarationResolverTester::case0028(){} -void DeclarationResolverTester::case0029(){} diff --git a/C/tests/SemanticModelTester.cpp b/C/tests/SemanticModelTester.cpp index d7af3383..c8cfa398 100644 --- a/C/tests/SemanticModelTester.cpp +++ b/C/tests/SemanticModelTester.cpp @@ -88,7 +88,7 @@ void SemanticModelTester::case0001() auto decltor = varAndOrFunDecl->declarators()->value; auto identDecltor = decltor->asIdentifierDeclarator(); - const DeclarationSymbol* declSym = semaModel->declarationOf(identDecltor); + const DeclarationSymbol* declSym = semaModel->declaredDeclaration(identDecltor); PSY_EXPECT_TRUE(declSym); PSY_EXPECT_EQ_ENU(declSym->kind(), DeclarationSymbolKind::Object, SymbolKind); PSY_EXPECT_EQ_ENU(declSym->asObjectDeclarationSymbol()->kind(), ObjectDeclarationSymbolKind::Variable, ObjectDeclarationSymbolKind); @@ -106,7 +106,7 @@ void SemanticModelTester::case0002() auto decltor = varAndOrFunDecl->declarators()->value; auto parenDecltor = decltor->asParenthesizedDeclarator(); - const DeclarationSymbol* sym = semaModel->declarationOf(parenDecltor); + const DeclarationSymbol* sym = semaModel->declaredDeclaration(parenDecltor); PSY_EXPECT_TRUE(sym); PSY_EXPECT_EQ_ENU(sym->kind(), DeclarationSymbolKind::Object, SymbolKind); PSY_EXPECT_EQ_ENU(sym->asObjectDeclarationSymbol()->kind(), ObjectDeclarationSymbolKind::Variable, ObjectDeclarationSymbolKind); @@ -121,7 +121,7 @@ void SemanticModelTester::case0003() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("int x ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 1); const DeclarationSymbol* sym0 = syms[0]; @@ -139,7 +139,7 @@ void SemanticModelTester::case0004() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("x y , z ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 2); const DeclarationSymbol* sym1 = syms[0]; @@ -164,7 +164,7 @@ void SemanticModelTester::case0090() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("int x , y ( ) ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 2); const DeclarationSymbol* sym0 = syms[0]; @@ -179,10 +179,10 @@ void SemanticModelTester::case0090() const DeclarationSymbol* sym1 = syms[1]; PSY_EXPECT_TRUE(sym1); PSY_EXPECT_EQ_ENU(sym1->kind(), DeclarationSymbolKind::Function, SymbolKind); - const Function* funcSym2 = sym1->asFunction(); - PSY_EXPECT_TRUE(funcSym2); - PSY_EXPECT_EQ_STR(funcSym2->name()->valueText(), "y"); - PSY_EXPECT_EQ_ENU(funcSym2->type()->kind(), TypeKind::Function, TypeKind); + const Function* funcDecl2 = sym1->asFunction(); + PSY_EXPECT_TRUE(funcDecl2); + PSY_EXPECT_EQ_STR(funcDecl2->name()->valueText(), "y"); + PSY_EXPECT_EQ_ENU(funcDecl2->type()->kind(), TypeKind::Function, TypeKind); } void SemanticModelTester::case0091() @@ -190,7 +190,7 @@ void SemanticModelTester::case0091() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("int x , y ( int z ) ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 2); const DeclarationSymbol* sym1 = syms[0]; @@ -205,10 +205,10 @@ void SemanticModelTester::case0091() const DeclarationSymbol* sym2 = syms[1]; PSY_EXPECT_TRUE(sym2); PSY_EXPECT_EQ_ENU(sym2->kind(), DeclarationSymbolKind::Function, SymbolKind); - const Function* funcSym2 = sym2->asFunction(); - PSY_EXPECT_TRUE(funcSym2); - PSY_EXPECT_EQ_STR(funcSym2->name()->valueText(), "y"); - PSY_EXPECT_EQ_ENU(funcSym2->type()->kind(), TypeKind::Function, TypeKind); + const Function* funcDecl2 = sym2->asFunction(); + PSY_EXPECT_TRUE(funcDecl2); + PSY_EXPECT_EQ_STR(funcDecl2->name()->valueText(), "y"); + PSY_EXPECT_EQ_ENU(funcDecl2->type()->kind(), TypeKind::Function, TypeKind); } void SemanticModelTester::case0092() @@ -216,7 +216,7 @@ void SemanticModelTester::case0092() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("x y , z ( ) ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 2); const DeclarationSymbol* sym0 = syms[0]; @@ -230,10 +230,10 @@ void SemanticModelTester::case0092() const DeclarationSymbol* sym1 = syms[1]; PSY_EXPECT_TRUE(sym1); PSY_EXPECT_EQ_ENU(sym1->kind(), DeclarationSymbolKind::Function, SymbolKind); - const Function* funcSym2 = sym1->asFunction(); - PSY_EXPECT_TRUE(funcSym2); - PSY_EXPECT_EQ_STR(funcSym2->name()->valueText(), "z"); - PSY_EXPECT_EQ_ENU(funcSym2->type()->kind(), TypeKind::Function, TypeKind); + const Function* funcDecl2 = sym1->asFunction(); + PSY_EXPECT_TRUE(funcDecl2); + PSY_EXPECT_EQ_STR(funcDecl2->name()->valueText(), "z"); + PSY_EXPECT_EQ_ENU(funcDecl2->type()->kind(), TypeKind::Function, TypeKind); } void SemanticModelTester::case0093(){} @@ -256,24 +256,24 @@ void SemanticModelTester::case0101() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("void x ( ) ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 1); const DeclarationSymbol* sym0 = syms[0]; PSY_EXPECT_TRUE(sym0); PSY_EXPECT_EQ_ENU(sym0->kind(), DeclarationSymbolKind::Function, SymbolKind); - const Function* funcSym = sym0->asFunction(); - PSY_EXPECT_TRUE(funcSym); - PSY_EXPECT_EQ_STR(funcSym->name()->valueText(), "x"); - PSY_EXPECT_EQ_ENU(funcSym->type()->kind(), TypeKind::Function, TypeKind); + const Function* funcDecl = sym0->asFunction(); + PSY_EXPECT_TRUE(funcDecl); + PSY_EXPECT_EQ_STR(funcDecl->name()->valueText(), "x"); + PSY_EXPECT_EQ_ENU(funcDecl->type()->kind(), TypeKind::Function, TypeKind); auto decltor = varAndOrFunDecl->declarators()->value; auto arrOrFunDecltor = decltor->asArrayOrFunctionDeclarator(); - const DeclarationSymbol* sym = semaModel->declarationOf(arrOrFunDecltor); + const DeclarationSymbol* sym = semaModel->declaredDeclaration(arrOrFunDecltor); PSY_EXPECT_TRUE(sym); PSY_EXPECT_TRUE(sym->kind() == DeclarationSymbolKind::Function); - PSY_EXPECT_EQ_PTR(sym, funcSym); + PSY_EXPECT_EQ_PTR(sym, funcDecl); } void SemanticModelTester::case0102() @@ -298,18 +298,18 @@ void SemanticModelTester::case0150() auto [funcDef, semaModel] = declAndSemaModel("void x ( ) { }"); - const Function* funcSym = semaModel->declarationOf(funcDef); - PSY_EXPECT_TRUE(funcSym); - PSY_EXPECT_EQ_STR(funcSym->name()->valueText(), "x"); - PSY_EXPECT_EQ_ENU(funcSym->type()->kind(), TypeKind::Function, TypeKind); + const Function* funcDecl = semaModel->declaredFunction(funcDef); + PSY_EXPECT_TRUE(funcDecl); + PSY_EXPECT_EQ_STR(funcDecl->name()->valueText(), "x"); + PSY_EXPECT_EQ_ENU(funcDecl->type()->kind(), TypeKind::Function, TypeKind); auto decltor = funcDef->declarator(); auto arrOrFunDecltor = decltor->asArrayOrFunctionDeclarator(); - const DeclarationSymbol* sym = semaModel->declarationOf(arrOrFunDecltor); + const DeclarationSymbol* sym = semaModel->declaredDeclaration(arrOrFunDecltor); PSY_EXPECT_TRUE(sym); PSY_EXPECT_TRUE(sym->kind() == DeclarationSymbolKind::Function); - PSY_EXPECT_EQ_PTR(sym, funcSym); + PSY_EXPECT_EQ_PTR(sym, funcDecl); } void SemanticModelTester::case0151() @@ -337,15 +337,15 @@ void SemanticModelTester::case0201() auto parmDecl0 = parmDecls->value; auto identDecltor = parmDecl0->declarator()->asIdentifierDeclarator(); - const DeclarationSymbol* sym = semaModel->declarationOf(identDecltor); + const DeclarationSymbol* sym = semaModel->declaredDeclaration(identDecltor); PSY_EXPECT_TRUE(sym); PSY_EXPECT_EQ_ENU(sym->kind(), DeclarationSymbolKind::Object, SymbolKind); PSY_EXPECT_EQ_ENU(sym->asObjectDeclarationSymbol()->kind(), ObjectDeclarationSymbolKind::Parameter, ObjectDeclarationSymbolKind); - const Parameter* parmSym = sym->asObjectDeclarationSymbol()->asParameter(); - PSY_EXPECT_TRUE(parmSym); - PSY_EXPECT_EQ_STR(parmSym->name()->valueText(), "y"); - PSY_EXPECT_EQ_ENU(parmSym->type()->kind(), TypeKind::Basic, TypeKind); - PSY_EXPECT_EQ_ENU(parmSym->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); + const Parameter* parmDecl = sym->asObjectDeclarationSymbol()->asParameter(); + PSY_EXPECT_TRUE(parmDecl); + PSY_EXPECT_EQ_STR(parmDecl->name()->valueText(), "y"); + PSY_EXPECT_EQ_ENU(parmDecl->type()->kind(), TypeKind::Basic, TypeKind); + PSY_EXPECT_EQ_ENU(parmDecl->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); } void SemanticModelTester::case0202() @@ -357,11 +357,11 @@ void SemanticModelTester::case0202() auto arrOrFunDecltor = decltor->asArrayOrFunctionDeclarator(); auto parmDecls = arrOrFunDecltor->suffix()->asParameterSuffix()->parameters(); - const Parameter* parmSym = semaModel->declarationOf(parmDecls->value); - PSY_EXPECT_TRUE(parmSym); - PSY_EXPECT_EQ_STR(parmSym->name()->valueText(), "y"); - PSY_EXPECT_EQ_ENU(parmSym->type()->kind(), TypeKind::Basic, TypeKind); - PSY_EXPECT_EQ_ENU(parmSym->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); + const Parameter* parmDecl = semaModel->declaredParameter(parmDecls->value); + PSY_EXPECT_TRUE(parmDecl); + PSY_EXPECT_EQ_STR(parmDecl->name()->valueText(), "y"); + PSY_EXPECT_EQ_ENU(parmDecl->type()->kind(), TypeKind::Basic, TypeKind); + PSY_EXPECT_EQ_ENU(parmDecl->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); } void SemanticModelTester::case0203() @@ -373,10 +373,10 @@ void SemanticModelTester::case0203() auto arrOrFunDecltor = decltor->asArrayOrFunctionDeclarator(); auto parmDecls = arrOrFunDecltor->suffix()->asParameterSuffix()->parameters(); - const Parameter* parmSym = semaModel->declarationOf(parmDecls->value); - PSY_EXPECT_TRUE(parmSym); - PSY_EXPECT_EQ_STR(parmSym->name()->valueText(), "z"); - PSY_EXPECT_EQ_ENU(parmSym->type()->kind(), TypeKind::Typedef, TypeKind); + const Parameter* parmDecl = semaModel->declaredParameter(parmDecls->value); + PSY_EXPECT_TRUE(parmDecl); + PSY_EXPECT_EQ_STR(parmDecl->name()->valueText(), "z"); + PSY_EXPECT_EQ_ENU(parmDecl->type()->kind(), TypeKind::Typedef, TypeKind); } void SemanticModelTester::case0204() @@ -388,16 +388,16 @@ void SemanticModelTester::case0204() auto arrOrFunDecltor = decltor->asArrayOrFunctionDeclarator(); auto parmDecls = arrOrFunDecltor->suffix()->asParameterSuffix()->parameters(); - const Parameter* parmSym0 = semaModel->declarationOf(parmDecls->value); - PSY_EXPECT_TRUE(parmSym0); - PSY_EXPECT_EQ_STR(parmSym0->name()->valueText(), "z"); - PSY_EXPECT_EQ_ENU(parmSym0->type()->kind(), TypeKind::Typedef, TypeKind); + const Parameter* parmDecl0 = semaModel->declaredParameter(parmDecls->value); + PSY_EXPECT_TRUE(parmDecl0); + PSY_EXPECT_EQ_STR(parmDecl0->name()->valueText(), "z"); + PSY_EXPECT_EQ_ENU(parmDecl0->type()->kind(), TypeKind::Typedef, TypeKind); - const Parameter* parmSym1 = semaModel->declarationOf(parmDecls->next->value); - PSY_EXPECT_TRUE(parmSym1); - PSY_EXPECT_EQ_STR(parmSym1->name()->valueText(), "w"); - PSY_EXPECT_EQ_ENU(parmSym1->type()->kind(), TypeKind::Basic, TypeKind); - PSY_EXPECT_EQ_ENU(parmSym1->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); + const Parameter* parmDecl1 = semaModel->declaredParameter(parmDecls->next->value); + PSY_EXPECT_TRUE(parmDecl1); + PSY_EXPECT_EQ_STR(parmDecl1->name()->valueText(), "w"); + PSY_EXPECT_EQ_ENU(parmDecl1->type()->kind(), TypeKind::Basic, TypeKind); + PSY_EXPECT_EQ_ENU(parmDecl1->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); } void SemanticModelTester::case0205(){} @@ -421,24 +421,26 @@ void SemanticModelTester::case0300() { auto [tyDecl, semaModel] = declAndSemaModel("struct x { int _ ; } ;"); + PSY_EXPECT_EQ_ENU(tyDecl->kind(), SyntaxKind::StructDeclaration, SyntaxKind); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(tyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "x"); + const Struct* strukt = semaModel->declaredStruct(tyDecl->asStructOrUnionDeclaration()); + PSY_EXPECT_TRUE(strukt); + PSY_EXPECT_EQ_ENU(strukt->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(strukt->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(strukt->specifiedType()->asTagType()->tag()->valueText(), "x"); } void SemanticModelTester::case0301() { auto [tyDecl, semaModel] = declAndSemaModel("union x { int _ ; } ;"); + PSY_EXPECT_EQ_ENU(tyDecl->kind(), SyntaxKind::UnionDeclaration, SyntaxKind); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(tyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Union, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "x"); + const Union* uniom = semaModel->declaredUnion(tyDecl->asStructOrUnionDeclaration()); + PSY_EXPECT_TRUE(uniom); + PSY_EXPECT_EQ_ENU(uniom->kind(), TypeDeclarationSymbolKind::Union, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(uniom->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(uniom->specifiedType()->asTagType()->tag()->valueText(), "x"); } void SemanticModelTester::case0302() @@ -446,17 +448,18 @@ void SemanticModelTester::case0302() auto [varAndOrFunDecl, semaModel] = declAndSemaModel("struct x { int _ ; } y ;"); - auto syms = semaModel->declarationsOf(varAndOrFunDecl); + auto syms = semaModel->declaredDeclarations(varAndOrFunDecl); PSY_EXPECT_EQ_INT(syms.size(), 1); auto spec = varAndOrFunDecl->specifiers()->value->asSpecifier(); auto tyDecl = spec->asTagDeclarationAsSpecifier()->tagDeclaration(); + PSY_EXPECT_EQ_ENU(tyDecl->kind(), SyntaxKind::StructDeclaration, SyntaxKind); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(tyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "x"); + const Struct* strukt = semaModel->declaredStruct(tyDecl->asStructOrUnionDeclaration()); + PSY_EXPECT_TRUE(strukt); + PSY_EXPECT_EQ_ENU(strukt->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(strukt->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(strukt->specifiedType()->asTagType()->tag()->valueText(), "x"); } void SemanticModelTester::case0303() @@ -467,12 +470,13 @@ void SemanticModelTester::case0303() auto tySpec = tyDecl->typeSpecifier(); auto fldDecl0 = tySpec->declarations()->value->asFieldDeclaration(); auto nestedTyDecl = fldDecl0->specifiers()->value->asTagDeclarationAsSpecifier()->tagDeclaration(); + PSY_EXPECT_EQ_ENU(nestedTyDecl->kind(), SyntaxKind::StructDeclaration, SyntaxKind); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(nestedTyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "y"); + const Struct* strukt = semaModel->declaredStruct(nestedTyDecl->asStructOrUnionDeclaration()); + PSY_EXPECT_TRUE(strukt); + PSY_EXPECT_EQ_ENU(strukt->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(strukt->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(strukt->specifiedType()->asTagType()->tag()->valueText(), "y"); } void SemanticModelTester::case0304() @@ -495,12 +499,16 @@ struct x auto nestedTySpec = nestedTyDecl->typeSpecifier(); auto nestedFldDecl0 = nestedTySpec->declarations()->value->asFieldDeclaration(); auto nestedNestedTyDecl = nestedFldDecl0->specifiers()->value->asTagDeclarationAsSpecifier()->tagDeclaration(); + PSY_EXPECT_EQ_ENU(nestedNestedTyDecl->kind(), + SyntaxKind::StructDeclaration, + SyntaxKind); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(nestedNestedTyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "z"); + const Struct* strukt = + semaModel->declaredStruct(nestedNestedTyDecl->asStructOrUnionDeclaration()); + PSY_EXPECT_TRUE(strukt); + PSY_EXPECT_EQ_ENU(strukt->kind(), TypeDeclarationSymbolKind::Struct, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(strukt->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(strukt->specifiedType()->asTagType()->tag()->valueText(), "z"); } void SemanticModelTester::case0305(){} @@ -557,10 +565,10 @@ void SemanticModelTester::case0350() auto tySpec = tyDecl->typeSpecifier(); auto fldDecl0 = tySpec->declarations()->value->asFieldDeclaration(); - std::vector fldSyms0 = semaModel->declarationsOf(fldDecl0); - PSY_EXPECT_EQ_INT(fldSyms0.size(), 1); + std::vector fldDecls0 = semaModel->declaredFields(fldDecl0); + PSY_EXPECT_EQ_INT(fldDecls0.size(), 1); - const Field* fldSym0_0 = fldSyms0[0]; + const Field* fldSym0_0 = fldDecls0[0]; PSY_EXPECT_TRUE(fldSym0_0); PSY_EXPECT_EQ_STR(fldSym0_0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->kind(), TypeKind::Basic, TypeKind); @@ -575,16 +583,16 @@ void SemanticModelTester::case0351() auto tySpec = tyDecl->typeSpecifier(); auto fldDecl0 = tySpec->declarations()->value->asFieldDeclaration(); - std::vector fldSyms0 = semaModel->declarationsOf(fldDecl0); - PSY_EXPECT_EQ_INT(fldSyms0.size(), 2); + std::vector fldDecls0 = semaModel->declaredFields(fldDecl0); + PSY_EXPECT_EQ_INT(fldDecls0.size(), 2); - const Field* fldSym0_0 = fldSyms0[0]; + const Field* fldSym0_0 = fldDecls0[0]; PSY_EXPECT_TRUE(fldSym0_0); PSY_EXPECT_EQ_STR(fldSym0_0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->kind(), TypeKind::Basic, TypeKind); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); - const Field* fldSym0_1 = fldSyms0[1]; + const Field* fldSym0_1 = fldDecls0[1]; PSY_EXPECT_TRUE(fldSym0_1); PSY_EXPECT_EQ_STR(fldSym0_1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(fldSym0_1->type()->kind(), TypeKind::Basic, TypeKind); @@ -599,20 +607,20 @@ void SemanticModelTester::case0352() auto tySpec = tyDecl->typeSpecifier(); auto fldDecl0 = tySpec->declarations()->value->asFieldDeclaration(); - std::vector fldSyms0 = semaModel->declarationsOf(fldDecl0); - PSY_EXPECT_EQ_INT(fldSyms0.size(), 1); + std::vector fldDecls0 = semaModel->declaredFields(fldDecl0); + PSY_EXPECT_EQ_INT(fldDecls0.size(), 1); - const Field* fldSym0_0 = fldSyms0[0]; + const Field* fldSym0_0 = fldDecls0[0]; PSY_EXPECT_TRUE(fldSym0_0); PSY_EXPECT_EQ_STR(fldSym0_0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->kind(), TypeKind::Basic, TypeKind); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); auto fldDecl1 = tySpec->declarations()->next->value->asFieldDeclaration(); - std::vector fldSyms1 = semaModel->declarationsOf(fldDecl1); - PSY_EXPECT_EQ_INT(fldSyms1.size(), 1); + std::vector fldDecls1 = semaModel->declaredFields(fldDecl1); + PSY_EXPECT_EQ_INT(fldDecls1.size(), 1); - const Field* fldSym1_0 = fldSyms1[0]; + const Field* fldSym1_0 = fldDecls1[0]; PSY_EXPECT_TRUE(fldSym1_0); PSY_EXPECT_EQ_STR(fldSym1_0->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(fldSym1_0->type()->kind(), TypeKind::Pointer, TypeKind); @@ -626,30 +634,30 @@ void SemanticModelTester::case0353() auto tySpec = tyDecl->typeSpecifier(); auto fldDecl0 = tySpec->declarations()->value->asFieldDeclaration(); - std::vector fldSyms0 = semaModel->declarationsOf(fldDecl0); - PSY_EXPECT_EQ_INT(fldSyms0.size(), 2); + std::vector fldDecls0 = semaModel->declaredFields(fldDecl0); + PSY_EXPECT_EQ_INT(fldDecls0.size(), 2); - const Field* fldSym0_0 = fldSyms0[0]; + const Field* fldSym0_0 = fldDecls0[0]; PSY_EXPECT_TRUE(fldSym0_0); PSY_EXPECT_EQ_STR(fldSym0_0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->kind(), TypeKind::Basic, TypeKind); PSY_EXPECT_EQ_ENU(fldSym0_0->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); - const Field* fldSym0_1 = fldSyms0[1]; + const Field* fldSym0_1 = fldDecls0[1]; PSY_EXPECT_EQ_STR(fldSym0_1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(fldSym0_1->type()->kind(), TypeKind::Basic, TypeKind); PSY_EXPECT_EQ_ENU(fldSym0_1->type()->asBasicType()->kind(), BasicTypeKind::Int, BasicTypeKind); auto fldDecl1 = tySpec->declarations()->next->value->asFieldDeclaration(); - std::vector fldSyms1 = semaModel->declarationsOf(fldDecl1); - PSY_EXPECT_EQ_INT(fldSyms1.size(), 2); + std::vector fldDecls1 = semaModel->declaredFields(fldDecl1); + PSY_EXPECT_EQ_INT(fldDecls1.size(), 2); - const Field* fldSym1_0 = fldSyms1[0]; + const Field* fldSym1_0 = fldDecls1[0]; PSY_EXPECT_TRUE(fldSym1_0); PSY_EXPECT_EQ_STR(fldSym1_0->name()->valueText(), "k"); PSY_EXPECT_EQ_ENU(fldSym1_0->type()->kind(), TypeKind::Pointer, TypeKind); - const Field* fldSym1_1 = fldSyms1[1]; + const Field* fldSym1_1 = fldDecls1[1]; PSY_EXPECT_TRUE(fldSym1_1); PSY_EXPECT_EQ_STR(fldSym1_1->name()->valueText(), "w"); PSY_EXPECT_EQ_ENU(fldSym1_1->type()->kind(), TypeKind::Basic, TypeKind); @@ -705,14 +713,14 @@ void SemanticModelTester::case0399(){} void SemanticModelTester::case0400() { - auto [tyDecl, semaModel] = + auto [enumDecl, semaModel] = declAndSemaModel("enum x { y } ;"); - const TypeDeclarationSymbol* tySym = semaModel->declarationOf(tyDecl); - PSY_EXPECT_TRUE(tySym); - PSY_EXPECT_EQ_ENU(tySym->kind(), TypeDeclarationSymbolKind::Enum, TypeDeclarationSymbolKind); - PSY_EXPECT_EQ_ENU(tySym->specifiedType()->kind(), TypeKind::Tag, TypeKind); - PSY_EXPECT_EQ_STR(tySym->specifiedType()->asTagType()->tag()->valueText(), "x"); + const Enum* enun = semaModel->declaredEnum(enumDecl); + PSY_EXPECT_TRUE(enun); + PSY_EXPECT_EQ_ENU(enun->kind(), TypeDeclarationSymbolKind::Enum, TypeDeclarationSymbolKind); + PSY_EXPECT_EQ_ENU(enun->specifiedType()->kind(), TypeKind::Tag, TypeKind); + PSY_EXPECT_EQ_STR(enun->specifiedType()->asTagType()->tag()->valueText(), "x"); } void SemanticModelTester::case0401() @@ -783,7 +791,7 @@ void SemanticModelTester::case0450() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym); PSY_EXPECT_EQ_STR(enumeratorSym->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym->type()->kind(), TypeKind::Basic, TypeKind); @@ -799,7 +807,7 @@ void SemanticModelTester::case0451() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym); PSY_EXPECT_EQ_STR(enumeratorSym->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym->type()->kind(), TypeKind::Basic, TypeKind); @@ -815,7 +823,7 @@ void SemanticModelTester::case0452() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym0 = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym0 = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym0); PSY_EXPECT_EQ_STR(enumeratorSym0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym0->type()->kind(), TypeKind::Basic, TypeKind); @@ -823,7 +831,7 @@ void SemanticModelTester::case0452() auto enumeratorDecl1 = tySpec->declarations()->next->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym1 = semaModel->declarationOf(enumeratorDecl1); + const Enumerator* enumeratorSym1 = semaModel->declaredEnumerator(enumeratorDecl1); PSY_EXPECT_TRUE(enumeratorSym1); PSY_EXPECT_EQ_STR(enumeratorSym1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(enumeratorSym1->type()->kind(), TypeKind::Basic, TypeKind); @@ -839,7 +847,7 @@ void SemanticModelTester::case0453() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym0 = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym0 = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym0); PSY_EXPECT_EQ_STR(enumeratorSym0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym0->type()->kind(), TypeKind::Basic, TypeKind); @@ -847,7 +855,7 @@ void SemanticModelTester::case0453() auto enumeratorDecl1 = tySpec->declarations()->next->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym1 = semaModel->declarationOf(enumeratorDecl1); + const Enumerator* enumeratorSym1 = semaModel->declaredEnumerator(enumeratorDecl1); PSY_EXPECT_TRUE(enumeratorSym1); PSY_EXPECT_EQ_STR(enumeratorSym1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(enumeratorSym1->type()->kind(), TypeKind::Basic, TypeKind); @@ -863,7 +871,7 @@ void SemanticModelTester::case0454() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym0 = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym0 = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym0); PSY_EXPECT_EQ_STR(enumeratorSym0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym0->type()->kind(), TypeKind::Basic, TypeKind); @@ -871,7 +879,7 @@ void SemanticModelTester::case0454() auto enumeratorDecl1 = tySpec->declarations()->next->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym1 = semaModel->declarationOf(enumeratorDecl1); + const Enumerator* enumeratorSym1 = semaModel->declaredEnumerator(enumeratorDecl1); PSY_EXPECT_TRUE(enumeratorSym1); PSY_EXPECT_EQ_STR(enumeratorSym1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(enumeratorSym1->type()->kind(), TypeKind::Basic, TypeKind); @@ -887,7 +895,7 @@ void SemanticModelTester::case0455() auto enumeratorDecl0 = tySpec->declarations()->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym0 = semaModel->declarationOf(enumeratorDecl0); + const Enumerator* enumeratorSym0 = semaModel->declaredEnumerator(enumeratorDecl0); PSY_EXPECT_TRUE(enumeratorSym0); PSY_EXPECT_EQ_STR(enumeratorSym0->name()->valueText(), "y"); PSY_EXPECT_EQ_ENU(enumeratorSym0->type()->kind(), TypeKind::Basic, TypeKind); @@ -895,7 +903,7 @@ void SemanticModelTester::case0455() auto enumeratorDecl1 = tySpec->declarations()->next->value->asEnumeratorDeclaration(); - const Enumerator* enumeratorSym1 = semaModel->declarationOf(enumeratorDecl1); + const Enumerator* enumeratorSym1 = semaModel->declaredEnumerator(enumeratorDecl1); PSY_EXPECT_TRUE(enumeratorSym1); PSY_EXPECT_EQ_STR(enumeratorSym1->name()->valueText(), "z"); PSY_EXPECT_EQ_ENU(enumeratorSym1->type()->kind(), TypeKind::Basic, TypeKind); diff --git a/C/tests/TestExpectation.cpp b/C/tests/TestExpectation.cpp index f8bc1824..adecf345 100644 --- a/C/tests/TestExpectation.cpp +++ b/C/tests/TestExpectation.cpp @@ -181,15 +181,15 @@ Expectation& Expectation::ambiguity(std::string s) return *this; } -Expectation& Expectation::declaration(Decl b) +Expectation& Expectation::declaration(Decl d) { - declarations_.push_back(b); + declarations_.push_back(d); return *this; } -Expectation& Expectation::declaration(Ty ty) +Expectation& Expectation::declaration(Ty t) { - declarations_.push_back(ty.decl_); + declarations_.push_back(t.decl_); return *this; } diff --git a/C/tests/TestExpectation.h b/C/tests/TestExpectation.h index 2797f421..7a25dbf3 100644 --- a/C/tests/TestExpectation.h +++ b/C/tests/TestExpectation.h @@ -143,8 +143,8 @@ struct Expectation Expectation& AST(std::vector&& v); std::vector declarations_; - Expectation& declaration(Decl b); - Expectation& declaration(Ty ty); + Expectation& declaration(Decl d); + Expectation& declaration(Ty t); bool checkScope_; std::vector scopePath_; diff --git a/C/tests/TestSuite_Internals.cpp b/C/tests/TestSuite_Internals.cpp index f4b92a95..ef6fe0fb 100644 --- a/C/tests/TestSuite_Internals.cpp +++ b/C/tests/TestSuite_Internals.cpp @@ -32,7 +32,7 @@ #include "BinderTester.h" #include "ParserTester.h" #include "ReparserTester.h" -#include "DeclarationResolverTester.h" +#include "TypeResolverTester.h" #include "../common/infra/Assertions.h" @@ -67,8 +67,8 @@ std::tuple InternalsTestSuite::testAll() auto C = std::make_unique(this); C->testBinder(); - auto D = std::make_unique(this); - D->testDeclarationResolver(); + auto D = std::make_unique(this); + D->testTypeResolver(); auto res = std::make_tuple(P->totalPassed() + B->totalPassed() @@ -399,60 +399,58 @@ bool CVRMatches(const Type* ty, CVR cvr) { switch (cvr) { case CVR::Const: - if (!ty->isConstQualified()) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isConstQualified()) { DETAIL_MISMATCH("missing const"); return false; } break; case CVR::Volatile: - if (!ty->isVolatileQualified()) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isVolatileQualified()) { DETAIL_MISMATCH("missing volatile"); return false; } break; case CVR::ConstAndVolatile: - if (!(ty->isConstQualified()) - || !(ty->isVolatileQualified())) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isConstQualified() + || !ty->asQualifiedType()->isVolatileQualified()) { DETAIL_MISMATCH("missing const volatile"); return false; } break; case CVR::Restrict: - if (!ty->isRestrictQualified()) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isRestrictQualified()) { DETAIL_MISMATCH("missing restrict"); return false; } break; case CVR::ConstAndRestrict: - if (!(ty->isConstQualified()) - || !(ty->isRestrictQualified())) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isConstQualified() + || !ty->asQualifiedType()->isRestrictQualified()) { DETAIL_MISMATCH("missing const restrict"); return false; } break; case CVR::Atomic: - if (!ty->isAtomicQualified()) { + if (ty->kind() != TypeKind::Qualified + || !ty->asQualifiedType()->isAtomicQualified()) { DETAIL_MISMATCH("missing _Atomic"); return false; } break; case CVR::None: - if (ty->isConstQualified()) { - DETAIL_MISMATCH("spurious const"); - return false; - } - if (ty->isVolatileQualified()) { - DETAIL_MISMATCH("spurious volatile"); - return false; - } - if (ty->isRestrictQualified()) { - DETAIL_MISMATCH("spurious restrict"); + if (ty->kind() == TypeKind::Qualified) { + DETAIL_MISMATCH("spurious qualified type"); return false; } break; @@ -468,17 +466,19 @@ bool typeMatches(const Type* ty, const Ty& t) return false); for (auto i = t.derivTyKs_.size(); i > 0; --i) { - auto derivTyK = t.derivTyKs_[i - 1]; - if (derivTyK != ty->kind()) { - DETAIL_MISMATCH("derived array/pointer/function type kind"); - return false; - } - auto derivTyCVR = t.derivTyCVRs_[i - 1]; if (!CVRMatches(ty, derivTyCVR)) { DETAIL_MISMATCH("derived type CVR"); return false; } + if (ty->kind() == TypeKind::Qualified) + ty = ty->asQualifiedType()->unqualifiedType(); + + auto derivTyK = t.derivTyKs_[i - 1]; + if (derivTyK != ty->kind()) { + DETAIL_MISMATCH("derived array/pointer/function type kind"); + return false; + } auto derivPtrTyDecay = t.derivPtrTyDecay_[i - 1]; @@ -556,6 +556,13 @@ bool typeMatches(const Type* ty, const Ty& t) } } + if (!CVRMatches(ty, t.CVR_)) { + DETAIL_MISMATCH("type CVR"); + return false; + } + if (ty->kind() == TypeKind::Qualified) + ty = ty->asQualifiedType()->unqualifiedType(); + if (ty->kind() != t.tyK_) { DETAIL_MISMATCH("basic/void/typedef/tag type mismatch"); return false; @@ -594,11 +601,6 @@ bool typeMatches(const Type* ty, const Ty& t) PSY_ASSERT(false, return false); } - if (!CVRMatches(ty, t.CVR_)) { - DETAIL_MISMATCH("type CVR"); - return false; - } - return true; } @@ -736,13 +738,35 @@ bool symbolMatchesBinding_(const std::unique_ptr& declSym, co } // anonymous -void InternalsTestSuite::bind(std::string text, Expectation X) +void InternalsTestSuite::matchDeclarations( + std::unique_ptr semaModel, + std::vector decls) { - parse(text); - auto compilation = Compilation::create(tree_->filePath()); - compilation->addSyntaxTrees({ tree_.get() }); - auto semaModel = compilation->computeSemanticModel(tree_.get()); + for (const auto& Decl : decls) { +#ifdef DEBUG_BINDING_SEARCH + std::cout << "\n\t\t..."; +#endif + using namespace std::placeholders; + auto pred = std::bind(symbolMatchesBinding_, _1, Decl); + auto decl = semaModel->searchForDecl(pred); + if (decl == nullptr) { + std::ostringstream oss; + oss << "no declaration matches the expectation: "; + oss << " identifier: " << Decl.ident_; + oss << " kind: " << to_string(Decl.declSymK_); + PSY__internals__FAIL(oss.str()); + } +#ifdef DEBUG_BINDING_SEARCH + std::cout << "\n\t\tmatch! "; +#endif + } + +} +void InternalsTestSuite::checkSemanticModel( + std::unique_ptr semaModel, + Expectation X) +{ if (!checkErrorAndWarn(X)) return; @@ -760,7 +784,7 @@ void InternalsTestSuite::bind(std::string text, Expectation X) if (decl == nullptr) { std::ostringstream oss; oss << "no declaration matches the expectation: "; - oss << " name or tag: " << Decl.ident_; + oss << " identifier: " << Decl.ident_; oss << " kind: " << to_string(Decl.declSymK_); PSY__internals__FAIL(oss.str()); } @@ -783,14 +807,31 @@ void InternalsTestSuite::bind(std::string text, Expectation X) PSY_EXPECT_TRUE(sameDecl); PSY_EXPECT_TRUE(symbolMatchesBinding(sameDecl, Decl)); } - - // resolution - // decl } } -void InternalsTestSuite::resolve(std::string text, Expectation X) +std::unique_ptr InternalsTestSuite::semanticModel(std::string text) +{ + parse(text); + auto compilation = Compilation::create(tree_->filePath()); + compilation->addSyntaxTrees({ tree_.get() }); + std::unique_ptr semaModel( + new SemanticModel(tree_.get(), compilation.get())); + return semaModel; +} + +void InternalsTestSuite::bind(std::string text, Expectation X) +{ + auto semaModel = semanticModel(text); + semaModel->applyBinder(); + checkSemanticModel(std::move(semaModel), X); +} + +void InternalsTestSuite::resolveTypes(std::string text, Expectation X) { - bind(text, X); + auto semaModel = semanticModel(text); + semaModel->applyBinder(); + semaModel->applyTypeResolver(); + checkSemanticModel(std::move(semaModel), X); } diff --git a/C/tests/TestSuite_Internals.h b/C/tests/TestSuite_Internals.h index 520225c9..5bf55568 100644 --- a/C/tests/TestSuite_Internals.h +++ b/C/tests/TestSuite_Internals.h @@ -43,7 +43,7 @@ class InternalsTestSuite : public TestSuite friend class ParserTester; friend class ReparserTester; friend class BinderTester; - friend class DeclarationResolverTester; + friend class TypeResolverTester; public: virtual ~InternalsTestSuite(); @@ -70,9 +70,15 @@ class InternalsTestSuite : public TestSuite Reparser::DisambiguationStrategy strategy, Expectation X = Expectation()); + std::unique_ptr semanticModel(std::string text); + void checkSemanticModel( + std::unique_ptr semaModel, + Expectation X); + void matchDeclarations( + std::unique_ptr semaModel, + std::vector v); void bind(std::string text, Expectation X = Expectation()); - - void resolve(std::string text, Expectation X = Expectation()); + void resolveTypes(std::string text, Expectation X = Expectation()); std::unique_ptr tree_; std::unique_ptr compilation_; diff --git a/C/tests/TypeResolverTester.cpp b/C/tests/TypeResolverTester.cpp new file mode 100644 index 00000000..6b7220a1 --- /dev/null +++ b/C/tests/TypeResolverTester.cpp @@ -0,0 +1,177 @@ +// Copyright (c) 2024 Leandro T. C. Melo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "TypeResolverTester.h" + +using namespace psy; +using namespace C; + +const std::string TypeResolverTester::Name = "TYPE-RESOLVER"; + +void TypeResolverTester::testTypeResolver() +{ + return run(tests_); +} + +void TypeResolverTester::resolve(std::string text, Expectation X) +{ + (static_cast(suite_)->resolveTypes(text, X)); +} + +void TypeResolverTester::case0000() +{ + auto s = R"( +typedef double x ; +x y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Double))); +} + +void TypeResolverTester::case0001() +{ + auto s = R"( +typedef double x ; +x * y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Derived(TypeKind::Pointer) + .ty_.Basic(BasicTypeKind::Double))); +} + +void TypeResolverTester::case0002() +{ + auto s = R"( +typedef double x ; +x const y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Double, CVR::Const))); +} + +void TypeResolverTester::case0003() +{ + auto s = R"( +typedef double const x ; +x const y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Basic(BasicTypeKind::Double, CVR::Const))); +} + +void TypeResolverTester::case0004() +{ + auto s = R"( +typedef double x ; +x * * y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Derived(TypeKind::Pointer) + .ty_.Derived(TypeKind::Pointer) + .ty_.Basic(BasicTypeKind::Double))); +} + +void TypeResolverTester::case0005() +{ + auto s = R"( +typedef double x ; +x y [ 1 ] ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Derived(TypeKind::Array) + .ty_.Basic(BasicTypeKind::Double))); +} + +void TypeResolverTester::case0006() +{ + auto s = R"( +typedef double * x ; +x y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Derived(TypeKind::Pointer) + .ty_.Basic(BasicTypeKind::Double))); +} + +void TypeResolverTester::case0007() +{ + auto s = R"( +typedef double * * x ; +x y ; +)"; + + resolve(s, + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationSymbolKind::Variable) + .ty_.Derived(TypeKind::Pointer) + .ty_.Derived(TypeKind::Pointer) + .ty_.Basic(BasicTypeKind::Double))); +} +void TypeResolverTester::case0008(){} +void TypeResolverTester::case0009(){} +void TypeResolverTester::case0010(){} +void TypeResolverTester::case0011(){} +void TypeResolverTester::case0012(){} +void TypeResolverTester::case0013(){} +void TypeResolverTester::case0014(){} +void TypeResolverTester::case0015(){} +void TypeResolverTester::case0016(){} +void TypeResolverTester::case0017(){} +void TypeResolverTester::case0018(){} +void TypeResolverTester::case0019(){} +void TypeResolverTester::case0020(){} +void TypeResolverTester::case0021(){} +void TypeResolverTester::case0022(){} +void TypeResolverTester::case0023(){} +void TypeResolverTester::case0024(){} +void TypeResolverTester::case0025(){} +void TypeResolverTester::case0026(){} +void TypeResolverTester::case0027(){} +void TypeResolverTester::case0028(){} +void TypeResolverTester::case0029(){} diff --git a/C/tests/DeclarationResolverTester.h b/C/tests/TypeResolverTester.h similarity index 89% rename from C/tests/DeclarationResolverTester.h rename to C/tests/TypeResolverTester.h index fc25552b..5e7f081a 100644 --- a/C/tests/DeclarationResolverTester.h +++ b/C/tests/TypeResolverTester.h @@ -25,31 +25,26 @@ #include "TestSuite_Internals.h" #include "tests/Tester.h" -#define TEST_DECLARATION_RESOLVER(Function) TestFunction { &DeclarationResolverTester::Function, #Function } +#define TEST_DECLARATION_RESOLVER(Function) TestFunction { &TypeResolverTester::Function, #Function } namespace psy { namespace C { -class DeclarationResolverTester final : public Tester +class TypeResolverTester final : public Tester { public: - DeclarationResolverTester(TestSuite* suite) + TypeResolverTester(TestSuite* suite) : Tester(suite) {} static const std::string Name; virtual std::string name() const override { return Name; } - void testDeclarationResolver(); + void testTypeResolver(); void resolve(std::string text, Expectation X); - using TestFunction = std::pair, const char*>; - - /* - xxxx - + 0000-0099 -> multiplication x pointer declaration - */ + using TestFunction = std::pair, const char*>; void case0000(); void case0001(); diff --git a/C/types/Type.cpp b/C/types/Type.cpp index 16aef4e3..95983c3f 100644 --- a/C/types/Type.cpp +++ b/C/types/Type.cpp @@ -33,46 +33,6 @@ TypeKind Type::kind() const return TypeKind(P->BF_.tyK_); } -bool Type::isConstQualified() const -{ - return P->BF_.const_; -} - -bool Type::isVolatileQualified() const -{ - return P->BF_.volatile_; -} - -bool Type::isRestrictQualified() const -{ - return P->BF_.restrict_; -} - -bool Type::isAtomicQualified() const -{ - return P->BF_.atomic_; -} - -void Type::qualifyWithConst() -{ - P->BF_.const_ = 1; -} - -void Type::qualifyWithVolatile() -{ - P->BF_.volatile_ = 1; -} - -void Type::qualifyWithRestrict() -{ - P->BF_.restrict_ = 1; -} - -void Type::qualifyWithAtomic() -{ - P->BF_.atomic_ = 1; -} - namespace psy { namespace C { @@ -93,6 +53,8 @@ std::string PSY_C_API to_string(const Type& ty) return to_string(*ty.asTagType()); case TypeKind::Void: return to_string(*ty.asVoidType()); + case TypeKind::Qualified: + return to_string(*ty.asQualifiedType()); } } diff --git a/C/types/Type.h b/C/types/Type.h index fce5eb51..7b785e49 100644 --- a/C/types/Type.h +++ b/C/types/Type.h @@ -36,8 +36,7 @@ namespace C { * \brief The Type class. * * \note Similar to: - * - \c clang::Type and clang::QualType of LLMV/Clang. - * - \c Microsoft.CodeAnalysis.ITypeDeclarationSymbol of Roslyn. + * - \c clang::Type and clang::Type of LLMV/Clang. * * \see TypeDeclarationSymbol */ @@ -64,6 +63,8 @@ class PSY_C_API Type virtual const TagType* asTagType() const { return nullptr; } virtual VoidType* asVoidType() { return nullptr; } virtual const VoidType* asVoidType() const { return nullptr; } + virtual QualifiedType* asQualifiedType() { return nullptr; } + virtual const QualifiedType* asQualifiedType() const { return nullptr; } //!@} /** @@ -71,34 +72,9 @@ class PSY_C_API Type */ TypeKind kind() const; - /** - * Whether \c this Type is \c const qualified. - */ - bool isConstQualified() const; - - /** - * Whether \c this Type is \c volatile qualified. - */ - bool isVolatileQualified() const; - - /** - * Whether \c this Type is \c restrict qualified. - */ - bool isRestrictQualified() const; - - /** - * Whether \c this Type is \c _Atomic qualified. - */ - bool isAtomicQualified() const; - PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Binder); - void qualifyWithConst(); - void qualifyWithVolatile(); - void qualifyWithRestrict(); - void qualifyWithAtomic(); - protected: DECL_PIMPL(Type); Type(TypeImpl* p); diff --git a/C/types/TypeKind.h b/C/types/TypeKind.h index d7eff894..7a17cd5b 100644 --- a/C/types/TypeKind.h +++ b/C/types/TypeKind.h @@ -42,12 +42,13 @@ enum class PSY_C_API TypeKind : std::uint8_t Pointer, Typedef, Tag, - Void + Void, + Qualified }; -inline std::string PSY_C_API to_string(TypeKind tyKind) +inline std::string PSY_C_API to_string(TypeKind tyK) { - switch (tyKind) { + switch (tyK) { case TypeKind::Array: return "Array"; case TypeKind::Basic: @@ -62,6 +63,8 @@ inline std::string PSY_C_API to_string(TypeKind tyKind) return "Tag"; case TypeKind::Void: return "Void"; + case TypeKind::Qualified: + return "Qualified"; } } diff --git a/C/types/Type_ALL.h b/C/types/Type_ALL.h index 0064cea2..8303db62 100644 --- a/C/types/Type_ALL.h +++ b/C/types/Type_ALL.h @@ -28,5 +28,6 @@ #include "Type_Typedef.h" #include "Type_Tag.h" #include "Type_Void.h" +#include "Type_Qualified.h" #endif diff --git a/C/types/Type_Array.cpp b/C/types/Type_Array.cpp index e0797e64..75d0e5ab 100644 --- a/C/types/Type_Array.cpp +++ b/C/types/Type_Array.cpp @@ -46,6 +46,11 @@ const Type* ArrayType::elementType() const return P_CAST->elemTy_; } +void ArrayType::resetElementType(const Type* elemTy) const +{ + P_CAST->elemTy_ = elemTy; +} + namespace psy { namespace C { diff --git a/C/types/Type_Array.h b/C/types/Type_Array.h index b647f3c6..5134e0e0 100644 --- a/C/types/Type_Array.h +++ b/C/types/Type_Array.h @@ -49,9 +49,12 @@ class PSY_C_API ArrayType final : public Type PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Binder); + PSY_GRANT_INTERNAL_ACCESS(TypeResolver); ArrayType(const Type* elemTy); + void resetElementType(const Type*) const; + private: DECL_PIMPL_SUB(ArrayType) }; diff --git a/C/types/Type_Pointer.cpp b/C/types/Type_Pointer.cpp index ddf3aead..911a5620 100644 --- a/C/types/Type_Pointer.cpp +++ b/C/types/Type_Pointer.cpp @@ -18,8 +18,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "Type_Pointer.h" #include "Type__IMPL__.inc" +#include "Type_Pointer.h" #include #include @@ -41,6 +41,11 @@ PointerType::PointerType(const Type* refedTy) : Type(new PointerTypeImpl(refedTy)) {} +void PointerType::resetReferencedType(const Type* refedTy) const +{ + P_CAST->refedTy_ = refedTy; +} + const Type* PointerType::referencedType() const { return P_CAST->refedTy_; @@ -72,8 +77,8 @@ namespace C { std::string PSY_C_API to_string(const PointerType& ptrTy) { std::ostringstream oss; - oss << ""; return oss.str(); } diff --git a/C/types/Type_Pointer.h b/C/types/Type_Pointer.h index b798a806..7073db08 100644 --- a/C/types/Type_Pointer.h +++ b/C/types/Type_Pointer.h @@ -36,8 +36,8 @@ class PSY_C_API PointerType final : public Type /** * Cast \c this Type as an PointerType. */ - virtual PointerType* asPointerType() { return this; } - virtual const PointerType* asPointerType() const { return this; } + virtual PointerType* asPointerType() override { return this; } + virtual const PointerType* asPointerType() const override { return this; } //!@} /** @@ -63,11 +63,13 @@ class PSY_C_API PointerType final : public Type PSY_INTERNAL: PSY_GRANT_INTERNAL_ACCESS(Binder); + PSY_GRANT_INTERNAL_ACCESS(TypeResolver); PointerType(const Type* refedTy); void markAsArisingFromArrayDecay(); void markAsArisingFromFunctionDecay(); + void resetReferencedType(const Type*) const; private: DECL_PIMPL_SUB(PointerType) diff --git a/C/types/Type_Qualified.cpp b/C/types/Type_Qualified.cpp new file mode 100644 index 00000000..7d995eb8 --- /dev/null +++ b/C/types/Type_Qualified.cpp @@ -0,0 +1,107 @@ +// Copyright (c) 2024 Leandro T. C. Melo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include "Type__IMPL__.inc" +#include "Type_Qualified.h" + +#include +#include + +using namespace psy; +using namespace C; + +struct QualifiedType::QualifiedTypeImpl : TypeImpl +{ + QualifiedTypeImpl(const Type* unqualTy) + : TypeImpl(TypeKind::Qualified) + , unqualTy_(unqualTy) + {} + + const Type* unqualTy_; +}; + +QualifiedType::QualifiedType(const Type* unqualTy) + : Type(new QualifiedTypeImpl(unqualTy)) +{} + +const Type* QualifiedType::unqualifiedType() const +{ + return P_CAST->unqualTy_; +} + +void QualifiedType::resetUnqualifiedType(const Type* unqualTy) const +{ + P_CAST->unqualTy_ = unqualTy; +} + +bool QualifiedType::isConstQualified() const +{ + return P->BF_.const_; +} + +bool QualifiedType::isVolatileQualified() const +{ + return P->BF_.volatile_; +} + +bool QualifiedType::isRestrictQualified() const +{ + return P->BF_.restrict_; +} + +bool QualifiedType::isAtomicQualified() const +{ + return P->BF_.atomic_; +} + +void QualifiedType::qualifyWithConst() +{ + P->BF_.const_ = 1; +} + +void QualifiedType::qualifyWithVolatile() +{ + P->BF_.volatile_ = 1; +} + +void QualifiedType::qualifyWithRestrict() +{ + P->BF_.restrict_ = 1; +} + +void QualifiedType::qualifyWithAtomic() +{ + P->BF_.atomic_ = 1; +} + +namespace psy { +namespace C { + +std::string PSY_C_API to_string(const QualifiedType& qualTy) +{ + std::ostringstream oss; + oss << ""; + return oss.str(); +} + +} // C +} // psy diff --git a/C/types/Type_Qualified.h b/C/types/Type_Qualified.h new file mode 100644 index 00000000..887f1782 --- /dev/null +++ b/C/types/Type_Qualified.h @@ -0,0 +1,90 @@ +// Copyright (c) 2024 Leandro T. C. Melo +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef PSYCHE_C_TYPE_QUALIFIED_H__ +#define PSYCHE_C_TYPE_QUALIFIED_H__ + +#include "API.h" +#include "Fwds.h" + +#include "Type.h" + +namespace psy { +namespace C { + +class PSY_C_API QualifiedType final : public Type +{ +public: + //!@{ + /** + * Cast \c this Type as an QualifiedType. + */ + virtual QualifiedType* asQualifiedType() override { return this; } + virtual const QualifiedType* asQualifiedType() const override { return this; } + //!@} + + /** + * The Type that is the \a unqualified version of \c this QualifiedType. + */ + const Type* unqualifiedType() const; + + /** + * Whether \c this Type is \c const qualified. + */ + bool isConstQualified() const; + + /** + * Whether \c this Type is \c volatile qualified. + */ + bool isVolatileQualified() const; + + /** + * Whether \c this Type is \c restrict qualified. + */ + bool isRestrictQualified() const; + + /** + * Whether \c this Type is \c _Atomic qualified. + */ + bool isAtomicQualified() const; + +PSY_INTERNAL: + PSY_GRANT_INTERNAL_ACCESS(Binder); + PSY_GRANT_INTERNAL_ACCESS(TypeResolver); + + QualifiedType(const Type* unqualTy); + + void qualifyWithConst(); + void qualifyWithVolatile(); + void qualifyWithRestrict(); + void qualifyWithAtomic(); + + void resetUnqualifiedType(const Type*) const; + +private: + DECL_PIMPL_SUB(QualifiedType); +}; + +std::string PSY_C_API to_string(const QualifiedType& qualTy); + +} // C +} // psy + +#endif