From 5fa2707760587d12e203e526ea919f45f5cd1bac Mon Sep 17 00:00:00 2001 From: Herb Sutter Date: Sun, 9 Apr 2023 12:20:06 -0700 Subject: [PATCH] Add diagnostics for `sometype.` and `object::`, closes #339 --- source/cppfront.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ source/parse.h | 10 ++++++++++ source/sema.h | 12 ++++++++++++ 3 files changed, 64 insertions(+) diff --git a/source/cppfront.cpp b/source/cppfront.cpp index f17ddc033..fb742e41a 100644 --- a/source/cppfront.cpp +++ b/source/cppfront.cpp @@ -1626,6 +1626,27 @@ class cppfront auto emit(qualified_id_node const& n) -> void { + // Check for some incorrect uses of :: or . + if (auto decl = sema.get_declaration_of(n.get_first_token(), true); + decl && std::ssize(n.ids) > 1 + ) + { + assert (decl->declaration); + + if ( + decl->declaration->is_object() + && n.ids[1].scope_op + && n.ids[1].scope_op->type() == lexeme::Scope + ) + { + errors.emplace_back( + n.position(), + "use '" + decl->identifier->to_string(true) + ".' to refer to an object member" + ); + return; + } + } + // Implicit "cpp2::" qualification of "unique.new" and "shared.new" if ( n.ids.size() == 2 @@ -2536,6 +2557,27 @@ class cppfront assert(n.expr); last_postfix_expr_was_pointer = false; + // Check for some incorrect uses of :: or . + if (auto decl = sema.get_declaration_of(n.get_first_token_ignoring_this(), true); + decl && !n.ops.empty() + ) + { + assert (decl->declaration); + + if ( + decl->declaration->is_type() + && n.ops[0].op + && n.ops[0].op->type() == lexeme::Dot + ) + { + errors.emplace_back( + n.position(), + "use '" + decl->identifier->to_string(true) + "::' to refer to a type member" + ); + return; + } + } + // For a 'move that' parameter, track the members we already moved from // so we can diagnose attempts to move from the same member twice if ( diff --git a/source/parse.h b/source/parse.h index c08efb21f..d13f7a1e1 100644 --- a/source/parse.h +++ b/source/parse.h @@ -636,6 +636,16 @@ struct qualified_id_node return {}; } + auto get_first_token() const + -> token const* + { + assert ( + !ids.empty() + && ids.front().id + ); + return ids.front().id->get_token(); + } + auto position() const -> source_position { diff --git a/source/sema.h b/source/sema.h index 65128d04b..31666e444 100644 --- a/source/sema.h +++ b/source/sema.h @@ -263,6 +263,18 @@ class sema // Get the declaration of t within the same named function or beyond it // + auto get_declaration_of( + token const* t, + bool look_beyond_current_function = false + ) + -> declaration_sym const* + { + if (!t) { + return {}; + } + return get_declaration_of(*t, look_beyond_current_function); + } + auto get_declaration_of( token const& t, bool look_beyond_current_function = false