Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile.emsdk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM emscripten/emsdk:4.0.1 as em
FROM emscripten/emsdk:4.0.6 as em

RUN apt-get update && apt-get install -y \
ninja-build \
Expand Down
1,245 changes: 648 additions & 597 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1921,6 +1921,7 @@ class NewExpressionAST final : public ExpressionAST {
DeclaratorAST* declarator = nullptr;
SourceLocation rparenLoc;
NewInitializerAST* newInitalizer = nullptr;
const Type* objectType = nullptr;

void accept(ASTVisitor* visitor) override { visitor->visit(this); }

Expand Down
69 changes: 48 additions & 21 deletions src/parser/cxx/binder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,6 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs,
bool isDeclaration) {
const auto _ = ScopeGuard{this};

auto className = get_name(control(), ast->unqualifiedId);
const auto location = ast->unqualifiedId->firstSourceLocation();

if (ast->nestedNameSpecifier) {
auto parent = ast->nestedNameSpecifier->symbol;

Expand All @@ -151,32 +148,62 @@ void Binder::bind(ElaboratedTypeSpecifierAST* ast, DeclSpecs& declSpecs,
}
}

ClassSymbol* classSymbol = nullptr;
auto templateId = ast_cast<SimpleTemplateIdAST>(ast->unqualifiedId);

if (scope()->isClassOrNamespaceScope()) {
for (auto candidate : scope()->find(className) | views::classes) {
classSymbol = candidate;
break;
const Identifier* name = nullptr;
if (templateId)
name = templateId->identifier;
else if (auto nameId = ast_cast<NameIdAST>(ast->unqualifiedId))
name = nameId->identifier;

const auto location = ast->unqualifiedId->firstSourceLocation();

if (ast->classKey == TokenKind::T_CLASS ||
ast->classKey == TokenKind::T_STRUCT ||
ast->classKey == TokenKind::T_UNION) {
auto is_class = [](Symbol* symbol) {
if (symbol->isClass()) return true;
return false;
};

auto candidate =
Lookup{scope()}.lookup(ast->nestedNameSpecifier, name, is_class);

auto classSymbol = symbol_cast<ClassSymbol>(candidate);

if (classSymbol) {
// validate the resolved class symbol

if (isDeclaration) {
// if the class is already declared, we need to check if the
if (classSymbol->enclosingScope() != declaringScope()) {
// the class is declared in a different scope
classSymbol = nullptr;
}
}
}
}

if (!classSymbol) {
const auto isUnion = ast->classKey == TokenKind::T_UNION;
classSymbol = control()->newClassSymbol(scope(), location);
if (!classSymbol) {
const auto isUnion = ast->classKey == TokenKind::T_UNION;
classSymbol = control()->newClassSymbol(scope(), location);

classSymbol->setIsUnion(isUnion);
classSymbol->setName(className);
classSymbol->setTemplateParameters(currentTemplateParameters());
classSymbol->setTemplateDeclaration(declSpecs.templateHead);
declaringScope()->addSymbol(classSymbol);
classSymbol->setIsUnion(isUnion);
classSymbol->setName(name);
classSymbol->setTemplateParameters(currentTemplateParameters());
classSymbol->setTemplateDeclaration(declSpecs.templateHead);
declaringScope()->addSymbol(classSymbol);

classSymbol->setDeclaration(ast);
}
classSymbol->setDeclaration(ast);
}

ast->symbol = classSymbol;
ast->symbol = classSymbol;
}

declSpecs.setTypeSpecifier(ast);
declSpecs.setType(ast->symbol->type());

if (ast->symbol) {
declSpecs.setType(ast->symbol->type());
}
}

void Binder::bind(ClassSpecifierAST* ast, DeclSpecs& declSpecs) {
Expand Down
9 changes: 7 additions & 2 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2558,13 +2558,15 @@ auto Parser::parse_new_expression(ExpressionAST*& yyast, const ExprContext& ctx)
lookahead.commit();

NewInitializerAST* newInitializer = nullptr;
parse_optional_new_initializer(newInitializer, ctx);
parse_optional_new_initializer(newInitializer, decl, ctx);

ast->lparenLoc = lparenLoc;
ast->typeSpecifierList = typeSpecifierList;
ast->rparenLoc = rparenLoc;
ast->newInitalizer = newInitializer;

ast->objectType = getDeclaratorType(unit, declarator, decl.specs.type());

check(ast);

return true;
Expand All @@ -2580,7 +2582,9 @@ auto Parser::parse_new_expression(ExpressionAST*& yyast, const ExprContext& ctx)

(void)parse_declarator(ast->declarator, decl, DeclaratorKind::kNewDeclarator);

parse_optional_new_initializer(ast->newInitalizer, ctx);
parse_optional_new_initializer(ast->newInitalizer, decl, ctx);

ast->objectType = getDeclaratorType(unit, ast->declarator, decl.specs.type());

check(ast);

Expand Down Expand Up @@ -2611,6 +2615,7 @@ void Parser::parse_optional_new_placement(NewPlacementAST*& yyast,
}

void Parser::parse_optional_new_initializer(NewInitializerAST*& yyast,
Decl& decl,
const ExprContext& ctx) {
if (BracedInitListAST* bracedInitList = nullptr;
parse_braced_init_list(bracedInitList, ctx)) {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class Parser final {
const ExprContext& ctx) -> bool;
void parse_optional_new_placement(NewPlacementAST*& yyast,
const ExprContext& ctx);
void parse_optional_new_initializer(NewInitializerAST*& yyast,
void parse_optional_new_initializer(NewInitializerAST*& yyast, Decl& decl,
const ExprContext& ctx);
[[nodiscard]] auto parse_delete_expression(ExpressionAST*& yyast,
const ExprContext& ctx) -> bool;
Expand Down
60 changes: 55 additions & 5 deletions src/parser/cxx/type_checker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,26 @@ void TypeChecker::Visitor::operator()(VaArgExpressionAST* ast) {
}
}

void TypeChecker::Visitor::operator()(SubscriptExpressionAST* ast) {}
void TypeChecker::Visitor::operator()(SubscriptExpressionAST* ast) {
if (auto pointerType = type_cast<PointerType>(ast->baseExpression->type)) {
ast->type = pointerType->elementType();
ast->valueCategory = ast->baseExpression->valueCategory;
return;
}

if (auto arrayType = type_cast<BoundedArrayType>(ast->baseExpression->type)) {
ast->type = arrayType->elementType();
ast->valueCategory = ast->baseExpression->valueCategory;
return;
}

if (auto arrayType =
type_cast<UnboundedArrayType>(ast->baseExpression->type)) {
ast->type = arrayType->elementType();
ast->valueCategory = ast->baseExpression->valueCategory;
return;
}
}

void TypeChecker::Visitor::operator()(CallExpressionAST* ast) {
if (!ast->baseExpression) return;
Expand Down Expand Up @@ -666,11 +685,38 @@ void TypeChecker::Visitor::operator()(NoexceptExpressionAST* ast) {
ast->type = control()->getBoolType();
}

void TypeChecker::Visitor::operator()(NewExpressionAST* ast) {}
void TypeChecker::Visitor::operator()(NewExpressionAST* ast) {
// TODO: decay
auto objectType = control()->remove_reference(ast->objectType);

if (auto arrayType = type_cast<BoundedArrayType>(ast->objectType)) {
ast->type = control()->getPointerType(arrayType->elementType());
} else if (auto unboundedType =
type_cast<UnboundedArrayType>(ast->objectType)) {
ast->type = control()->getPointerType(unboundedType->elementType());
} else {
ast->type = control()->getPointerType(ast->objectType);
}

ast->valueCategory = ValueCategory::kPrValue;
}

void TypeChecker::Visitor::operator()(DeleteExpressionAST* ast) {}
void TypeChecker::Visitor::operator()(DeleteExpressionAST* ast) {
ast->type = control()->getVoidType();
ast->valueCategory = ValueCategory::kPrValue;
}

void TypeChecker::Visitor::operator()(CastExpressionAST* ast) {}
void TypeChecker::Visitor::operator()(CastExpressionAST* ast) {
if (ast->typeId) {
ast->type = control()->remove_reference(ast->typeId->type);
if (control()->is_lvalue_reference(ast->typeId->type))
ast->valueCategory = ValueCategory::kLValue;
else if (control()->is_rvalue_reference(ast->typeId->type))
ast->valueCategory = ValueCategory::kXValue;
else
ast->valueCategory = ValueCategory::kPrValue;
}
}

void TypeChecker::Visitor::operator()(ImplicitCastExpressionAST* ast) {}

Expand Down Expand Up @@ -808,7 +854,11 @@ void TypeChecker::Visitor::operator()(TypeTraitExpressionAST* ast) {

void TypeChecker::Visitor::operator()(ConditionExpressionAST* ast) {}

void TypeChecker::Visitor::operator()(EqualInitializerAST* ast) {}
void TypeChecker::Visitor::operator()(EqualInitializerAST* ast) {
if (!ast->expression) return;
ast->type = ast->expression->type;
ast->valueCategory = ast->expression->valueCategory;
}

void TypeChecker::Visitor::operator()(BracedInitListAST* ast) {}

Expand Down
2 changes: 1 addition & 1 deletion tests/unit_tests/ast/variadic_function_02.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void ff(int count, ...) {
// CHECK-NEXT: statement: compound-statement
// CHECK-NEXT: statement-list
// CHECK-NEXT: expression-statement
// CHECK-NEXT: expression: cast-expression
// CHECK-NEXT: expression: cast-expression [prvalue void]
// CHECK-NEXT: type-id: type-id
// CHECK-NEXT: type-specifier-list
// CHECK-NEXT: void-type-specifier
Expand Down