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
1 change: 1 addition & 0 deletions src/parser/cxx/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,7 @@ class UsingDeclaratorAST final : public AST {
NestedNameSpecifierAST* nestedNameSpecifier = nullptr;
UnqualifiedIdAST* unqualifiedId = nullptr;
SourceLocation ellipsisLoc;
UsingDeclarationSymbol* symbol = nullptr;
bool isPack = false;

void accept(ASTVisitor* visitor) override { visitor->visit(this); }
Expand Down
9 changes: 9 additions & 0 deletions src/parser/cxx/control.cc
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct Control::Private {
std::forward_list<ConstraintTypeParameterSymbol>
constraintTypeParameterSymbols;
std::forward_list<EnumeratorSymbol> enumeratorSymbols;
std::forward_list<UsingDeclarationSymbol> usingDeclarationSymbols;

std::forward_list<TypeTraitIdentifierInfo> typeTraitIdentifierInfos;

Expand Down Expand Up @@ -624,6 +625,14 @@ auto Control::newEnumeratorSymbol(Scope* enclosingScope, SourceLocation loc)
return symbol;
}

auto Control::newUsingDeclarationSymbol(Scope* enclosingScope,
SourceLocation loc)
-> UsingDeclarationSymbol* {
auto symbol = &d->usingDeclarationSymbols.emplace_front(enclosingScope);
symbol->setLocation(loc);
return symbol;
}

auto Control::is_void(const Type* type) -> bool {
return d->traits.is_void(type);
}
Expand Down
3 changes: 3 additions & 0 deletions src/parser/cxx/control.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ class Control {
[[nodiscard]] auto newEnumeratorSymbol(Scope* enclosingScope,
SourceLocation sourceLocation)
-> EnumeratorSymbol*;
[[nodiscard]] auto newUsingDeclarationSymbol(Scope* enclosingScope,
SourceLocation sourceLocation)
-> UsingDeclarationSymbol*;

[[nodiscard]] auto instantiate(TranslationUnit* unit, Symbol* primaryTemplate,
const std::vector<TemplateArgument>& arguments)
Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/external_name_encoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ struct ExternalNameEncoder::SymbolVisitor {
void operator()(OverloadSetSymbol* symbol) {}

void operator()(BaseClassSymbol* symbol) {}

void operator()(UsingDeclarationSymbol* symbol) {}
};

ExternalNameEncoder::ExternalNameEncoder() {}
Expand Down
25 changes: 20 additions & 5 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8277,8 +8277,6 @@ auto Parser::parse_using_declarator_list(List<UsingDeclaratorAST*>*& yyast)

if (!parse_using_declarator(declarator)) return false;

declarator->isPack = match(TokenKind::T_DOT_DOT_DOT, declarator->ellipsisLoc);

*it = make_list_node(pool_, declarator);
it = &(*it)->next;

Expand All @@ -8287,9 +8285,6 @@ auto Parser::parse_using_declarator_list(List<UsingDeclaratorAST*>*& yyast)
while (match(TokenKind::T_COMMA, commaLoc)) {
if (UsingDeclaratorAST* declarator = nullptr;
parse_using_declarator(declarator)) {
declarator->isPack =
match(TokenKind::T_DOT_DOT_DOT, declarator->ellipsisLoc);

*it = make_list_node(pool_, declarator);
it = &(*it)->next;
} else {
Expand All @@ -8316,10 +8311,30 @@ auto Parser::parse_using_declarator(UsingDeclaratorAST*& yyast) -> bool {
/*inRequiresClause*/ false))
return false;

auto name = convertName(unqualifiedId);

SourceLocation ellipsisLoc;
auto isPack = match(TokenKind::T_DOT_DOT_DOT, ellipsisLoc);

yyast = make_node<UsingDeclaratorAST>(pool_);
yyast->typenameLoc = typenameLoc;
yyast->nestedNameSpecifier = nestedNameSpecifier;
yyast->unqualifiedId = unqualifiedId;
yyast->ellipsisLoc = ellipsisLoc;
yyast->isPack = isPack;

auto target = Lookup{scope_}.lookup(nestedNameSpecifier, name);

auto symbol = control_->newUsingDeclarationSymbol(
scope_, unqualifiedId->firstSourceLocation());

yyast->symbol = symbol;

symbol->setName(name);
symbol->setDeclarator(yyast);
symbol->setTarget(target);

std::invoke(DeclareSymbol{this, scope_}, symbol);

return true;
}
Expand Down
8 changes: 8 additions & 0 deletions src/parser/cxx/symbol_instantiation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct SymbolInstantiation::VisitSymbol {
-> Symbol*;
[[nodiscard]] auto operator()(OverloadSetSymbol* symbol) -> Symbol*;
[[nodiscard]] auto operator()(BaseClassSymbol* symbol) -> Symbol*;
[[nodiscard]] auto operator()(UsingDeclarationSymbol* symbol) -> Symbol*;
};

struct SymbolInstantiation::VisitType {
Expand Down Expand Up @@ -373,6 +374,13 @@ auto SymbolInstantiation::VisitSymbol::operator()(BaseClassSymbol* symbol)
return newSymbol;
}

auto SymbolInstantiation::VisitSymbol::operator()(
UsingDeclarationSymbol* symbol) -> Symbol* {
auto newSymbol = self.replacement(symbol);
newSymbol->setTarget(self.instantiate(symbol->target()));
return newSymbol;
}

// types

auto SymbolInstantiation::VisitType::operator()(const BuiltinVaListType* type)
Expand Down
13 changes: 12 additions & 1 deletion src/parser/cxx/symbol_printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ struct DumpSymbols {
} else {
out << std::format("{} {}\n", classKey, to_string(symbol->name()));
}
indent();
if (!symbol->constructors().empty()) {
++depth;
for (auto constructor : symbol->constructors()) {
Expand Down Expand Up @@ -308,6 +307,18 @@ struct DumpSymbols {
out << std::format("enumerator {}\n",
to_string(symbol->type(), symbol->name()));
}

void operator()(UsingDeclarationSymbol* symbol) {
indent();

if (auto target = symbol->target()) {
out << std::format("using {}\n",
to_string(target->type(), target->name()));
} else {
// unresolved symbol
out << std::format("using unresolved {}\n", to_string(symbol->name()));
}
}
};

} // namespace
Expand Down
17 changes: 17 additions & 0 deletions src/parser/cxx/symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -614,4 +614,21 @@ void EnumeratorSymbol::setValue(const std::optional<ConstValue>& value) {
value_ = value;
}

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

UsingDeclarationSymbol::~UsingDeclarationSymbol() {}

auto UsingDeclarationSymbol::target() const -> Symbol* { return target_; }

void UsingDeclarationSymbol::setTarget(Symbol* symbol) { target_ = symbol; }

auto UsingDeclarationSymbol::declarator() const -> UsingDeclaratorAST* {
return declarator_;
}

void UsingDeclarationSymbol::setDeclarator(UsingDeclaratorAST* declarator) {
declarator_ = declarator;
}

} // namespace cxx
18 changes: 18 additions & 0 deletions src/parser/cxx/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,24 @@ class EnumeratorSymbol final : public Symbol {
std::optional<ConstValue> value_;
};

class UsingDeclarationSymbol final : public Symbol {
public:
constexpr static auto Kind = SymbolKind::kUsingDeclaration;

explicit UsingDeclarationSymbol(Scope* enclosingScope);
~UsingDeclarationSymbol() override;

[[nodiscard]] auto declarator() const -> UsingDeclaratorAST*;
void setDeclarator(UsingDeclaratorAST* declarator);

[[nodiscard]] auto target() const -> Symbol*;
void setTarget(Symbol* symbol);

private:
Symbol* target_ = nullptr;
UsingDeclaratorAST* declarator_ = nullptr;
};

template <typename Visitor>
auto visit(Visitor&& visitor, Symbol* symbol) {
#define PROCESS_SYMBOL(S) \
Expand Down
3 changes: 2 additions & 1 deletion src/parser/cxx/symbols_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ namespace cxx {
V(TemplateTypeParameter) \
V(ConstraintTypeParameter) \
V(OverloadSet) \
V(BaseClass)
V(BaseClass) \
V(UsingDeclaration)

class Symbol;
class ScopedSymbol;
Expand Down
44 changes: 44 additions & 0 deletions tests/unit_tests/sema/using_decl_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %cxx -fcheck -dump-symbols %s | %filecheck %s

int printf(const char*, ...);

namespace std {
using ::printf;
}

struct Base {
operator bool() const;

void f();
};

struct Derived : Base {
using Base::operator bool;
using Base::f;
};

namespace std {
using nullptr_t = decltype(nullptr);
} // namespace std

auto main() -> int {
using std::nullptr_t;
return 0;
}

// clang-format off
// CHECK:namespace
// CHECK-NEXT: function int printf(const char*...)
// CHECK-NEXT: namespace std
// CHECK-NEXT: using int printf(const char*...)
// CHECK-NEXT: typealias decltype(nullptr) nullptr_t
// CHECK-NEXT: class Base
// CHECK-NEXT: function operator bool() const
// CHECK-NEXT: function void f()
// CHECK-NEXT: class Derived
// CHECK-NEXT: using operator bool() const
// CHECK-NEXT: using void f()
// CHECK-NEXT: function int main()
// CHECK-NEXT: block
// CHECK-NEXT: using decltype(nullptr) nullptr_t

Loading