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: 2 additions & 0 deletions src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,7 @@ class BuiltinOffsetofExpressionAST final : public ExpressionAST {
SourceLocation commaLoc;
ExpressionAST* expression = nullptr;
SourceLocation rparenLoc;
FieldSymbol* symbol = nullptr;

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

Expand Down Expand Up @@ -3156,6 +3157,7 @@ class EnumSpecifierAST final : public SpecifierAST {
SourceLocation commaLoc;
List<EnumeratorAST*>* enumeratorList = nullptr;
SourceLocation rbraceLoc;
Symbol* symbol = nullptr;

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

Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/const_expression_evaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <cxx/types.h>

#include <format>
#include <optional>

namespace cxx {

Expand Down Expand Up @@ -214,6 +215,7 @@ auto ConstExpressionEvaluator::operator()(BuiltinBitCastExpressionAST* ast)

auto ConstExpressionEvaluator::operator()(BuiltinOffsetofExpressionAST* ast)
-> std::optional<ConstValue> {
if (ast->symbol) return ast->symbol->offset();
return std::nullopt;
}

Expand Down
7 changes: 7 additions & 0 deletions src/parser/cxx/memory_layout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,13 @@ struct SizeOf {
struct AlignmentOf {
const MemoryLayout& memoryLayout;

auto operator()(const ClassType* type) const -> std::optional<std::size_t> {
return type->symbol()->alignment();
}

auto operator()(auto type) const -> std::optional<std::size_t> {
// ### TODO
if (!type) return std::nullopt;
return memoryLayout.sizeOf(type);
}
};
Expand Down Expand Up @@ -297,11 +302,13 @@ void MemoryLayout::setSizeOfLongDouble(std::size_t sizeOfLongDouble) {

auto MemoryLayout::sizeOf(const Type* type) const
-> std::optional<std::size_t> {
if (!type) return std::nullopt;
return visit(SizeOf{*this}, type);
}

auto MemoryLayout::alignmentOf(const Type* type) const
-> std::optional<std::size_t> {
if (!type) return std::nullopt;
return visit(AlignmentOf{*this}, type);
}

Expand Down
6 changes: 3 additions & 3 deletions src/parser/cxx/name_lookup.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ class Lookup {
[[nodiscard]] auto lookupType(NestedNameSpecifierAST* nestedNameSpecifier,
const Identifier* id) const -> Symbol*;

private:
[[nodiscard]] auto unqualifiedLookup(const Name* name) const -> Symbol*;

[[nodiscard]] auto qualifiedLookup(Scope* scope, const Name* name) const
-> Symbol*;

private:
[[nodiscard]] auto unqualifiedLookup(const Name* name) const -> Symbol*;

[[nodiscard]] auto qualifiedLookup(Symbol* scopedSymbol,
const Name* name) const -> Symbol*;

Expand Down
94 changes: 87 additions & 7 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <cxx/const_expression_evaluator.h>
#include <cxx/control.h>
#include <cxx/literals.h>
#include <cxx/memory_layout.h>
#include <cxx/name_lookup.h>
#include <cxx/name_printer.h>
#include <cxx/names.h>
Expand All @@ -34,6 +35,7 @@
#include <cxx/token.h>
#include <cxx/type_printer.h>
#include <cxx/types.h>
#include <cxx/util.h>
#include <cxx/views/symbol_chain.h>

#include <algorithm>
Expand All @@ -42,12 +44,6 @@
#include <ranges>
#include <unordered_set>

#include "cxx/cxx_fwd.h"
#include "cxx/parser_fwd.h"
#include "cxx/source_location.h"
#include "cxx/symbols_fwd.h"
#include "cxx/token_fwd.h"

namespace cxx {

namespace {
Expand Down Expand Up @@ -2652,6 +2648,19 @@ auto Parser::parse_builtin_offsetof_expression(ExpressionAST*& yyast,
parse_expression(ast->expression, ctx);
expect(TokenKind::T_RPAREN, ast->rparenLoc);

auto classType = type_cast<ClassType>(ast->typeId->type);
auto id = ast_cast<IdExpressionAST>(ast->expression);

if (classType && id && !id->nestedNameSpecifier) {
auto symbol = classType->symbol();
auto name = convertName(id->unqualifiedId);
auto member = Lookup{scope_}.qualifiedLookup(symbol->scope(), name);
auto field = symbol_cast<FieldSymbol>(member);
ast->symbol = field;
}

ast->type = control_->getSizeType();

return true;
}

Expand Down Expand Up @@ -5631,7 +5640,10 @@ auto Parser::parse_defining_type_specifier(
if (parse_enum_specifier(yyast, specs)) {
lookahead.commit();

auto enumSpec = ast_cast<EnumSpecifierAST>(yyast);

specs.setTypeSpecifier(yyast);
specs.type = enumSpec->symbol->type();

return true;
}
Expand All @@ -5641,6 +5653,7 @@ auto Parser::parse_defining_type_specifier(
lookahead.commit();

specs.setTypeSpecifier(classSpecifier);
specs.type = classSpecifier->symbol->type();
yyast = classSpecifier;

return true;
Expand Down Expand Up @@ -6867,6 +6880,7 @@ auto Parser::parse_elaborated_type_specifier(
}

ast->symbol = classSymbol;
specs.type = classSymbol->type();

return true;
}
Expand Down Expand Up @@ -7971,6 +7985,7 @@ auto Parser::parse_enum_specifier(SpecifierAST*& yyast, DeclSpecs& specs)
ast->colonLoc = colonLoc;
ast->typeSpecifierList = typeSpecifierList;
ast->lbraceLoc = lbraceLoc;
ast->symbol = symbol;

if (!match(TokenKind::T_RBRACE, ast->rbraceLoc)) {
parse_enumerator_list(ast->enumeratorList, symbol->type());
Expand Down Expand Up @@ -9416,7 +9431,69 @@ auto Parser::parse_class_specifier(
expect(TokenKind::T_RBRACE, ast->rbraceLoc);
}

ast->symbol->setComplete(true);
if (!is_template(classSymbol)) {
int offset = 0;
int alignment = 1;

for (auto base : classSymbol->baseClasses()) {
auto baseClassSymbol = symbol_cast<ClassSymbol>(base->symbol());

if (!baseClassSymbol) {
if (config_.checkTypes) {
parse_error(base->location(), std::format("base class '{}' not found",
to_string(base->name())));
}
continue;
}

offset = align_to(offset, baseClassSymbol->alignment());
offset += baseClassSymbol->sizeInBytes();
alignment = std::max(alignment, baseClassSymbol->alignment());
}

for (auto member : classSymbol->scope()->symbols()) {
auto field = symbol_cast<FieldSymbol>(member);
if (!field) continue;
if (field->isStatic()) continue;

if (!field->alignment()) {
if (config_.checkTypes) {
parse_error(field->location(),
std::format("alignment of incomplete type '{}'",
to_string(field->type(), field->name())));
}
continue;
}

auto size = control_->memoryLayout()->sizeOf(field->type());

if (!size.has_value()) {
if (config_.checkTypes) {
parse_error(field->location(),
std::format("size of incomplete type '{}'",
to_string(field->type(), field->name())));
}
continue;
}

if (classSymbol->isUnion()) {
offset = std::max(offset, int(size.value()));
} else {
offset = align_to(offset, field->alignment());
field->setOffset(offset);
offset += size.value();
}

alignment = std::max(alignment, field->alignment());
}

offset = align_to(offset, alignment);

classSymbol->setAlignment(alignment);
classSymbol->setSizeInBytes(offset);
}

classSymbol->setComplete(true);

return true;
}
Expand Down Expand Up @@ -9798,6 +9875,9 @@ auto Parser::declareField(DeclaratorAST* declarator, const Decl& decl)
applySpecifiers(fieldSymbol, decl.specs);
fieldSymbol->setName(name);
fieldSymbol->setType(type);
if (auto alignment = control_->memoryLayout()->alignmentOf(type)) {
fieldSymbol->setAlignment(alignment.value());
}
scope_->addSymbol(fieldSymbol);
return fieldSymbol;
}
Expand Down
18 changes: 17 additions & 1 deletion src/parser/cxx/symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,15 @@ auto ClassSymbol::isComplete() const -> bool { return isComplete_; }

void ClassSymbol::setComplete(bool isComplete) { isComplete_ = isComplete; }

auto ClassSymbol::sizeInBytes() const -> std::size_t { return sizeInBytes_; }
auto ClassSymbol::sizeInBytes() const -> int { return sizeInBytes_; }

void ClassSymbol::setSizeInBytes(int sizeInBytes) {
sizeInBytes_ = sizeInBytes;
}

auto ClassSymbol::alignment() const -> int { return alignment_; }

void ClassSymbol::setAlignment(int alignment) { alignment_ = alignment; }

auto ClassSymbol::hasBaseClass(Symbol* symbol) const -> bool {
std::unordered_set<const ClassSymbol*> processed;
Expand Down Expand Up @@ -493,6 +501,14 @@ auto FieldSymbol::isInline() const -> bool { return isInline_; }

void FieldSymbol::setInline(bool isInline) { isInline_ = isInline; }

auto FieldSymbol::offset() const -> int { return offset_; }

void FieldSymbol::setOffset(int offset) { offset_ = offset; }

auto FieldSymbol::alignment() const -> int { return alignment_; }

void FieldSymbol::setAlignment(int alignment) { alignment_ = alignment; }

ParameterSymbol::ParameterSymbol(Scope* enclosingScope)
: Symbol(Kind, enclosingScope) {}

Expand Down
17 changes: 15 additions & 2 deletions src/parser/cxx/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ class ClassSymbol final : public ScopedSymbol {
[[nodiscard]] auto isComplete() const -> bool;
void setComplete(bool isComplete);

[[nodiscard]] auto sizeInBytes() const -> std::size_t;
[[nodiscard]] auto sizeInBytes() const -> int;
void setSizeInBytes(int sizeInBytes);

[[nodiscard]] auto alignment() const -> int;
void setAlignment(int alignment);

[[nodiscard]] auto hasBaseClass(Symbol* symbol) const -> bool;

Expand Down Expand Up @@ -305,7 +309,8 @@ class ClassSymbol final : public ScopedSymbol {
std::unique_ptr<TemplateInfo<ClassSymbol>> templateInfo_;
ClassSymbol* templateClass_ = nullptr;
std::size_t templateSepcializationIndex_ = 0;
std::size_t sizeInBytes_ = 0;
int sizeInBytes_ = 0;
int alignment_ = 0;
union {
std::uint32_t flags_{};
struct {
Expand Down Expand Up @@ -566,6 +571,12 @@ class FieldSymbol final : public Symbol {
[[nodiscard]] auto isInline() const -> bool;
void setInline(bool isInline);

[[nodiscard]] auto offset() const -> int;
void setOffset(int offset);

[[nodiscard]] auto alignment() const -> int;
void setAlignment(int alignment);

private:
union {
std::uint32_t flags_{};
Expand All @@ -577,6 +588,8 @@ class FieldSymbol final : public Symbol {
std::uint32_t isInline_ : 1;
};
};
int offset_{};
int alignment_{};
};

class ParameterSymbol final : public Symbol {
Expand Down
6 changes: 6 additions & 0 deletions tests/unit_tests/sema/wasm_stdlib_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// RUN: %cxx -toolchain wasm32 -ftemplates -fcheck %s

#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>