diff --git a/C/CMakeLists.txt b/C/CMakeLists.txt index 913701e9b..124cf78c4 100644 --- a/C/CMakeLists.txt +++ b/C/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) project(cfe) diff --git a/C/sema/DiagnosticsReporter_TypeChecker.cpp b/C/sema/DiagnosticsReporter_TypeChecker.cpp index 3f4afffff..93d7b0300 100644 --- a/C/sema/DiagnosticsReporter_TypeChecker.cpp +++ b/C/sema/DiagnosticsReporter_TypeChecker.cpp @@ -39,11 +39,12 @@ const std::string TypeChecker::DiagnosticsReporter::ID_of_ExpectedExpression = " const std::string TypeChecker::DiagnosticsReporter::ID_of_UnknownMemberOfTag = "TypeChecker-011"; const std::string TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInAssignment = "TypeChecker-012"; const std::string TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInArgumentToParameterAssignment = "TypeChecker-013"; -const std::string TypeChecker::DiagnosticsReporter::ID_of_CannotAssignToExpressionOfConstQualifiedType = "TypeChecker-014"; -const std::string TypeChecker::DiagnosticsReporter::ID_of_CannotAssignToExpressionOfArrayType = "TypeChecker-015"; -const std::string TypeChecker::DiagnosticsReporter::ID_of_ConversionBetweenIntegerAndPointerTypesInAssignment = "TypeChecker-016"; -const std::string TypeChecker::DiagnosticsReporter::ID_of_TooFewArgumentsToFunctionCall = "TypeChecker-017"; -const std::string TypeChecker::DiagnosticsReporter::ID_of_TooManyArgumentsToFunctionCall = "TypeChecker-018"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInInitialization = "TypeChecker-014"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_CannotAssignToExpressionOfConstQualifiedType = "TypeChecker-015"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_CannotAssignToExpressionOfArrayType = "TypeChecker-016"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_ConversionBetweenIntegerAndPointerTypesInAssignment = "TypeChecker-017"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_TooFewArgumentsToFunctionCall = "TypeChecker-018"; +const std::string TypeChecker::DiagnosticsReporter::ID_of_TooManyArgumentsToFunctionCall = "TypeChecker-019"; void TypeChecker::DiagnosticsReporter::diagnose(DiagnosticDescriptor&& desc, SyntaxToken tk) { @@ -194,6 +195,17 @@ void TypeChecker::DiagnosticsReporter::IncompatibleTypesInArgumentToParameterAss tk); } +void TypeChecker::DiagnosticsReporter::IncompatibleTypesInInitialization(SyntaxToken tk) +{ + diagnose(DiagnosticDescriptor( + ID_of_IncompatibleTypesInInitialization, + "[[incompatible types in initialization]]", + "incompatible types in initialization", + DiagnosticSeverity::Error, + DiagnosticCategory::TypeChecking), + tk); +} + void TypeChecker::DiagnosticsReporter::CannotAssignToExpressionOfConstQualifiedType(SyntaxToken tk) { diagnose(DiagnosticDescriptor( diff --git a/C/sema/TypeChecker.cpp b/C/sema/TypeChecker.cpp index ede01f400..d8dfa3f02 100644 --- a/C/sema/TypeChecker.cpp +++ b/C/sema/TypeChecker.cpp @@ -22,6 +22,7 @@ #include "syntax/SyntaxTree.h" +#include "parser/Unparser.h" #include "sema/Scope.h" #include "sema/PlatformOptions.h" #include "sema/Compilation.h" @@ -651,7 +652,7 @@ bool TypeChecker::isNULLPointerConstant(const SyntaxNode* node) void TypeChecker::createTypeInfo( const SyntaxNode* node, const Type* ty, - TypeInfo::Origin tyOrig) + TypeInfo::Origin orig) { auto undergoneConv = TypeInfo::UndergoneConversion::No; if (ty->kind() == TypeKind::Function) { @@ -660,17 +661,17 @@ void TypeChecker::createTypeInfo( undergoneConv = TypeInfo::UndergoneConversion::Yes; } ty_ = ty; - TypeInfo tyInfo(ty_, tyOrig, undergoneConv); + TypeInfo tyInfo(ty_, orig, undergoneConv); semaModel_->setTypeInfoOf(node, std::move(tyInfo)); } SyntaxVisitor::Action TypeChecker::typeChecked( const ExpressionSyntax* node, const Type* ty, - TypeInfo::Origin tyOrig) + TypeInfo::Origin orig) { PSY_ASSERT_2(ty, return Action::Quit); - createTypeInfo(node, ty, tyOrig); + createTypeInfo(node, ty, orig); return Action::Skip; } @@ -690,7 +691,26 @@ SyntaxVisitor::Action TypeChecker::typeCheckError(const SyntaxNode* node) SyntaxVisitor::Action TypeChecker::visitVariableAndOrFunctionDeclaration( const VariableAndOrFunctionDeclarationSyntax* node) { - return Action::Visit; + for (auto iter = node->declarators(); iter; iter = iter->next) { + auto decltor = iter->value; + auto decl = semaModel_->declarationBy(decltor); + PSY_ASSERT_2(decl, continue); + switch (decl->category()) { + case DeclarationCategory::Member: + case DeclarationCategory::Function: + case DeclarationCategory::Object: { + auto typeableDecl = MIXIN_TypeableDeclarationSymbol::from(decl); + PSY_ASSERT_2(typeableDecl, return Action::Quit); + ty_ = typeableDecl->type(); + break; + } + case DeclarationCategory::Type: + return typeCheckError(node); + } + VISIT(decltor); + } + + return Action::Skip; } SyntaxVisitor::Action TypeChecker::visitFunctionDefinition( @@ -699,11 +719,33 @@ SyntaxVisitor::Action TypeChecker::visitFunctionDefinition( return Action::Visit; } +/* Specifiers */ + SyntaxVisitor::Action TypeChecker::visitExtGNU_Attribute(const ExtGNU_AttributeSyntax*) { return Action::Quit; } +/* Initializers */ + +SyntaxVisitor::Action TypeChecker::visitExpressionInitializer( + const ExpressionInitializerSyntax* node) +{ + auto leftTy = unqualifiedAndResolved(ty_); + VISIT(node->expression()); + auto rightTy = unqualifiedAndResolved(ty_); + if (!isTypeAssignableFromOtherType(leftTy, rightTy, node->expression())) + diagReporter_.IncompatibleTypesInInitialization(node->expression()->firstToken()); + + return Action::Quit; +} + +SyntaxVisitor::Action TypeChecker::visitBraceEnclosedInitializer( + const BraceEnclosedInitializerSyntax* node) { + // TODO + return Action::Quit; +} + //-------------// // Expressions // //-------------// diff --git a/C/sema/TypeChecker.h b/C/sema/TypeChecker.h index 0501d20c9..daaf05c8b 100644 --- a/C/sema/TypeChecker.h +++ b/C/sema/TypeChecker.h @@ -92,6 +92,7 @@ class PSY_C_INTERNAL_API TypeChecker final : protected SyntaxVisitor void UnknownMemberOfTag(SyntaxToken tk); void IncompatibleTypesInAssignment(SyntaxToken tk); void IncompatibleTypesInArgumentToParameterAssignment(SyntaxToken tk); + void IncompatibleTypesInInitialization(SyntaxToken tk); void CannotAssignToExpressionOfConstQualifiedType(SyntaxToken tk); void CannotAssignToExpressionOfArrayType(SyntaxToken tk); void ConversionBetweenIntegerAndPointerTypesInAssignment(SyntaxToken tk); @@ -112,6 +113,7 @@ class PSY_C_INTERNAL_API TypeChecker final : protected SyntaxVisitor static const std::string ID_of_UnknownMemberOfTag; static const std::string ID_of_IncompatibleTypesInAssignment; static const std::string ID_of_IncompatibleTypesInArgumentToParameterAssignment; + static const std::string ID_of_IncompatibleTypesInInitialization; static const std::string ID_of_CannotAssignToExpressionOfConstQualifiedType; static const std::string ID_of_CannotAssignToExpressionOfArrayType; static const std::string ID_of_ConversionBetweenIntegerAndPointerTypesInAssignment; @@ -130,6 +132,10 @@ class PSY_C_INTERNAL_API TypeChecker final : protected SyntaxVisitor /* Specifiers */ virtual Action visitExtGNU_Attribute(const ExtGNU_AttributeSyntax*) override; + /* Initializers */ + virtual Action visitExpressionInitializer(const ExpressionInitializerSyntax*) override; + virtual Action visitBraceEnclosedInitializer(const BraceEnclosedInitializerSyntax*) override; + //-------------// // Expressions // //-------------// diff --git a/C/stdlib-support/CMakeLists.txt b/C/stdlib-support/CMakeLists.txt index 8b4947fb6..8d1fcfddb 100644 --- a/C/stdlib-support/CMakeLists.txt +++ b/C/stdlib-support/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) project(psychecstd) diff --git a/C/tests/TypeCheckerTester.cpp b/C/tests/TypeCheckerTester.cpp index eee61bf00..e16fe7ddc 100644 --- a/C/tests/TypeCheckerTester.cpp +++ b/C/tests/TypeCheckerTester.cpp @@ -4472,3 +4472,176 @@ void TypeCheckerTester::case0756(){} void TypeCheckerTester::case0757(){} void TypeCheckerTester::case0758(){} void TypeCheckerTester::case0759(){} + +void TypeCheckerTester::case0800() +{ + auto s = R"( +void _ () +{ + int x ; + int y = x; +} +)"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0801() +{ + auto s = R"( +void _ () +{ + int x ; + long y = x; +} +)"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0802() +{ + auto s = R"( +void _ () +{ + int x ; + int * y = x; +} +)"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInInitialization)); +} + +void TypeCheckerTester::case0803() +{ + auto s = R"( +void _ () +{ + long x ; + int * y = x; +} +)"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInInitialization)); +} + +void TypeCheckerTester::case0804() +{ + auto s = R"( +struct s { int m ; } v ; +void _ () +{ + int x = v ; +} +)"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInInitialization)); +} + +void TypeCheckerTester::case0805() +{ + auto s = R"( +struct s { int m ; } ; +void _ () +{ + int x ; + struct s y = x ; +} +)"; + + checkTypes( + s, + Expectation() + .diagnostic( + Expectation::ErrorOrWarn::Error, + TypeChecker::DiagnosticsReporter::ID_of_IncompatibleTypesInInitialization)); +} + +void TypeCheckerTester::case0806() +{ + auto s = R"( +struct s { int m ; } x ; +void _ () +{ + struct s y = x ; +} +)"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0807() +{ + auto s = R"( +typedef struct a { + struct b { + struct c { + const int m ; + } xx ; + } yy; +} t; +void _ () +{ + t x = { { { 42 } } }; +} +)"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0808() +{ + auto s = R"( +typedef struct a { + struct b { + struct c { + int m ; + } xx ; + } yy; +} t; +void _ () +{ + t x = { { { 42 } } }; +} +)"; + + checkTypes(s, Expectation()); +} + +void TypeCheckerTester::case0809(){} +void TypeCheckerTester::case0810(){} +void TypeCheckerTester::case0811(){} +void TypeCheckerTester::case0812(){} +void TypeCheckerTester::case0813(){} +void TypeCheckerTester::case0814(){} +void TypeCheckerTester::case0815(){} +void TypeCheckerTester::case0816(){} +void TypeCheckerTester::case0817(){} +void TypeCheckerTester::case0818(){} +void TypeCheckerTester::case0819(){} +void TypeCheckerTester::case0820(){} +void TypeCheckerTester::case0821(){} +void TypeCheckerTester::case0822(){} +void TypeCheckerTester::case0823(){} +void TypeCheckerTester::case0824(){} +void TypeCheckerTester::case0825(){} +void TypeCheckerTester::case0826(){} +void TypeCheckerTester::case0827(){} +void TypeCheckerTester::case0828(){} +void TypeCheckerTester::case0829(){} +void TypeCheckerTester::case0830(){} diff --git a/C/tests/TypeCheckerTester.h b/C/tests/TypeCheckerTester.h index 629fa2bc6..78793114f 100644 --- a/C/tests/TypeCheckerTester.h +++ b/C/tests/TypeCheckerTester.h @@ -54,7 +54,7 @@ class TypeCheckerTester final : public Tester + 0300-0399 -> function call + 0500-0599 -> unary (prefix) + 0700-0799 -> simple assignment - + + + 0800-0899 -> initialization */ void case0000(); @@ -423,6 +423,38 @@ class TypeCheckerTester final : public Tester void case0758(); void case0759(); + void case0800(); + void case0801(); + void case0802(); + void case0803(); + void case0804(); + void case0805(); + void case0806(); + void case0807(); + void case0808(); + void case0809(); + void case0810(); + void case0811(); + void case0812(); + void case0813(); + void case0814(); + void case0815(); + void case0816(); + void case0817(); + void case0818(); + void case0819(); + void case0820(); + void case0821(); + void case0822(); + void case0823(); + void case0824(); + void case0825(); + void case0826(); + void case0827(); + void case0828(); + void case0829(); + void case0830(); + std::vector tests_ { TEST_TYPE_CHECKER(case0000), @@ -791,6 +823,37 @@ class TypeCheckerTester final : public Tester TEST_TYPE_CHECKER(case0758), TEST_TYPE_CHECKER(case0759), + TEST_TYPE_CHECKER(case0800), + TEST_TYPE_CHECKER(case0801), + TEST_TYPE_CHECKER(case0802), + TEST_TYPE_CHECKER(case0803), + TEST_TYPE_CHECKER(case0804), + TEST_TYPE_CHECKER(case0805), + TEST_TYPE_CHECKER(case0806), + TEST_TYPE_CHECKER(case0807), + TEST_TYPE_CHECKER(case0808), + TEST_TYPE_CHECKER(case0809), + TEST_TYPE_CHECKER(case0810), + TEST_TYPE_CHECKER(case0811), + TEST_TYPE_CHECKER(case0812), + TEST_TYPE_CHECKER(case0813), + TEST_TYPE_CHECKER(case0814), + TEST_TYPE_CHECKER(case0815), + TEST_TYPE_CHECKER(case0816), + TEST_TYPE_CHECKER(case0817), + TEST_TYPE_CHECKER(case0818), + TEST_TYPE_CHECKER(case0819), + TEST_TYPE_CHECKER(case0820), + TEST_TYPE_CHECKER(case0821), + TEST_TYPE_CHECKER(case0822), + TEST_TYPE_CHECKER(case0823), + TEST_TYPE_CHECKER(case0824), + TEST_TYPE_CHECKER(case0825), + TEST_TYPE_CHECKER(case0826), + TEST_TYPE_CHECKER(case0827), + TEST_TYPE_CHECKER(case0828), + TEST_TYPE_CHECKER(case0829), + TEST_TYPE_CHECKER(case0830), }; }; diff --git a/CMakeLists.txt b/CMakeLists.txt index 2cf718255..1794d1b29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) project(psychec) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ce6da01a8..de5ddaae1 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) project(psychecommon)