diff --git a/C/binder/Binder.h b/C/binder/Binder.h index d31dcd34e..7994171da 100644 --- a/C/binder/Binder.h +++ b/C/binder/Binder.h @@ -203,6 +203,7 @@ class PSY_C_INTERNAL_API Binder final : protected SyntaxVisitor virtual Action visitParameterSuffix(const ParameterSuffixSyntax*) override; virtual Action visitIdentifierDeclarator(const IdentifierDeclaratorSyntax*) override; virtual Action visitAbstractDeclarator(const AbstractDeclaratorSyntax*) override; + virtual Action visitBitfieldDeclarator(const BitfieldDeclaratorSyntax*) override; //------------// // Statements // diff --git a/C/binder/Binder_Declarators.cpp b/C/binder/Binder_Declarators.cpp index a5b27049c..6af9e3209 100644 --- a/C/binder/Binder_Declarators.cpp +++ b/C/binder/Binder_Declarators.cpp @@ -23,6 +23,7 @@ #include "SyntaxTree.h" +#include "parser/Unparser.h" #include "binder/Scope.h" #include "compilation/SemanticModel.h" #include "symbols/Symbol_ALL.h" @@ -35,13 +36,14 @@ #include "../common/infra/Assertions.h" #include +#include using namespace psy; using namespace C; void Binder::nameDeclarationAtTop(const Identifier* name) { - SYM_AT_TOP_V(sym); + DECL_TOP_SYM_ret(sym); auto nameableDecl = MIXIN_NameableSymbol::from(sym); PSY_ASSERT_2(nameableDecl, return); nameableDecl->setName(name); @@ -49,11 +51,11 @@ void Binder::nameDeclarationAtTop(const Identifier* name) void Binder::typeDeclarationAtTopWithTypeAtTop() { - SYM_AT_TOP_V(sym); + DECL_TOP_SYM_ret(sym); auto typeableDecl = MIXIN_TypeableSymbol::from(sym); PSY_ASSERT_2(typeableDecl, return); - TY_AT_TOP_V(ty); + DECL_TOP_TY_ret(ty); typeableDecl->setType(ty); if (!pendingFunTys_.empty()) { @@ -64,16 +66,23 @@ void Binder::typeDeclarationAtTopWithTypeAtTop() void Binder::popTypesUntilNonDerivedDeclaratorType() { - PSY_ASSERT_2(!tys_.empty(), return); - auto ty = tys_.top(); + DECL_TOP_TY_ret(ty); while (true) { switch (ty->kind()) { + case TypeKind::Qualified: { + auto unqualTyK = ty->asQualifiedType()->unqualifiedType()->kind(); + if (!(unqualTyK == TypeKind::Array + || unqualTyK == TypeKind::Function + || unqualTyK == TypeKind::Pointer)) { + return; + } + [[fallthrough]]; + } case TypeKind::Array: case TypeKind::Function: case TypeKind::Pointer: popType(); - PSY_ASSERT_2(!tys_.empty(), return); - ty = tys_.top(); + TOP_TY_ret(ty); continue; default: return; @@ -88,7 +97,7 @@ SyntaxVisitor::Action Binder::visitDeclaration_AtMultipleDeclarators_COMMON( { for (auto decltorIt = node->declarators(); decltorIt; decltorIt = decltorIt->next) { visit(decltorIt->value); - SYM_AT_TOP(sym); + DECL_TOP_SYM_retQ(sym); switch (sym->kind()) { case SymbolKind::Declaration: { auto decl = sym->asDeclaration(); @@ -103,7 +112,7 @@ SyntaxVisitor::Action Binder::visitDeclaration_AtMultipleDeclarators_COMMON( typeDeclarationAtTopWithTypeAtTop(); popTypesUntilNonDerivedDeclaratorType(); popSymbol(); - SCOPE_AT_TOP(scope); + DECL_TOP_SCOPE_retQ(scope); scope->addDeclaration(decl); break; } @@ -169,7 +178,7 @@ SyntaxVisitor::Action Binder::visitFunctionDefinition_AtDeclarator(const Functio auto decl = popSymbolAsDeclaration(); PSY_ASSERT_2(decl, return Action::Quit); - SCOPE_AT_TOP(scope); + DECL_TOP_SCOPE_retQ(scope); scope->addDeclaration(decl); popType(); @@ -191,13 +200,13 @@ SyntaxVisitor::Action Binder::visitArrayOrFunctionDeclarator(const ArrayOrFuncti switch (node->suffix()->kind()) { case SyntaxKind::SubscriptSuffix: { - TY_AT_TOP(ty); + DECL_TOP_TY_retQ(ty); pushType(makeType(ty)); break; } case SyntaxKind::ParameterSuffix: { - TY_AT_TOP(ty); + DECL_TOP_TY_retQ(ty); switch (ty->kind()) { case TypeKind::Function: diagReporter_.FunctionReturningFunction( @@ -258,7 +267,7 @@ SyntaxVisitor::Action Binder::visitParameterSuffix(const ParameterSuffixSyntax* SyntaxVisitor::Action Binder::visitPointerDeclarator(const PointerDeclaratorSyntax* node) { - TY_AT_TOP(ty); + DECL_TOP_TY_retQ(ty); pushType(makeType(ty)); for (auto specIt = node->qualifiersAndAttributes(); specIt; specIt = specIt->next) @@ -276,13 +285,25 @@ SyntaxVisitor::Action Binder::visitParenthesizedDeclarator(const ParenthesizedDe return Action::Skip; } +SyntaxVisitor::Action Binder::visitBitfieldDeclarator(const BitfieldDeclaratorSyntax* node) +{ + if (node->innerDeclarator()) { + visit(node->innerDeclarator()); + } else { + bindObjectOrFunctionAndPushSymbol(node); + nameDeclarationAtTop(tree_->findIdentifier("", 0)); + } + + return Action::Skip; +} + void Binder::bindObjectOrFunctionAndPushSymbol(const SyntaxNode* node) { - SCOPE_AT_TOP_V(scope); + DECL_TOP_SCOPE_ret(scope); switch (scope->kind()) { case ScopeKind::File: case ScopeKind::Block: { - TY_AT_TOP_V(ty); + DECL_TOP_TY_ret(ty); switch (ty->kind()) { case TypeKind::Function: bindAndPushSymbol(node); @@ -295,7 +316,7 @@ void Binder::bindObjectOrFunctionAndPushSymbol(const SyntaxNode* node) case TypeKind::Qualified: case TypeKind::Typedef: case TypeKind::Tag: { - SYM_AT_TOP_V(sym); + DECL_TOP_SYM_ret(sym); switch (sym->kind()) { case SymbolKind::Declaration: { auto decl = sym->asDeclaration(); @@ -346,7 +367,7 @@ void Binder::bindObjectOrFunctionAndPushSymbol(const SyntaxNode* node) break; case ScopeKind::FunctionPrototype: { - TY_AT_TOP_V(ty); + DECL_TOP_TY_ret(ty); switch (ty->kind()) { case TypeKind::Array: { /* @@ -355,7 +376,7 @@ void Binder::bindObjectOrFunctionAndPushSymbol(const SyntaxNode* node) * shall be adjusted to “qualified pointer to type”... */ popType(); - TY_AT_TOP_V(otherTy); + DECL_TOP_TY_ret(otherTy); auto ptrTy = makeType(otherTy); pushType(ptrTy); ptrTy->markAsArisingFromArrayDecay(); diff --git a/C/binder/Binder_End.cpp b/C/binder/Binder_End.cpp index 675501574..bc9c4b5d8 100644 --- a/C/binder/Binder_End.cpp +++ b/C/binder/Binder_End.cpp @@ -83,7 +83,7 @@ SyntaxVisitor::Action Binder::visitDeclaration_AtEnd_COMMON(const DeclarationSyn { auto decl = popSymbolAsDeclaration(); PSY_ASSERT_2(decl, return Action::Quit); - SCOPE_AT_TOP(scope); + DECL_TOP_SCOPE_retQ(scope); scope->addDeclaration(decl->asDeclaration()); return Action::Skip; diff --git a/C/binder/Binder_Specifiers.cpp b/C/binder/Binder_Specifiers.cpp index fa951f89c..1d9adff48 100644 --- a/C/binder/Binder_Specifiers.cpp +++ b/C/binder/Binder_Specifiers.cpp @@ -81,7 +81,6 @@ SyntaxVisitor::Action Binder::visitEnumDeclaration_AtSpecifier(const EnumDeclara auto tagTy = makeType( TagTypeKind::Enum, identifier(node->typeSpec_->tagToken())); - pushType(tagTy); bindAndPushSymbol(node, tagTy); return visitTagDeclaration_AtInternalDeclarations_COMMON( @@ -216,201 +215,200 @@ SyntaxVisitor::Action Binder::visitBasicTypeSpecifier(const BasicTypeSpecifierSy return Action::Skip; } - TY_AT_TOP(ty); - PSY_ASSERT_2(ty->kind() == TypeKind::Basic, return Action::Skip); - BasicType* curBasicTy = ty->asBasicType(); - auto curBasicTyK = ty->asBasicType()->kind(); - switch (tySpecTk.kind()) { - case SyntaxKind::Keyword_char: - switch (curBasicTyK) { - case BasicTypeKind::Int_S: - if (tySpecHasImplicit_int) { - curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S); + DECL_TOP_TY_retQ(ty); + if (ty->kind() == TypeKind::Basic) { + BasicType* curBasicTy = ty->asBasicType(); + auto curBasicTyK = ty->asBasicType()->kind(); + switch (tySpecTk.kind()) { + case SyntaxKind::Keyword_char: + switch (curBasicTyK) { + case BasicTypeKind::Int_S: + if (tySpecHasImplicit_int) { + curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S); + return Action::Skip; + } + break; + case BasicTypeKind::Int_U: + if (tySpecHasImplicit_int) { + curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U); + return Action::Skip; + } + break; + default: + break; + } + break; + + case SyntaxKind::Keyword_short: + switch (curBasicTyK) { + case BasicTypeKind::Int: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Short); return Action::Skip; - } - break; - case BasicTypeKind::Int_U: - if (tySpecHasImplicit_int) { - curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U); + case BasicTypeKind::Int_S: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S); return Action::Skip; - } - break; - default: - break; - } - break; - - case SyntaxKind::Keyword_short: - switch (curBasicTyK) { - case BasicTypeKind::Int: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Short); - return Action::Skip; - case BasicTypeKind::Int_S: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S); - return Action::Skip; - case BasicTypeKind::Int_U: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U); - return Action::Skip; - default: - break; - } - break; - - case SyntaxKind::Keyword_int: { - auto allowIdentity = tySpecHasImplicit_int; - tySpecHasImplicit_int = false; - switch (curBasicTyK) { - case BasicTypeKind::Short: - case BasicTypeKind::Short_S: - case BasicTypeKind::Short_U: - case BasicTypeKind::Int_S: - case BasicTypeKind::Int_U: - case BasicTypeKind::Long_S: - case BasicTypeKind::Long_U: - case BasicTypeKind::Long: - case BasicTypeKind::LongLong: - case BasicTypeKind::LongLong_S: - case BasicTypeKind::LongLong_U: - if (allowIdentity) + case BasicTypeKind::Int_U: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U); return Action::Skip; - break; - default: - break; - } - break; - } + default: + break; + } + break; - case SyntaxKind::Keyword_long: - switch (curBasicTyK) { - case BasicTypeKind::Int: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Long); - return Action::Skip; - case BasicTypeKind::Int_S: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S); - return Action::Skip; - case BasicTypeKind::Int_U: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U); - return Action::Skip; - case BasicTypeKind::Long: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong); - return Action::Skip; - case BasicTypeKind::Long_S: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S); - return Action::Skip; - case BasicTypeKind::Long_U: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U); - return Action::Skip; - case BasicTypeKind::Double: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDouble); - return Action::Skip; - case BasicTypeKind::DoubleComplex: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex); - return Action::Skip; - default: - break; + case SyntaxKind::Keyword_int: { + auto allowIdentity = tySpecHasImplicit_int; + tySpecHasImplicit_int = false; + switch (curBasicTyK) { + case BasicTypeKind::Short: + case BasicTypeKind::Short_S: + case BasicTypeKind::Short_U: + case BasicTypeKind::Int_S: + case BasicTypeKind::Int_U: + case BasicTypeKind::Long_S: + case BasicTypeKind::Long_U: + case BasicTypeKind::Long: + case BasicTypeKind::LongLong: + case BasicTypeKind::LongLong_S: + case BasicTypeKind::LongLong_U: + if (allowIdentity) + return Action::Skip; + break; + default: + break; + } + break; } - break; - - case SyntaxKind::Keyword_float: - switch (curBasicTyK) { - case BasicTypeKind::DoubleComplex: - if (tySpecHasImplicit_double) { - curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex); + case SyntaxKind::Keyword_long: + switch (curBasicTyK) { + case BasicTypeKind::Int: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Long); return Action::Skip; - } - break; - default: - break; - } - break; - - case SyntaxKind::Keyword_double: { - bool allowIdentity = tySpecHasImplicit_double; - tySpecHasImplicit_double = false; - switch (curBasicTyK) { - case BasicTypeKind::Long: - if (tySpecHasImplicit_int) { + case BasicTypeKind::Int_S: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S); + return Action::Skip; + case BasicTypeKind::Int_U: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U); + return Action::Skip; + case BasicTypeKind::Long: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong); + return Action::Skip; + case BasicTypeKind::Long_S: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S); + return Action::Skip; + case BasicTypeKind::Long_U: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U); + return Action::Skip; + case BasicTypeKind::Double: curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDouble); return Action::Skip; - } - break; - case BasicTypeKind::DoubleComplex: - case BasicTypeKind::LongDoubleComplex: - if (allowIdentity) + case BasicTypeKind::DoubleComplex: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex); return Action::Skip; - break; - default: - break; - } - break; - } + default: + break; + } + break; - case SyntaxKind::Keyword__Bool: - break; + case SyntaxKind::Keyword_float: + switch (curBasicTyK) { + case BasicTypeKind::DoubleComplex: + if (tySpecHasImplicit_double) { + curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex); + return Action::Skip; + } + break; + default: + break; + } + break; - case SyntaxKind::Keyword__Complex: - switch (curBasicTyK) { - case BasicTypeKind::Long: - case BasicTypeKind::LongDouble: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex); - return Action::Skip; - case BasicTypeKind::Float: - curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex); - return Action::Skip; - case BasicTypeKind::Double: - curBasicTy->resetBasicTypeKind(BasicTypeKind::DoubleComplex); - return Action::Skip; - default: - break; + case SyntaxKind::Keyword_double: { + bool allowIdentity = tySpecHasImplicit_double; + tySpecHasImplicit_double = false; + switch (curBasicTyK) { + case BasicTypeKind::Long: + if (tySpecHasImplicit_int) { + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDouble); + return Action::Skip; + } + break; + case BasicTypeKind::DoubleComplex: + case BasicTypeKind::LongDoubleComplex: + if (allowIdentity) + return Action::Skip; + break; + default: + break; + } + break; } - break; + case SyntaxKind::Keyword__Bool: + break; - case SyntaxKind::Keyword_signed: - switch (curBasicTyK) { - case BasicTypeKind::Char: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S); - return Action::Skip; - case BasicTypeKind::Short: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S); - return Action::Skip; - case BasicTypeKind::Int: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_S); - return Action::Skip; - case BasicTypeKind::Long: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S); - return Action::Skip; - case BasicTypeKind::LongLong: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S); - return Action::Skip; - default: - break; - } - break; + case SyntaxKind::Keyword__Complex: + switch (curBasicTyK) { + case BasicTypeKind::Long: + case BasicTypeKind::LongDouble: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongDoubleComplex); + return Action::Skip; + case BasicTypeKind::Float: + curBasicTy->resetBasicTypeKind(BasicTypeKind::FloatComplex); + return Action::Skip; + case BasicTypeKind::Double: + curBasicTy->resetBasicTypeKind(BasicTypeKind::DoubleComplex); + return Action::Skip; + default: + break; + } + break; - case SyntaxKind::Keyword_unsigned: - switch (curBasicTyK) { - case BasicTypeKind::Char: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U); - return Action::Skip; - case BasicTypeKind::Short: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U); - return Action::Skip; - case BasicTypeKind::Int: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_U); - return Action::Skip; - case BasicTypeKind::Long: - curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U); - return Action::Skip; - case BasicTypeKind::LongLong: - curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U); - return Action::Skip; - default: - break; - } - break; + case SyntaxKind::Keyword_signed: + switch (curBasicTyK) { + case BasicTypeKind::Char: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_S); + return Action::Skip; + case BasicTypeKind::Short: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_S); + return Action::Skip; + case BasicTypeKind::Int: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_S); + return Action::Skip; + case BasicTypeKind::Long: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_S); + return Action::Skip; + case BasicTypeKind::LongLong: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_S); + return Action::Skip; + default: + break; + } + break; - default: - PSY_ASSERT_FAIL_1(return Action::Quit); + case SyntaxKind::Keyword_unsigned: + switch (curBasicTyK) { + case BasicTypeKind::Char: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Char_U); + return Action::Skip; + case BasicTypeKind::Short: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Short_U); + return Action::Skip; + case BasicTypeKind::Int: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Int_U); + return Action::Skip; + case BasicTypeKind::Long: + curBasicTy->resetBasicTypeKind(BasicTypeKind::Long_U); + return Action::Skip; + case BasicTypeKind::LongLong: + curBasicTy->resetBasicTypeKind(BasicTypeKind::LongLong_U); + return Action::Skip; + default: + break; + } + break; + + default: + PSY_ASSERT_FAIL_1(return Action::Quit); + } } diagReporter_.InvalidType(tySpecTk); @@ -469,26 +467,30 @@ SyntaxVisitor::Action Binder::visitTagDeclarationAsSpecifier( visit(node->tagDeclaration()); const TagTypeSpecifierSyntax* tySpec = node->tagDeclaration()->typeSpecifier(); + TagType* tagTy = nullptr; switch (tySpec->kind()) { - case SyntaxKind::StructTypeSpecifier: { - auto tagTy = makeType( + case SyntaxKind::StructTypeSpecifier: + tagTy = makeType( TagTypeKind::Struct, identifier(tySpec->tagToken())); - pushType(tagTy); break; - } - case SyntaxKind::UnionTypeSpecifier:{ - auto tagTy = makeType( + case SyntaxKind::UnionTypeSpecifier: + tagTy = makeType( TagTypeKind::Union, identifier(tySpec->tagToken())); - pushType(tagTy); break; - } + + case SyntaxKind::EnumTypeSpecifier: + tagTy = makeType( + TagTypeKind::Enum, + identifier(tySpec->tagToken())); + break; default: PSY_ASSERT_2(false, return Action::Quit); } + pushType(tagTy); return Action::Skip; } @@ -504,7 +506,7 @@ SyntaxVisitor::Action Binder::visitTypedefName(const TypedefNameSyntax* node) SyntaxVisitor::Action Binder::visitTypeQualifier(const TypeQualifierSyntax* node) { QualifiedType* qualTy = nullptr; - TY_AT_TOP(ty); + DECL_TOP_TY_retQ(ty); switch (ty->kind()) { case TypeKind::Qualified: qualTy = ty->asQualifiedType(); diff --git a/C/binder/Binder__MACROS__.inc b/C/binder/Binder__MACROS__.inc index 2e45e6105..dc927bf0d 100644 --- a/C/binder/Binder__MACROS__.inc +++ b/C/binder/Binder__MACROS__.inc @@ -44,31 +44,24 @@ # define DBG_TY_STACK(sym) do {} while (0) #endif -#define SYM_AT_TOP(S) \ - PSY_ASSERT_2(!syms_.empty(), return Action::Quit); \ - auto S = syms_.top(); -#define SYM_AT_TOP_V(S) \ - PSY_ASSERT_2(!syms_.empty(), return); \ - auto S = syms_.top(); - -#define TY_AT_TOP(T) \ - PSY_ASSERT_2(!tys_.empty(), return Action::Quit); \ - auto T = tys_.top(); -#define TY_AT_TOP_V(T) \ - PSY_ASSERT_2(!tys_.empty(), return); \ - auto T = tys_.top(); - -#define SCOPE_AT_TOP(S) \ - PSY_ASSERT_2(!scopes_.empty(), return Action::Quit); \ - auto S = scopes_.top(); -#define SCOPE_AT_TOP_V(S) \ - PSY_ASSERT_2(!scopes_.empty(), return); \ - auto S = scopes_.top(); - -#define RETURN_IF_QUIT(CALL) \ - do { \ - auto action = CALL; \ - if (action == Action::Quit) \ - return action; \ - } while (0) - +#define VALID_TOP(STACK, RET) \ + PSY_ASSERT_2(!STACK.empty(), RET); \ + PSY_ASSERT_2(STACK.top(), RET); +#define TOP(V, STACK, RET) \ + VALID_TOP(STACK, RET); \ + V = STACK.top(); +#define DECL_TOP(V, STACK, RET) \ + VALID_TOP(STACK, RET); \ + auto V = STACK.top(); +#define TOP_SYM_retQ(V) TOP(V, syms_, return Action::Quit) +#define TOP_SYM_ret(V) TOP(V, syms_, return) +#define TOP_TY_retQ(V) TOP(V, tys_, return Action::Quit) +#define TOP_TY_ret(V) TOP(V, tys_, return) +#define TOP_SCOPE_retQ(V) TOP(V, scopes_, return Action::Quit) +#define TOP_SCOPE_ret(V) TOP(V, scopes_, return) +#define DECL_TOP_SYM_retQ(V) DECL_TOP(V, syms_, return Action::Quit) +#define DECL_TOP_SYM_ret(V) DECL_TOP(V, syms_, return) +#define DECL_TOP_TY_retQ(V) DECL_TOP(V, tys_, return Action::Quit) +#define DECL_TOP_TY_ret(V) DECL_TOP(V, tys_, return) +#define DECL_TOP_SCOPE_retQ(V) DECL_TOP(V, scopes_, return Action::Quit) +#define DECL_TOP_SCOPE_ret(V) DECL_TOP(V, scopes_, return) diff --git a/C/compilation/SemanticModel.cpp b/C/compilation/SemanticModel.cpp index 40b3830b0..4d8a418eb 100644 --- a/C/compilation/SemanticModel.cpp +++ b/C/compilation/SemanticModel.cpp @@ -41,7 +41,7 @@ using namespace C; struct SemanticModel::SemanticModelImpl { SemanticModelImpl(const SyntaxTree* tree, Compilation* compilation) - : bindingIsOK_(true) + : bindingIsOK_(false) // TODO , tree_(tree) , compilation_(compilation) {} diff --git a/C/reparser/Disambiguator.cpp b/C/reparser/Disambiguator.cpp index c2bae1b47..be83b34cb 100644 --- a/C/reparser/Disambiguator.cpp +++ b/C/reparser/Disambiguator.cpp @@ -398,7 +398,8 @@ SyntaxVisitor::Action Disambiguator::visitSwitchStatement(const SwitchStatementS SyntaxVisitor::Action Disambiguator::visitWhileStatement(const WhileStatementSyntax* node) { - visitMaybeAmbiguousExpression(node->cond_); + if (node->cond_) + visitMaybeAmbiguousExpression(node->cond_); visitMaybeAmbiguousStatement(node->stmt_); return Action::Skip; @@ -415,8 +416,10 @@ SyntaxVisitor::Action Disambiguator::visitDoStatement(const DoStatementSyntax* n SyntaxVisitor::Action Disambiguator::visitForStatement(const ForStatementSyntax* node) { visit(node->initStmt_); - visitMaybeAmbiguousExpression(node->cond_); - visitMaybeAmbiguousExpression(node->expr_); + if (node->cond_) + visitMaybeAmbiguousExpression(node->cond_); + if (node->expr_) + visitMaybeAmbiguousExpression(node->expr_); visitMaybeAmbiguousStatement(node->stmt_); return Action::Skip; @@ -424,7 +427,8 @@ SyntaxVisitor::Action Disambiguator::visitForStatement(const ForStatementSyntax* SyntaxVisitor::Action Disambiguator::visitReturnStatement(const ReturnStatementSyntax* node) { - visitMaybeAmbiguousExpression(node->expr_); + if (node->expr_) + visitMaybeAmbiguousExpression(node->expr_); return Action::Skip; } diff --git a/C/tests/BinderTester.h b/C/tests/BinderTester.h index 92991318f..341d50989 100644 --- a/C/tests/BinderTester.h +++ b/C/tests/BinderTester.h @@ -84,6 +84,7 @@ class BinderTester final : public Tester + 2250-2299 -> qualified pointers + 2300-2349 -> arrays + 2350-2399 -> arrays of objects of qualified type + + 2400-2449 -> bit fields Types + 3000-0049 -> structures and unions @@ -1613,6 +1614,56 @@ class BinderTester final : public Tester void case2397(); void case2398(); void case2399(); + void case2400(); + void case2401(); + void case2402(); + void case2403(); + void case2404(); + void case2405(); + void case2406(); + void case2407(); + void case2408(); + void case2409(); + void case2410(); + void case2411(); + void case2412(); + void case2413(); + void case2414(); + void case2415(); + void case2416(); + void case2417(); + void case2418(); + void case2419(); + void case2420(); + void case2421(); + void case2422(); + void case2423(); + void case2424(); + void case2425(); + void case2426(); + void case2427(); + void case2428(); + void case2429(); + void case2430(); + void case2431(); + void case2432(); + void case2433(); + void case2434(); + void case2435(); + void case2436(); + void case2437(); + void case2438(); + void case2439(); + void case2440(); + void case2441(); + void case2442(); + void case2443(); + void case2444(); + void case2445(); + void case2446(); + void case2447(); + void case2448(); + void case2449(); // 3000-3999 @@ -3738,6 +3789,56 @@ class BinderTester final : public Tester TEST_BINDER(case2397), TEST_BINDER(case2398), TEST_BINDER(case2399), + TEST_BINDER(case2400), + TEST_BINDER(case2401), + TEST_BINDER(case2402), + TEST_BINDER(case2403), + TEST_BINDER(case2404), + TEST_BINDER(case2405), + TEST_BINDER(case2406), + TEST_BINDER(case2407), + TEST_BINDER(case2408), + TEST_BINDER(case2409), + TEST_BINDER(case2410), + TEST_BINDER(case2411), + TEST_BINDER(case2412), + TEST_BINDER(case2413), + TEST_BINDER(case2414), + TEST_BINDER(case2415), + TEST_BINDER(case2416), + TEST_BINDER(case2417), + TEST_BINDER(case2418), + TEST_BINDER(case2419), + TEST_BINDER(case2420), + TEST_BINDER(case2421), + TEST_BINDER(case2422), + TEST_BINDER(case2423), + TEST_BINDER(case2424), + TEST_BINDER(case2425), + TEST_BINDER(case2426), + TEST_BINDER(case2427), + TEST_BINDER(case2428), + TEST_BINDER(case2429), + TEST_BINDER(case2430), + TEST_BINDER(case2431), + TEST_BINDER(case2432), + TEST_BINDER(case2433), + TEST_BINDER(case2434), + TEST_BINDER(case2435), + TEST_BINDER(case2436), + TEST_BINDER(case2437), + TEST_BINDER(case2438), + TEST_BINDER(case2439), + TEST_BINDER(case2440), + TEST_BINDER(case2441), + TEST_BINDER(case2442), + TEST_BINDER(case2443), + TEST_BINDER(case2444), + TEST_BINDER(case2445), + TEST_BINDER(case2446), + TEST_BINDER(case2447), + TEST_BINDER(case2448), + TEST_BINDER(case2449), TEST_BINDER(case3001), TEST_BINDER(case3002), diff --git a/C/tests/BinderTester_1000_1999.cpp b/C/tests/BinderTester_1000_1999.cpp index 095319597..f513b3871 100644 --- a/C/tests/BinderTester_1000_1999.cpp +++ b/C/tests/BinderTester_1000_1999.cpp @@ -160,8 +160,22 @@ void BinderTester::case1013() .ty_.Tag("x", TagTypeKind::Struct))); } -void BinderTester::case1014(){} -void BinderTester::case1015(){} +void BinderTester::case1014() +{ + bind("enum x { y } z ;", + Expectation() + .declaration(Decl().Object("z", ObjectDeclarationKind::Variable) + .ty_.Tag("x", TagTypeKind::Enum))); +} + +void BinderTester::case1015() +{ + bind("_Bool x ;", + Expectation() + .declaration(Decl().Object("x", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Bool))); +} + void BinderTester::case1016(){} void BinderTester::case1017(){} void BinderTester::case1018(){} diff --git a/C/tests/BinderTester_2000_2999.cpp b/C/tests/BinderTester_2000_2999.cpp index 4e6888823..16aac5014 100644 --- a/C/tests/BinderTester_2000_2999.cpp +++ b/C/tests/BinderTester_2000_2999.cpp @@ -862,3 +862,96 @@ void BinderTester::case2396(){ } void BinderTester::case2397(){ } void BinderTester::case2398(){ } void BinderTester::case2399(){ } + +void BinderTester::case2400() +{ + bind(R"( +struct x +{ + short y : 1 ; +}; + )", + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Field) + .ty_.Basic(BasicTypeKind::Short))); +} + +void BinderTester::case2401() +{ + bind(R"( +struct x +{ + short y : 1 , z : 1 ; +}; + )", + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Field) + .ty_.Basic(BasicTypeKind::Short)) + .declaration(Decl() + .Object("z", ObjectDeclarationKind::Field) + .ty_.Basic(BasicTypeKind::Short))); +} + +void BinderTester::case2402() +{ + bind(R"( +struct x +{ + short y : 1 , : 7 ; +}; + )", + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Field) + .ty_.Basic(BasicTypeKind::Short))); +} + +void BinderTester::case2403(){} +void BinderTester::case2404(){} +void BinderTester::case2405(){} +void BinderTester::case2406(){} +void BinderTester::case2407(){} +void BinderTester::case2408(){} +void BinderTester::case2409(){} +void BinderTester::case2410(){} +void BinderTester::case2411(){} +void BinderTester::case2412(){} +void BinderTester::case2413(){} +void BinderTester::case2414(){} +void BinderTester::case2415(){} +void BinderTester::case2416(){} +void BinderTester::case2417(){} +void BinderTester::case2418(){} +void BinderTester::case2419(){} +void BinderTester::case2420(){} +void BinderTester::case2421(){} +void BinderTester::case2422(){} +void BinderTester::case2423(){} +void BinderTester::case2424(){} +void BinderTester::case2425(){} +void BinderTester::case2426(){} +void BinderTester::case2427(){} +void BinderTester::case2428(){} +void BinderTester::case2429(){} +void BinderTester::case2430(){} +void BinderTester::case2431(){} +void BinderTester::case2432(){} +void BinderTester::case2433(){} +void BinderTester::case2434(){} +void BinderTester::case2435(){} +void BinderTester::case2436(){} +void BinderTester::case2437(){} +void BinderTester::case2438(){} +void BinderTester::case2439(){} +void BinderTester::case2440(){} +void BinderTester::case2441(){} +void BinderTester::case2442(){} +void BinderTester::case2443(){} +void BinderTester::case2444(){} +void BinderTester::case2445(){} +void BinderTester::case2446(){} +void BinderTester::case2447(){} +void BinderTester::case2448(){} +void BinderTester::case2449(){} diff --git a/C/tests/BinderTester_3000_3999.cpp b/C/tests/BinderTester_3000_3999.cpp index 295d74f3e..6e2f38c8f 100644 --- a/C/tests/BinderTester_3000_3999.cpp +++ b/C/tests/BinderTester_3000_3999.cpp @@ -607,17 +607,68 @@ void BinderTester::case3301() void BinderTester::case3302() { + bind(R"( +struct x +{ + short y : 1 , : 7 ; +}; +int z ; + )", + Expectation() + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Field) + .ty_.Basic(BasicTypeKind::Short)) + .declaration(Decl() + .Object("z", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Int))); } void BinderTester::case3303() { + bind(R"( +struct x { int _ ; } ; +float y ; + )", + Expectation() + .declaration(Decl() + .Type("x", TagTypeDeclarationKind::Struct) + .inNameSpace(NameSpace::Tags)) + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Float))); } void BinderTester::case3304() { + bind(R"( +enum x { _ } ; +float y ; + )", + Expectation() + .declaration(Decl() + .Type("x", TagTypeDeclarationKind::Enum) + .inNameSpace(NameSpace::Tags)) + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Float))); +} + +void BinderTester::case3305() +{ + bind(R"( +const char * const x ; +float y ; + )", + Expectation() + .declaration(Decl() + .Object("x", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Char, CVR::Const) + .ty_.Derived(TypeKind::Pointer, CVR::Const)) + .declaration(Decl() + .Object("y", ObjectDeclarationKind::Variable) + .ty_.Basic(BasicTypeKind::Float))); } -void BinderTester::case3305(){} void BinderTester::case3306(){} void BinderTester::case3307(){} void BinderTester::case3308(){} diff --git a/C/tests/BinderTester_4000_4999.cpp b/C/tests/BinderTester_4000_4999.cpp index 94f4ffef2..7ecfd993f 100644 --- a/C/tests/BinderTester_4000_4999.cpp +++ b/C/tests/BinderTester_4000_4999.cpp @@ -500,10 +500,11 @@ void BinderTester::case4049() void BinderTester::case4050() { - bind("_Bool x ;", + bind("struct x int y ;", Expectation() - .declaration(Decl().Object("x", ObjectDeclarationKind::Variable) - .ty_.Basic(BasicTypeKind::Bool))); + .diagnostic( + Expectation::ErrorOrWarn::Error, + Binder::DiagnosticsReporter::ID_InvalidType)); } void BinderTester::case4051() @@ -518,7 +519,10 @@ void BinderTester::case4051() .ty_.Basic(BasicTypeKind::Char))); } -void BinderTester::case4052(){} +void BinderTester::case4052() +{ +} + void BinderTester::case4053(){} void BinderTester::case4054(){} void BinderTester::case4055(){} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e51929b9..4cc51390e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,14 +27,14 @@ set(PSYCHEC_CXX_FLAGS "${PSYCHEC_CXX_FLAGS} -Wall \ # Project sources. set(PSYCHEC_SOURCES - # Abstract data types + # Data structures ${PROJECT_SOURCE_DIR}/data-structures/Substitution.h ${PROJECT_SOURCE_DIR}/data-structures/Substitution.cpp ${PROJECT_SOURCE_DIR}/data-structures/VersionedMap.h # Tools - ${PROJECT_SOURCE_DIR}/tools/GnuCompilerFacade.h - ${PROJECT_SOURCE_DIR}/tools/GnuCompilerFacade.cpp + ${PROJECT_SOURCE_DIR}/tools/GNUCompilerFacade.h + ${PROJECT_SOURCE_DIR}/tools/GNUCompilerFacade.cpp # Utilities ${PROJECT_SOURCE_DIR}/utility/FileInfo.h diff --git a/cnippet/CompilerFrontend_C.cpp b/cnippet/CompilerFrontend_C.cpp index 20c602cd1..35ebac374 100644 --- a/cnippet/CompilerFrontend_C.cpp +++ b/cnippet/CompilerFrontend_C.cpp @@ -21,7 +21,7 @@ #include "CompilerFrontend_C.h" #include "FileInfo.h" -#include "GnuCompilerFacade.h" +#include "GNUCompilerFacade.h" #include "IO.h" #include "Plugin.h" @@ -31,6 +31,7 @@ #include "../common/infra/Assertions.h" +#include #include using namespace cnip; @@ -111,7 +112,7 @@ int CCompilerFrontend::extendWithStdLibHeaders(const std::string& srcText, int CCompilerFrontend::preprocess(const std::string& srcText, const psy::FileInfo& fi) { - GnuCompilerFacade cc(config_->compiler_, + GNUCompilerFacade cc(config_->compiler_, config_->std_, config_->definedMacros_, config_->undefedMacros_, @@ -120,7 +121,7 @@ int CCompilerFrontend::preprocess(const std::string& srcText, std::string srcText_P; int exit; if (config_->ppIncludes_) { - std::tie(exit, srcText_P) = cc.preprocess(srcText); + std::tie(exit, srcText_P) = cc.preprocessFile(fi.fullFileName()); if (exit != 0) { std::cerr << kCnip << "preprocessor invocation failed" << std::endl; return ERROR_PreprocessorInvocationFailure; diff --git a/command/cxxopts/include/cxxopts.hpp b/command/cxxopts/include/cxxopts.hpp index 811bd2601..6d230f062 100644 --- a/command/cxxopts/include/cxxopts.hpp +++ b/command/cxxopts/include/cxxopts.hpp @@ -1986,7 +1986,7 @@ Options::help_one_group(const std::string& g) const longest = (std::min)(longest, static_cast(OPTION_LONGEST)); //widest allowed description - auto allowed = size_t{180} - longest - OPTION_DESC_GAP; + auto allowed = size_t{76} - longest - OPTION_DESC_GAP; auto fiter = format.begin(); for (const auto& o : group->second.options) diff --git a/tools/GnuCompilerFacade.cpp b/tools/GNUCompilerFacade.cpp similarity index 75% rename from tools/GnuCompilerFacade.cpp rename to tools/GNUCompilerFacade.cpp index fbda31d3c..6778dd4ef 100644 --- a/tools/GnuCompilerFacade.cpp +++ b/tools/GNUCompilerFacade.cpp @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#include "GnuCompilerFacade.h" +#include "GNUCompilerFacade.h" #include "Process.h" @@ -32,7 +32,7 @@ const char * const kInclude = "#include"; using namespace psy; -GnuCompilerFacade::GnuCompilerFacade(const std::string& compilerName, +GNUCompilerFacade::GNUCompilerFacade(const std::string& compilerName, const std::string& std, const std::vector& D, const std::vector& U, @@ -44,20 +44,25 @@ GnuCompilerFacade::GnuCompilerFacade(const std::string& compilerName, , I_(I) {} -std::pair GnuCompilerFacade::preprocess(const std::string& srcText) +std::pair GNUCompilerFacade::preprocessFile(const std::string& filePath) { - std::string in = "cat << 'EOF' | "; - in += compilerName_; - in += assemblePPOptions(); - in += " "; - in += "-std=" + std_ + " "; - in += "-E -x c -CC -"; - in += "\n" + srcText + "\nEOF"; + std::string cmd = compilerName_ + assemblePPOptions(); + cmd += " -std=" + std_ + " -E -x c -CC "; + cmd += filePath; + return Process().execute(cmd); +} +std::pair GNUCompilerFacade::preprocessText(const std::string& srcText) +{ + std::string in = "cat << 'EOF' | "; + in += compilerName_ + assemblePPOptions(); + in += " -std=" + std_ + " -E -x c -CC -\n"; + in += srcText; + in += "\nEOF"; return Process().execute(in); } -std::pair GnuCompilerFacade::preprocess_IgnoreIncludes(const std::string& srcText) +std::pair GNUCompilerFacade::preprocess_IgnoreIncludes(const std::string& srcText) { std::string srcText_P; srcText_P.reserve(srcText.length()); @@ -66,17 +71,14 @@ std::pair GnuCompilerFacade::preprocess_IgnoreIncludes(const s std::string line; while (std::getline(iss, line)) { line.erase(0, line.find_first_not_of(' ')); - if (line.find(kInclude) == 0) continue; - srcText_P += (line + "\n"); } - - return preprocess(srcText_P); + return preprocessText(srcText_P); } -std::string GnuCompilerFacade::assemblePPOptions() const +std::string GNUCompilerFacade::assemblePPOptions() const { std::string s; for (const auto& d : D_) diff --git a/tools/GnuCompilerFacade.h b/tools/GNUCompilerFacade.h similarity index 87% rename from tools/GnuCompilerFacade.h rename to tools/GNUCompilerFacade.h index 90c422a88..880fd60e5 100644 --- a/tools/GnuCompilerFacade.h +++ b/tools/GNUCompilerFacade.h @@ -21,22 +21,25 @@ #ifndef PSYCHE_GNU_COMPILER_FACADE_H__ #define PSYCHE_GNU_COMPILER_FACADE_H__ +#include "FileInfo.h" + #include #include #include namespace psy { -class GnuCompilerFacade +class GNUCompilerFacade { public: - GnuCompilerFacade(const std::string& compilerName, + GNUCompilerFacade(const std::string& compilerName, const std::string& std, const std::vector& D, const std::vector& U, const std::vector& I); - std::pair preprocess(const std::string& srcText); + std::pair preprocessFile(const std::string& filePath); + std::pair preprocessText(const std::string& scrText); std::pair preprocess_IgnoreIncludes(const std::string& srcText); private: