diff --git a/C/sema/SemanticModel.cpp b/C/sema/SemanticModel.cpp index 8e4d056bb..7b7bcba04 100644 --- a/C/sema/SemanticModel.cpp +++ b/C/sema/SemanticModel.cpp @@ -143,7 +143,7 @@ TypeInfo SemanticModel::typeInfoOf_CORE(const SyntaxNode* node) if (it != P->tyInfoByNode_.end()) return it->second; return TypeInfo(compilation()->canonicalErrorType(), - TypeInfo::TypeOrigin::Error); + TypeInfo::Origin::Error); } TypeInfo SemanticModel::typeInfoOf(const ExpressionSyntax* node) const diff --git a/C/sema/TypeChecker.cpp b/C/sema/TypeChecker.cpp index af9a009c8..ede01f400 100644 --- a/C/sema/TypeChecker.cpp +++ b/C/sema/TypeChecker.cpp @@ -360,18 +360,18 @@ bool TypeChecker::satisfyRealTypeConstraint(const Type* ty, const SyntaxNode* no } bool TypeChecker::typesAreCompatible( - const Type* oneTy, - const Type* otherTy, + const Type* ty1, + const Type* ty2, bool treatVoidAsAny, bool ignoreQualifier) { - switch (oneTy->kind()) { + switch (ty1->kind()) { case TypeKind::Array: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: return typesAreCompatible( - oneTy->asArrayType()->elementType(), - otherTy->asArrayType()->elementType(), + ty1->asArrayType()->elementType(), + ty2->asArrayType()->elementType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Basic: @@ -379,14 +379,14 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Pointer: return typesAreCompatible( - oneTy->asArrayType()->elementType(), - otherTy->asPointerType()->referencedType(), + ty1->asArrayType()->elementType(), + ty2->asPointerType()->referencedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -401,18 +401,18 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Basic: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: break; case TypeKind::Basic: - return oneTy->asBasicType()->kind() == otherTy->asBasicType()->kind(); + return ty1->asBasicType()->kind() == ty2->asBasicType()->kind(); case TypeKind::Function: case TypeKind::Pointer: break; case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -421,8 +421,8 @@ bool TypeChecker::typesAreCompatible( case TypeKind::Qualified: if (ignoreQualifier) return typesAreCompatible( - oneTy, - otherTy->asQualifiedType()->unqualifiedType(), + ty1, + ty2->asQualifiedType()->unqualifiedType(), treatVoidAsAny, false); break; @@ -432,16 +432,66 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Function: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: case TypeKind::Basic: - case TypeKind::Function: + case TypeKind::Function: { + auto funcTy1 = ty1->asFunctionType(); + auto funcTy2 = ty2->asFunctionType(); + if (!typesAreCompatible( + funcTy1->returnType(), + funcTy2->returnType(), + false, + ignoreQualifier)) { + break; + } + auto parmListForm1 = funcTy1->parameterListForm(); + auto parmListForm2 = funcTy2->parameterListForm(); + switch (parmListForm1) { + case FunctionType::ParameterListForm::SpecifiedAsEmpty: + return parmListForm2 == FunctionType::ParameterListForm::SpecifiedAsEmpty + || parmListForm2 == FunctionType::ParameterListForm::Unspecified; + case FunctionType::ParameterListForm::Unspecified: + return true; + case FunctionType::ParameterListForm::NonEmpty: { + if (parmListForm2 == FunctionType::ParameterListForm::SpecifiedAsEmpty) + break; + if (parmListForm2 == FunctionType::ParameterListForm::Unspecified) + return true; + auto parmsTys1 = funcTy1->parameterTypes(); + auto parmsTys2 = funcTy2->parameterTypes(); + auto parmsSz1 = parmsTys1.size(); + if (parmsSz1 == parmsTys2.size()) { + auto parmsAreIncompatible = false; + for (auto idx = 0U; idx < parmsSz1; ++idx) { + auto parmTy1 = parmsTys1[idx]; + auto parmTy2 = parmsTys2[idx]; + if (!typesAreCompatible( + parmTy1, + parmTy2, + treatVoidAsAny, + ignoreQualifier)) { + parmsAreIncompatible = true; + break; + } + } + if (!parmsAreIncompatible) + return true; + } + break; + } + default: + PSY_ASSERT_1(false); + break; + } + break; + } case TypeKind::Pointer: break; case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -456,11 +506,11 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Pointer: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: return typesAreCompatible( - oneTy->asPointerType()->referencedType(), - otherTy->asArrayType()->elementType(), + ty1->asPointerType()->referencedType(), + ty2->asArrayType()->elementType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Basic: @@ -468,14 +518,14 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Pointer: return typesAreCompatible( - oneTy->asPointerType()->referencedType(), - otherTy->asPointerType()->referencedType(), + ty1->asPointerType()->referencedType(), + ty2->asPointerType()->referencedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -494,7 +544,7 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Tag: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: case TypeKind::Basic: case TypeKind::Function: @@ -502,15 +552,15 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: { - auto oneTagTy = oneTy->asTagType(); - auto otherTagTy = otherTy->asTagType(); - return oneTagTy->kind() == otherTagTy->kind() - && oneTy->asTagType()->tag() == otherTy->asTagType()->tag(); + auto tagTy1 = ty1->asTagType(); + auto tagTy2 = ty2->asTagType(); + return tagTy1->kind() == tagTy2->kind() + && ty1->asTagType()->tag() == ty2->asTagType()->tag(); } case TypeKind::Void: return treatVoidAsAny; @@ -522,7 +572,7 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::Void: - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: case TypeKind::Basic: case TypeKind::Function: @@ -530,8 +580,8 @@ bool TypeChecker::typesAreCompatible( return treatVoidAsAny; case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -548,11 +598,11 @@ bool TypeChecker::typesAreCompatible( case TypeKind::Qualified: if (ignoreQualifier) return typesAreCompatible( - oneTy->asQualifiedType()->unqualifiedType(), - otherTy, + ty1->asQualifiedType()->unqualifiedType(), + ty2, treatVoidAsAny, ignoreQualifier); - switch (otherTy->kind()) { + switch (ty2->kind()) { case TypeKind::Array: case TypeKind::Basic: case TypeKind::Function: @@ -560,8 +610,8 @@ bool TypeChecker::typesAreCompatible( break; case TypeKind::TypedefName: return typesAreCompatible( - oneTy, - otherTy->asTypedefNameType()->resolvedSynonymizedType(), + ty1, + ty2->asTypedefNameType()->resolvedSynonymizedType(), treatVoidAsAny, ignoreQualifier); case TypeKind::Tag: @@ -569,13 +619,13 @@ bool TypeChecker::typesAreCompatible( case TypeKind::Void: return treatVoidAsAny; case TypeKind::Qualified: { - auto oneQualTy = oneTy->asQualifiedType(); - auto otherQualTy = otherTy->asQualifiedType(); - if (oneQualTy->qualifiers() != otherQualTy->qualifiers()) + auto qualTy1 = ty1->asQualifiedType(); + auto qualTy2 = ty2->asQualifiedType(); + if (qualTy1->qualifiers() != qualTy2->qualifiers()) return false; return typesAreCompatible( - oneQualTy->unqualifiedType(), - otherQualTy->unqualifiedType(), + qualTy1->unqualifiedType(), + qualTy2->unqualifiedType(), treatVoidAsAny, ignoreQualifier); } @@ -601,17 +651,23 @@ bool TypeChecker::isNULLPointerConstant(const SyntaxNode* node) void TypeChecker::createTypeInfo( const SyntaxNode* node, const Type* ty, - TypeInfo::TypeOrigin tyOrig) + TypeInfo::Origin tyOrig) { + auto undergoneConv = TypeInfo::UndergoneConversion::No; + if (ty->kind() == TypeKind::Function) { + std::unique_ptr ptrTy(new PointerType(ty)); + ty = semaModel_->keepType(std::move(ptrTy)); + undergoneConv = TypeInfo::UndergoneConversion::Yes; + } ty_ = ty; - TypeInfo tyInfo(ty_, tyOrig); + TypeInfo tyInfo(ty_, tyOrig, undergoneConv); semaModel_->setTypeInfoOf(node, std::move(tyInfo)); } SyntaxVisitor::Action TypeChecker::typeChecked( const ExpressionSyntax* node, const Type* ty, - TypeInfo::TypeOrigin tyOrig) + TypeInfo::Origin tyOrig) { PSY_ASSERT_2(ty, return Action::Quit); createTypeInfo(node, ty, tyOrig); @@ -620,9 +676,10 @@ SyntaxVisitor::Action TypeChecker::typeChecked( SyntaxVisitor::Action TypeChecker::typeCheckError(const SyntaxNode* node) { - createTypeInfo(node, - semaModel_->compilation()->canonicalErrorType(), - TypeInfo::TypeOrigin::Error); + createTypeInfo( + node, + semaModel_->compilation()->canonicalErrorType(), + TypeInfo::Origin::Error); return Action::Quit; } @@ -630,57 +687,15 @@ SyntaxVisitor::Action TypeChecker::typeCheckError(const SyntaxNode* node) // Declarations // //--------------// -void TypeChecker::determineParameterListForm(FunctionDeclarationSymbol* func) -{ - PSY_ASSERT_2(func->type(), return); - PSY_ASSERT_2(func->type()->kind() == TypeKind::Function, return); - - auto funcTy = func->type()->asFunctionType(); - auto parmTys = funcTy->parameterTypes(); - if (parmTys.size() == 0) - funcTy->setParameterListForm( - FunctionType::ParameterListForm::Unspecified); - else { - if (parmTys.size() == 1) { - auto resolvedParmTy = resolved(parmTys[0]); - if (resolvedParmTy && resolvedParmTy->kind() == TypeKind::Void) - funcTy->setParameterListForm( - FunctionType::ParameterListForm::SpecifiedAsEmpty); - else - funcTy->setParameterListForm( - FunctionType::ParameterListForm::NonEmpty); - } - else - funcTy->setParameterListForm( - FunctionType::ParameterListForm::NonEmpty); - } -} - SyntaxVisitor::Action TypeChecker::visitVariableAndOrFunctionDeclaration( const VariableAndOrFunctionDeclarationSyntax* node) { - auto decls = semaModel_->variableAndOrFunctionsFor(node); - for (auto decl : decls) { - PSY_ASSERT_2(decl, continue); - switch (decl->kind()) { - case SymbolKind::FunctionDeclaration: - determineParameterListForm(decl->asFunctionDeclaration()); - break; - default: - break; - } - } - return Action::Visit; } SyntaxVisitor::Action TypeChecker::visitFunctionDefinition( const FunctionDefinitionSyntax* node) { - auto func = semaModel_->functionFor(node); - PSY_ASSERT_2(func, return Action::Quit); - determineParameterListForm(func); - return Action::Visit; } @@ -1660,7 +1675,7 @@ SyntaxVisitor::Action TypeChecker::visitTypeName(const TypeNameSyntax* node) return Action::Quit; } PSY_ASSERT_2(ty, return Action::Quit); - createTypeInfo(node, ty, TypeInfo::TypeOrigin::TypeName); + createTypeInfo(node, ty, TypeInfo::Origin::TypeName); return Action::Skip; } diff --git a/C/sema/TypeChecker.h b/C/sema/TypeChecker.h index 96a466511..0501d20c9 100644 --- a/C/sema/TypeChecker.h +++ b/C/sema/TypeChecker.h @@ -221,10 +221,10 @@ class PSY_C_INTERNAL_API TypeChecker final : protected SyntaxVisitor //--------// virtual Action visitTypeName(const TypeNameSyntax*) override; - void createTypeInfo(const SyntaxNode*, const Type*, TypeInfo::TypeOrigin); + void createTypeInfo(const SyntaxNode*, const Type*, TypeInfo::Origin); Action typeChecked(const ExpressionSyntax*, const Type*, - TypeInfo::TypeOrigin = TypeInfo::TypeOrigin::Expression); + TypeInfo::Origin = TypeInfo::Origin::ExpressionTyping); Action typeCheckError(const SyntaxNode*); static const Type* resolved(const Type* ty); @@ -232,8 +232,6 @@ class PSY_C_INTERNAL_API TypeChecker final : protected SyntaxVisitor const Type* typeOfStringLiteral(StringLiteral::EncodingPrefix encodingSuffix); - void determineParameterListForm(FunctionDeclarationSymbol* func); - bool isNULLPointerConstant(const SyntaxNode* node); bool isAssignableType(const Type* ty, const SyntaxNode* node); bool isTypeAssignableFromOtherType(const Type* ty, diff --git a/C/sema/TypeInfo.cpp b/C/sema/TypeInfo.cpp index e5416a82c..572484006 100644 --- a/C/sema/TypeInfo.cpp +++ b/C/sema/TypeInfo.cpp @@ -23,17 +23,36 @@ using namespace psy; using namespace C; -TypeInfo::TypeInfo(const Type* ty, TypeOrigin tyOrig) +TypeInfo::TypeInfo(const Type* ty, Origin orig) : ty_(ty) - , tyOrig_(tyOrig) + , orig_(orig) + , undergoneConv_(UndergoneConversion::No) +{} + +TypeInfo::TypeInfo(const Type* ty, + Origin tyOrig, + UndergoneConversion undergoneConv) + : ty_(ty) + , orig_(tyOrig) + , undergoneConv_(undergoneConv) {} TypeInfo::~TypeInfo() {} -TypeInfo::TypeOrigin TypeInfo::typeOrigin() const +TypeInfo::Origin TypeInfo::origin() const +{ + return orig_; +} + +void TypeInfo::markAsUndergoneConversion() +{ + undergoneConv_ = UndergoneConversion::Yes; +} + +TypeInfo::UndergoneConversion TypeInfo::undergoneConversion() const { - return tyOrig_; + return undergoneConv_; } const Type* TypeInfo::type() const diff --git a/C/sema/TypeInfo.h b/C/sema/TypeInfo.h index d3fe1e387..22e250dbb 100644 --- a/C/sema/TypeInfo.h +++ b/C/sema/TypeInfo.h @@ -40,19 +40,30 @@ class PSY_C_API TypeInfo final ~TypeInfo(); /** - * The alternatives of a TypeOrigin. + * The alternatives of a type origin. */ - enum class TypeOrigin : std::uint8_t + enum class Origin : std::uint8_t { Error, - Expression, + ExpressionTyping, TypeName, }; /** - * The TypeOrigin of the Type of \c this TypeInfo. + * The origin of the Type of \c this TypeInfo. */ - TypeOrigin typeOrigin() const; + Origin origin() const; + + /** + * Wheter the type has undergone conversion. + **/ + enum class UndergoneConversion : std::uint8_t + { + No, + Yes, + }; + + UndergoneConversion undergoneConversion() const; /** * The Type of \c this TypeInfo. @@ -63,11 +74,15 @@ class PSY_C_API TypeInfo final PSY_GRANT_INTERNAL_ACCESS(TypeChecker); PSY_GRANT_INTERNAL_ACCESS(SemanticModel); + void markAsUndergoneConversion(); + private: - TypeInfo(const Type* ty, TypeOrigin tyOrig); + TypeInfo(const Type* ty, Origin orig); + TypeInfo(const Type* ty, Origin orig, UndergoneConversion undergoneConv); const Type* ty_; - TypeOrigin tyOrig_; + Origin orig_; + UndergoneConversion undergoneConv_; }; } // C diff --git a/C/sema/TypedefNameTypeResolver.cpp b/C/sema/TypedefNameTypeResolver.cpp index 89bbe5738..c51778758 100644 --- a/C/sema/TypedefNameTypeResolver.cpp +++ b/C/sema/TypedefNameTypeResolver.cpp @@ -95,10 +95,10 @@ const Type* TypedefNameTypeResolver::resolve(const Type* ty) auto resolvedTy = resolve(retTy); if (resolvedTy != retTy) funcTy->setReturnType(resolvedTy); - const auto parms = funcTy->parameterTypes(); - const auto parmsSize = parms.size(); - for (FunctionType::ParameterTypes::size_type idx = 0; idx < parmsSize; ++idx) { - const Type* parmTy = parms[idx]; + const auto parmsTys = funcTy->parameterTypes(); + const auto parmsSz = parmsTys.size(); + for (FunctionType::ParameterTypes::size_type idx = 0; idx < parmsSz; ++idx) { + const Type* parmTy = parmsTys[idx]; resolvedTy = resolve(parmTy); if (resolvedTy != parmTy) funcTy->setParameterType(idx, resolvedTy); diff --git a/C/tests/SemanticModelTester.cpp b/C/tests/SemanticModelTester.cpp index 873d4a6e9..a24441761 100644 --- a/C/tests/SemanticModelTester.cpp +++ b/C/tests/SemanticModelTester.cpp @@ -1179,7 +1179,8 @@ void SemanticModelTester::case0503() auto tyInfo = semaModel->typeInfoOf(exprNode); auto ty = tyInfo.type(); PSY_EXPECT_TRUE(ty); - PSY_EXPECT_EQ_ENU(ty->kind(), TypeKind::Function, TypeKind); + PSY_EXPECT_EQ_ENU(ty->kind(), TypeKind::Pointer, TypeKind); + PSY_EXPECT_EQ_ENU(ty->asPointerType()->referencedType()->kind(), TypeKind::Function, TypeKind); exprNode = exprNodeByText["f ( )"]; PSY_EXPECT_TRUE(exprNode); @@ -1199,7 +1200,8 @@ void SemanticModelTester::case0504() auto tyInfo = semaModel->typeInfoOf(exprNode); auto ty = tyInfo.type(); PSY_EXPECT_TRUE(ty); - PSY_EXPECT_EQ_ENU(ty->kind(), TypeKind::Function, TypeKind); + PSY_EXPECT_EQ_ENU(ty->kind(), TypeKind::Pointer, TypeKind); + PSY_EXPECT_EQ_ENU(ty->asPointerType()->referencedType()->kind(), TypeKind::Function, TypeKind); exprNode = exprNodeByText["f ( )"]; PSY_EXPECT_TRUE(exprNode); diff --git a/C/tests/TypeCheckerTester.cpp b/C/tests/TypeCheckerTester.cpp index 45060a8c1..eee61bf00 100644 --- a/C/tests/TypeCheckerTester.cpp +++ b/C/tests/TypeCheckerTester.cpp @@ -4223,21 +4223,242 @@ void _ () TypeChecker::DiagnosticsReporter::ID_of_CannotAssignToExpressionOfConstQualifiedType)); } -void TypeCheckerTester::case0733(){} -void TypeCheckerTester::case0734(){} -void TypeCheckerTester::case0735(){} -void TypeCheckerTester::case0736(){} -void TypeCheckerTester::case0737(){} -void TypeCheckerTester::case0738(){} -void TypeCheckerTester::case0739(){} -void TypeCheckerTester::case0740(){} -void TypeCheckerTester::case0741(){} - -void TypeCheckerTester::case0742(){} -void TypeCheckerTester::case0743(){} -void TypeCheckerTester::case0744(){} -void TypeCheckerTester::case0745(){} -void TypeCheckerTester::case0746(){} +void TypeCheckerTester::case0733() +{ + auto s = R"( +void _ () +{ + typedef void ( * t ) (); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0734() +{ + auto s = R"( +void _ ( int * p , int * q ) +{ + typedef void ( * t ) ( double ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0735() +{ + auto s = R"( +void _ ( void ) +{ + typedef void ( * t ) ( double ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0736() +{ + auto s = R"( +void _ ( void ) +{ + typedef void ( * t ) ( void ); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0737() +{ + auto s = R"( +void _ ( int y ) +{ + typedef void ( * t ) ( void ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0738() +{ + auto s = R"( +void _ ( int y ) +{ + typedef void ( * t ) ( ); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0739() +{ + auto s = R"( +double _ ( int y ) +{ + typedef void ( * t ) ( int ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0740() +{ + auto s = R"( +void _ ( int y ) +{ + typedef double ( * t ) ( int ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0741() +{ + auto s = R"( +double _ ( int y ) +{ + typedef double ( * t ) ( int ); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0742() +{ + auto s = R"( +double _ ( int y ) +{ + typedef double ( * t ) ( short ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0743() +{ + auto s = R"( +double _ ( short y ) +{ + typedef double ( * t ) ( int ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + +void TypeCheckerTester::case0744() +{ + auto s = R"( +void _ ( void ) +{ + typedef void ( * t ) ( ); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0745() +{ + auto s = R"( +void _ ( ) +{ + typedef void ( * t ) ( void ); + t x ; + x = _ ; +} + )"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0746() +{ + auto s = R"( +double * _ ( int y ) +{ + typedef void * ( * t ) ( int ); + t x ; + x = _ ; +} + )"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment)); +} + void TypeCheckerTester::case0747(){} void TypeCheckerTester::case0748(){} void TypeCheckerTester::case0749(){} diff --git a/C/types/Type_Function.cpp b/C/types/Type_Function.cpp index 49e80eeec..18f0f1ae1 100644 --- a/C/types/Type_Function.cpp +++ b/C/types/Type_Function.cpp @@ -21,6 +21,7 @@ #include "Type_Function.h" #include "Type__IMPL__.inc" +#include "types/Type_TypedefName.h" #include "../common/infra/Assertions.h" #include @@ -70,11 +71,6 @@ void FunctionType::setParameterType(ParameterTypes::size_type idx, const Type* p P_CAST->paramTys_[idx] = paramTy; } -void FunctionType::setParameterListForm(ParameterListForm form) -{ - P_CAST->F_.parmListForm_ = static_cast(form); -} - bool FunctionType::isVariadic() const { return P_CAST->F_.isVariadic_; @@ -87,7 +83,17 @@ void FunctionType::markAsVariadic() FunctionType::ParameterListForm FunctionType::parameterListForm() const { - return ParameterListForm(P_CAST->F_.parmListForm_); + auto sz = P_CAST->paramTys_.size(); + if (sz == 0) + return FunctionType::ParameterListForm::Unspecified; + if (sz > 1) + return FunctionType::ParameterListForm::NonEmpty; + auto parmTy = P_CAST->paramTys_[0]; + if (parmTy->kind() == TypeKind::TypedefName) + parmTy = parmTy->asTypedefNameType()->resolvedSynonymizedType(); + return parmTy && parmTy->kind() == TypeKind::Void + ? FunctionType::ParameterListForm::SpecifiedAsEmpty + : FunctionType::ParameterListForm::NonEmpty; } namespace psy { diff --git a/C/types/Type_Function.h b/C/types/Type_Function.h index 4024c5d0c..09aaff7ea 100644 --- a/C/types/Type_Function.h +++ b/C/types/Type_Function.h @@ -89,7 +89,6 @@ class PSY_C_API FunctionType final : public Type void addParameterType(const Type* paramTy); void setParameterType(ParameterTypes::size_type idx, const Type* paramTy) const; void setReturnType(const Type* retTy) const; - void setParameterListForm(ParameterListForm form); void markAsVariadic(); private: diff --git a/C/types/Type__IMPL__.inc b/C/types/Type__IMPL__.inc index e040f8447..3919e3cec 100644 --- a/C/types/Type__IMPL__.inc +++ b/C/types/Type__IMPL__.inc @@ -47,7 +47,6 @@ struct Type::TypeImpl std::uint32_t tagTyK_ : 2; // FunctionType - std::uint32_t parmListForm_ : 2; std::uint32_t isVariadic_ : 1; }; union