From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by sourceware.org (Postfix) with ESMTPS id ECD1A384644B for ; Wed, 26 Oct 2022 08:16:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org ECD1A384644B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=embecosm.com Received: by mail-wr1-x431.google.com with SMTP id o4so16815720wrq.6 for ; Wed, 26 Oct 2022 01:16:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to; bh=/vSUCNndhCmmNIg/3Mj7JP9Ha5hpOBRiPaRL5e9nvvA=; b=AwfgIyyqksUDdIFn6rE9Z2xm00BBTHljeuJWEAJ4mU7RXsY0jgdZYxt4+61EK8fZ5m mxwOlQqXscw64sdQKxnTopgA6ZdAWIHUGE6ROWi64c0Jv+Pa+cddZSZKYDiItCxBGqQG CkSUI11FolhBGYfY0r9+00WHxoX7Cd/PIcMXafWtzt0ManShI/xsS7tWzqzdhl/nK2Xd irlTEeMdQHawBuZrBW4ToITrG1x2cEagY0oDcYXmSmwN0yU533QKrrf2n41kN7DBka77 OhBYRhSWip7FAZKg+xKVEjcFhhkABJb0SmiXajFdHA0MzmaqkqcXwCE+xK6/bE210PLl 4Z4g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=/vSUCNndhCmmNIg/3Mj7JP9Ha5hpOBRiPaRL5e9nvvA=; b=SAnoH3llLuaQe5dbcwH+5JOvopLfRqHjWH4rdOgVbgBSsitvydAhYmdAkgKTYcie96 GoXdeUWHSkyDvnxWPR49wOt/LeEWDkkW2WCimN8JrnpV3hzz7lFM1g6tA/+zXYN4VmJv 0SmfGx+ezfyWld+CP5rMbtNtE89l2hY6G2Hp/qIj3tDnsc2DA2el9PUPZB0vvkHa1cdw O+BfmJeT5Ac7iqj4JNeSoD5ntYCknfZ2FaLShX8TN2giu57Zn/OoBxr4aBD6KVqVquSM JFEpFAQnD/xcduxn9OeXWinqgRRBPSTsl3zag12y/KBWlPI4Rn7mle/8wYvxwG16fbXg nOiQ== X-Gm-Message-State: ACrzQf2DZBtRLjWfWFscBxzUR1KwwOdWnljcYENsPC31XbykNS3SpOJF 4uPwQFRlIy9vo4s5DCWlU4VP5y9ZqHiqwr0YyQ== X-Google-Smtp-Source: AMsMyM5lssgnw/e8Tw6fcpuYY09VXhUDM1d41wZVV6cd7/I1oEx0EbT7ywgsXqAzqH8QVH/PAWd4og== X-Received: by 2002:a05:6000:1ace:b0:22f:7201:74c0 with SMTP id i14-20020a0560001ace00b0022f720174c0mr28257340wry.216.1666772159974; Wed, 26 Oct 2022 01:15:59 -0700 (PDT) Received: from platypus.lan ([2001:861:5e4c:3bb0:6424:328a:1734:3249]) by smtp.googlemail.com with ESMTPSA id q16-20020a05600c46d000b003c6f426467fsm1134310wmo.40.2022.10.26.01.15.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Oct 2022 01:15:59 -0700 (PDT) From: arthur.cohen@embecosm.com To: gcc-patches@gcc.gnu.org Cc: gcc-rust@gcc.gnu.org Subject: [PATCH Rust front-end v3 31/46] gccrs: Add const checker Date: Wed, 26 Oct 2022 10:17:56 +0200 Message-Id: <20221026081811.602573-32-arthur.cohen@embecosm.com> X-Mailer: git-send-email 2.37.2 In-Reply-To: <20221026081811.602573-1-arthur.cohen@embecosm.com> References: <20221026081811.602573-1-arthur.cohen@embecosm.com> Reply-To: arthur.cohen@embecosm.com MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Arthur Cohen Similarly to the unsafe checker, constant evaluation can only be performed in a few contexts and include restrictions on the Rust language. Should the user fail to uphold those conditions, errors will be reported and the compilation pipeline interrupted. These contexts are as follow: - Array type length expressions - Array repeat length expressions - Constants - Statics - Enum discriminants - Const generic arguments In these contexts, the user is restricted to calling only functions marked as `const` or perform arithmetic operations only on certain types, among other restrictions. --- gcc/rust/checks/errors/rust-const-checker.cc | 844 +++++++++++++++++++ gcc/rust/checks/errors/rust-const-checker.h | 189 +++++ 2 files changed, 1033 insertions(+) create mode 100644 gcc/rust/checks/errors/rust-const-checker.cc create mode 100644 gcc/rust/checks/errors/rust-const-checker.h diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc new file mode 100644 index 00000000000..35c61fe03f0 --- /dev/null +++ b/gcc/rust/checks/errors/rust-const-checker.cc @@ -0,0 +1,844 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#include "rust-const-checker.h" +#include "rust-hir.h" +#include "rust-hir-expr.h" +#include "rust-hir-stmt.h" +#include "rust-hir-item.h" + +namespace Rust { +namespace HIR { + +ConstChecker::ConstChecker () + : resolver (*Resolver::Resolver::get ()), + mappings (*Analysis::Mappings::get ()) +{} + +void +ConstChecker::go (HIR::Crate &crate) +{ + for (auto &item : crate.items) + item->accept_vis (*this); +} + +bool +ConstChecker::is_const_extern_fn (HIR::ExternalFunctionItem &fn) +{ + // FIXME: Is it really how we want to handle `rustc_const_stable` + // and `rustc_const_unstable`? + // TODO: Add these attributes to the attribute check and handle + // `stable` and `unstable` as well + return std::any_of ( + fn.get_outer_attrs ().begin (), fn.get_outer_attrs ().end (), + [] (const AST::Attribute &attr) { + // `starts_with` in C++11... + return attr.get_path ().as_string ().rfind ("rustc_const_", 0) == 0; + }); +} + +void +ConstChecker::visit (Lifetime &lifetime) +{} + +void +ConstChecker::visit (LifetimeParam &lifetime_param) +{} + +void +ConstChecker::visit (PathInExpression &path) +{} + +void +ConstChecker::visit (TypePathSegment &segment) +{} + +void +ConstChecker::visit (TypePathSegmentGeneric &segment) +{} + +void +ConstChecker::visit (TypePathSegmentFunction &segment) +{} + +void +ConstChecker::visit (TypePath &path) +{} + +void +ConstChecker::visit (QualifiedPathInExpression &path) +{} + +void +ConstChecker::visit (QualifiedPathInType &path) +{} + +void +ConstChecker::visit (LiteralExpr &expr) +{} + +void +ConstChecker::visit (BorrowExpr &expr) +{ + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (DereferenceExpr &expr) +{ + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ErrorPropagationExpr &expr) +{ + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (NegationExpr &expr) +{ + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ArithmeticOrLogicalExpr &expr) +{ + expr.get_lhs ()->accept_vis (*this); + expr.get_rhs ()->accept_vis (*this); +} + +void +ConstChecker::visit (ComparisonExpr &expr) +{ + expr.get_lhs ()->accept_vis (*this); + expr.get_rhs ()->accept_vis (*this); +} + +void +ConstChecker::visit (LazyBooleanExpr &expr) +{ + expr.get_lhs ()->accept_vis (*this); + expr.get_rhs ()->accept_vis (*this); +} + +void +ConstChecker::visit (TypeCastExpr &expr) +{ + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (AssignmentExpr &expr) +{ + expr.get_lhs ()->accept_vis (*this); + expr.get_rhs ()->accept_vis (*this); +} + +void +ConstChecker::visit (CompoundAssignmentExpr &expr) +{ + expr.get_left_expr ()->accept_vis (*this); + expr.get_right_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (GroupedExpr &expr) +{ + expr.get_expr_in_parens ()->accept_vis (*this); +} + +void +ConstChecker::visit (ArrayElemsValues &elems) +{ + for (auto &elem : elems.get_values ()) + elem->accept_vis (*this); +} + +void +ConstChecker::visit (ArrayElemsCopied &elems) +{ + elems.get_elem_to_copy ()->accept_vis (*this); + + const_context.enter (elems.get_mappings ().get_hirid ()); + + elems.get_num_copies_expr ()->accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (ArrayExpr &expr) +{ + expr.get_internal_elements ()->accept_vis (*this); +} + +void +ConstChecker::visit (ArrayIndexExpr &expr) +{ + expr.get_array_expr ()->accept_vis (*this); + expr.get_index_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (TupleExpr &expr) +{ + for (auto &elem : expr.get_tuple_elems ()) + elem->accept_vis (*this); +} + +void +ConstChecker::visit (TupleIndexExpr &expr) +{ + expr.get_tuple_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (StructExprStruct &expr) +{} + +void +ConstChecker::visit (StructExprFieldIdentifier &field) +{} + +void +ConstChecker::visit (StructExprFieldIdentifierValue &field) +{ + field.get_value ()->accept_vis (*this); +} + +void +ConstChecker::visit (StructExprFieldIndexValue &field) +{ + field.get_value ()->accept_vis (*this); +} + +void +ConstChecker::visit (StructExprStructFields &expr) +{ + for (auto &field : expr.get_fields ()) + field->accept_vis (*this); +} + +void +ConstChecker::visit (StructExprStructBase &expr) +{} + +void +ConstChecker::check_function_call (HirId fn_id, Location locus) +{ + if (!const_context.is_in_context ()) + return; + + auto maybe_fn = mappings.lookup_hir_item (fn_id); + if (maybe_fn && maybe_fn->get_item_kind () != Item::ItemKind::Function) + return; + + // There are const extern functions (intrinsics) + // TODO: Should we check the ABI is only "rust intrinsics"? Is that handled + // elsewhere? + HirId parent_block; + auto maybe_extern_item + = mappings.lookup_hir_extern_item (fn_id, &parent_block); + if (maybe_extern_item + && maybe_extern_item->get_extern_kind () + != ExternalItem::ExternKind::Function) + return; + + auto is_error = false; + if (maybe_fn) + { + auto fn = static_cast (maybe_fn); + if (!fn->get_qualifiers ().is_const ()) + is_error = true; + } + + if (maybe_extern_item) + { + { + auto fn = static_cast (maybe_extern_item); + if (!is_const_extern_fn (*fn)) + is_error = true; + } + } + + if (is_error) + rust_error_at (locus, "only functions marked as % are allowed to " + "be called from constant contexts"); +} + +void +ConstChecker::visit (CallExpr &expr) +{ + auto fn = expr.get_fnexpr (); + if (!fn) + return; + + NodeId ast_node_id = fn->get_mappings ().get_nodeid (); + NodeId ref_node_id; + HirId definition_id; + + // We don't care about types here + if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) + return; + + rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id)); + + check_function_call (definition_id, expr.get_locus ()); + + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +ConstChecker::visit (MethodCallExpr &expr) +{ + expr.get_receiver ()->accept_vis (*this); + + for (auto &arg : expr.get_arguments ()) + arg->accept_vis (*this); +} + +void +ConstChecker::visit (FieldAccessExpr &expr) +{ + expr.get_receiver_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ClosureExprInner &expr) +{} + +void +ConstChecker::visit (BlockExpr &expr) +{ + for (auto &stmt : expr.get_statements ()) + stmt->accept_vis (*this); + + if (expr.has_expr ()) + expr.get_final_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ClosureExprInnerTyped &expr) +{} + +void +ConstChecker::visit (ContinueExpr &expr) +{} + +void +ConstChecker::visit (BreakExpr &expr) +{ + if (expr.has_break_expr ()) + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (RangeFromToExpr &expr) +{ + expr.get_from_expr ()->accept_vis (*this); + expr.get_to_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (RangeFromExpr &expr) +{ + expr.get_from_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (RangeToExpr &expr) +{ + expr.get_to_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (RangeFullExpr &expr) +{} + +void +ConstChecker::visit (RangeFromToInclExpr &expr) +{ + expr.get_from_expr ()->accept_vis (*this); + expr.get_to_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (RangeToInclExpr &expr) +{ + // FIXME: Visit to_expr +} + +void +ConstChecker::visit (ReturnExpr &expr) +{ + if (expr.has_return_expr ()) + expr.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (UnsafeBlockExpr &expr) +{ + expr.get_block_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (LoopExpr &expr) +{ + expr.get_loop_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (WhileLoopExpr &expr) +{ + expr.get_predicate_expr ()->accept_vis (*this); + expr.get_loop_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (WhileLetLoopExpr &expr) +{ + expr.get_cond ()->accept_vis (*this); + expr.get_loop_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (ForLoopExpr &expr) +{ + expr.get_iterator_expr ()->accept_vis (*this); + expr.get_loop_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfExpr &expr) +{ + expr.get_if_condition ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfExprConseqElse &expr) +{ + expr.get_if_condition ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); + expr.get_else_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfExprConseqIf &expr) +{ + expr.get_if_condition ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); + expr.get_conseq_if_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfExprConseqIfLet &expr) +{ + expr.get_if_condition ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); + + // TODO: Visit conseq if let expression +} + +void +ConstChecker::visit (IfLetExpr &expr) +{ + expr.get_scrutinee_expr ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfLetExprConseqElse &expr) +{ + expr.get_scrutinee_expr ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); + + // TODO: Visit else expression +} + +void +ConstChecker::visit (IfLetExprConseqIf &expr) +{ + expr.get_scrutinee_expr ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); +} + +void +ConstChecker::visit (IfLetExprConseqIfLet &expr) +{ + expr.get_scrutinee_expr ()->accept_vis (*this); + expr.get_if_block ()->accept_vis (*this); + + // TODO: Visit conseq if let expression +} + +void +ConstChecker::visit (MatchExpr &expr) +{ + expr.get_scrutinee_expr ()->accept_vis (*this); + + for (auto &match_arm : expr.get_match_cases ()) + match_arm.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (AwaitExpr &expr) +{ + // TODO: Visit expression +} + +void +ConstChecker::visit (AsyncBlockExpr &expr) +{ + // TODO: Visit block expression +} + +void +ConstChecker::visit (TypeParam ¶m) +{} + +void +ConstChecker::visit (ConstGenericParam ¶m) +{} + +void +ConstChecker::visit (LifetimeWhereClauseItem &item) +{} + +void +ConstChecker::visit (TypeBoundWhereClauseItem &item) +{} + +void +ConstChecker::visit (Module &module) +{ + for (auto &item : module.get_items ()) + item->accept_vis (*this); +} + +void +ConstChecker::visit (ExternCrate &crate) +{} + +void +ConstChecker::visit (UseTreeGlob &use_tree) +{} + +void +ConstChecker::visit (UseTreeList &use_tree) +{} + +void +ConstChecker::visit (UseTreeRebind &use_tree) +{} + +void +ConstChecker::visit (UseDeclaration &use_decl) +{} + +void +ConstChecker::visit (Function &function) +{ + auto const_fn = function.get_qualifiers ().is_const (); + if (const_fn) + const_context.enter (function.get_mappings ().get_hirid ()); + + for (auto ¶m : function.get_function_params ()) + param.get_type ()->accept_vis (*this); + + function.get_definition ()->accept_vis (*this); + + if (const_fn) + const_context.exit (); +} + +void +ConstChecker::visit (TypeAlias &type_alias) +{} + +void +ConstChecker::visit (StructStruct &struct_item) +{} + +void +ConstChecker::visit (TupleStruct &tuple_struct) +{} + +void +ConstChecker::visit (EnumItem &item) +{} + +void +ConstChecker::visit (EnumItemTuple &item) +{} + +void +ConstChecker::visit (EnumItemStruct &item) +{} + +void +ConstChecker::visit (EnumItemDiscriminant &item) +{ + const_context.enter (item.get_mappings ().get_hirid ()); + + item.get_discriminant_expression ()->accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (Enum &enum_item) +{} + +void +ConstChecker::visit (Union &union_item) +{} + +void +ConstChecker::visit (ConstantItem &const_item) +{ + const_context.enter (const_item.get_mappings ().get_hirid ()); + + const_item.get_expr ()->accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (StaticItem &static_item) +{ + const_context.enter (static_item.get_mappings ().get_hirid ()); + + static_item.get_expr ()->accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (TraitItemFunc &item) +{ + if (item.has_block_defined ()) + item.get_block_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (TraitItemConst &item) +{ + if (item.has_expr ()) + item.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (TraitItemType &item) +{} + +void +ConstChecker::visit (Trait &trait) +{ + for (auto &item : trait.get_trait_items ()) + item->accept_vis (*this); +} + +void +ConstChecker::visit (ImplBlock &impl) +{ + for (auto &item : impl.get_impl_items ()) + item->accept_vis (*this); +} + +void +ConstChecker::visit (ExternalStaticItem &item) +{} + +void +ConstChecker::visit (ExternalFunctionItem &item) +{} + +void +ConstChecker::visit (ExternBlock &block) +{ + // FIXME: Do we need to do this? + for (auto &item : block.get_extern_items ()) + item->accept_vis (*this); +} + +void +ConstChecker::visit (LiteralPattern &pattern) +{} + +void +ConstChecker::visit (IdentifierPattern &pattern) +{} + +void +ConstChecker::visit (WildcardPattern &pattern) +{} + +void +ConstChecker::visit (RangePatternBoundLiteral &bound) +{} + +void +ConstChecker::visit (RangePatternBoundPath &bound) +{} + +void +ConstChecker::visit (RangePatternBoundQualPath &bound) +{} + +void +ConstChecker::visit (RangePattern &pattern) +{} + +void +ConstChecker::visit (ReferencePattern &pattern) +{} + +void +ConstChecker::visit (StructPatternFieldTuplePat &field) +{} + +void +ConstChecker::visit (StructPatternFieldIdentPat &field) +{} + +void +ConstChecker::visit (StructPatternFieldIdent &field) +{} + +void +ConstChecker::visit (StructPattern &pattern) +{} + +void +ConstChecker::visit (TupleStructItemsNoRange &tuple_items) +{} + +void +ConstChecker::visit (TupleStructItemsRange &tuple_items) +{} + +void +ConstChecker::visit (TupleStructPattern &pattern) +{} + +void +ConstChecker::visit (TuplePatternItemsMultiple &tuple_items) +{} + +void +ConstChecker::visit (TuplePatternItemsRanged &tuple_items) +{} + +void +ConstChecker::visit (TuplePattern &pattern) +{} + +void +ConstChecker::visit (GroupedPattern &pattern) +{} + +void +ConstChecker::visit (SlicePattern &pattern) +{} + +void +ConstChecker::visit (EmptyStmt &stmt) +{} + +void +ConstChecker::visit (LetStmt &stmt) +{ + if (stmt.has_init_expr ()) + stmt.get_init_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ExprStmtWithoutBlock &stmt) +{ + stmt.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (ExprStmtWithBlock &stmt) +{ + stmt.get_expr ()->accept_vis (*this); +} + +void +ConstChecker::visit (TraitBound &bound) +{} + +void +ConstChecker::visit (ImplTraitType &type) +{} + +void +ConstChecker::visit (TraitObjectType &type) +{} + +void +ConstChecker::visit (ParenthesisedType &type) +{} + +void +ConstChecker::visit (ImplTraitTypeOneBound &type) +{} + +void +ConstChecker::visit (TupleType &type) +{} + +void +ConstChecker::visit (NeverType &type) +{} + +void +ConstChecker::visit (RawPointerType &type) +{} + +void +ConstChecker::visit (ReferenceType &type) +{} + +void +ConstChecker::visit (ArrayType &type) +{ + const_context.enter (type.get_mappings ().get_hirid ()); + + type.get_size_expr ()->accept_vis (*this); + + const_context.exit (); +} + +void +ConstChecker::visit (SliceType &type) +{} + +void +ConstChecker::visit (InferredType &type) +{} + +void +ConstChecker::visit (BareFunctionType &type) +{} + +} // namespace HIR +} // namespace Rust diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h new file mode 100644 index 00000000000..50838d18996 --- /dev/null +++ b/gcc/rust/checks/errors/rust-const-checker.h @@ -0,0 +1,189 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_CONST_CHECKER_H +#define RUST_CONST_CHECKER_H + +#include "rust-hir-visitor.h" +#include "rust-hir-type-check.h" +#include "rust-stacked-contexts.h" +#include "rust-name-resolver.h" + +namespace Rust { +namespace HIR { +class ConstChecker : public HIRFullVisitor +{ +public: + ConstChecker (); + + void go (HIR::Crate &crate); + + /** + * Check if an item is a const extern item or not + * TODO: Move this to a const compilation context class or an attribute + * checking class + */ + static bool is_const_extern_fn (HIR::ExternalFunctionItem &fn); + +private: + /** + * Check that only const functions are called in const contexts + */ + void check_function_call (HirId fn_id, Location locus); + + StackedContexts const_context; + Resolver::Resolver &resolver; + Analysis::Mappings &mappings; + + virtual void visit (Lifetime &lifetime) override; + virtual void visit (LifetimeParam &lifetime_param) override; + virtual void visit (PathInExpression &path) override; + virtual void visit (TypePathSegment &segment) override; + virtual void visit (TypePathSegmentGeneric &segment) override; + virtual void visit (TypePathSegmentFunction &segment) override; + virtual void visit (TypePath &path) override; + virtual void visit (QualifiedPathInExpression &path) override; + virtual void visit (QualifiedPathInType &path) override; + virtual void visit (LiteralExpr &expr) override; + virtual void visit (BorrowExpr &expr) override; + virtual void visit (DereferenceExpr &expr) override; + virtual void visit (ErrorPropagationExpr &expr) override; + virtual void visit (NegationExpr &expr) override; + virtual void visit (ArithmeticOrLogicalExpr &expr) override; + virtual void visit (ComparisonExpr &expr) override; + virtual void visit (LazyBooleanExpr &expr) override; + virtual void visit (TypeCastExpr &expr) override; + virtual void visit (AssignmentExpr &expr) override; + virtual void visit (CompoundAssignmentExpr &expr) override; + virtual void visit (GroupedExpr &expr) override; + virtual void visit (ArrayElemsValues &elems) override; + virtual void visit (ArrayElemsCopied &elems) override; + virtual void visit (ArrayExpr &expr) override; + virtual void visit (ArrayIndexExpr &expr) override; + virtual void visit (TupleExpr &expr) override; + virtual void visit (TupleIndexExpr &expr) override; + virtual void visit (StructExprStruct &expr) override; + virtual void visit (StructExprFieldIdentifier &field) override; + virtual void visit (StructExprFieldIdentifierValue &field) override; + virtual void visit (StructExprFieldIndexValue &field) override; + virtual void visit (StructExprStructFields &expr) override; + virtual void visit (StructExprStructBase &expr) override; + virtual void visit (CallExpr &expr) override; + virtual void visit (MethodCallExpr &expr) override; + virtual void visit (FieldAccessExpr &expr) override; + virtual void visit (ClosureExprInner &expr) override; + virtual void visit (BlockExpr &expr) override; + virtual void visit (ClosureExprInnerTyped &expr) override; + virtual void visit (ContinueExpr &expr) override; + virtual void visit (BreakExpr &expr) override; + virtual void visit (RangeFromToExpr &expr) override; + virtual void visit (RangeFromExpr &expr) override; + virtual void visit (RangeToExpr &expr) override; + virtual void visit (RangeFullExpr &expr) override; + virtual void visit (RangeFromToInclExpr &expr) override; + virtual void visit (RangeToInclExpr &expr) override; + virtual void visit (ReturnExpr &expr) override; + virtual void visit (UnsafeBlockExpr &expr) override; + virtual void visit (LoopExpr &expr) override; + virtual void visit (WhileLoopExpr &expr) override; + virtual void visit (WhileLetLoopExpr &expr) override; + virtual void visit (ForLoopExpr &expr) override; + virtual void visit (IfExpr &expr) override; + virtual void visit (IfExprConseqElse &expr) override; + virtual void visit (IfExprConseqIf &expr) override; + virtual void visit (IfExprConseqIfLet &expr) override; + virtual void visit (IfLetExpr &expr) override; + virtual void visit (IfLetExprConseqElse &expr) override; + virtual void visit (IfLetExprConseqIf &expr) override; + virtual void visit (IfLetExprConseqIfLet &expr) override; + virtual void visit (MatchExpr &expr) override; + virtual void visit (AwaitExpr &expr) override; + virtual void visit (AsyncBlockExpr &expr) override; + virtual void visit (TypeParam ¶m) override; + virtual void visit (ConstGenericParam ¶m) override; + virtual void visit (LifetimeWhereClauseItem &item) override; + virtual void visit (TypeBoundWhereClauseItem &item) override; + virtual void visit (Module &module) override; + virtual void visit (ExternCrate &crate) override; + virtual void visit (UseTreeGlob &use_tree) override; + virtual void visit (UseTreeList &use_tree) override; + virtual void visit (UseTreeRebind &use_tree) override; + virtual void visit (UseDeclaration &use_decl) override; + virtual void visit (Function &function) override; + virtual void visit (TypeAlias &type_alias) override; + virtual void visit (StructStruct &struct_item) override; + virtual void visit (TupleStruct &tuple_struct) override; + virtual void visit (EnumItem &item) override; + virtual void visit (EnumItemTuple &item) override; + virtual void visit (EnumItemStruct &item) override; + virtual void visit (EnumItemDiscriminant &item) override; + virtual void visit (Enum &enum_item) override; + virtual void visit (Union &union_item) override; + virtual void visit (ConstantItem &const_item) override; + virtual void visit (StaticItem &static_item) override; + virtual void visit (TraitItemFunc &item) override; + virtual void visit (TraitItemConst &item) override; + virtual void visit (TraitItemType &item) override; + virtual void visit (Trait &trait) override; + virtual void visit (ImplBlock &impl) override; + virtual void visit (ExternalStaticItem &item) override; + virtual void visit (ExternalFunctionItem &item) override; + virtual void visit (ExternBlock &block) override; + virtual void visit (LiteralPattern &pattern) override; + virtual void visit (IdentifierPattern &pattern) override; + virtual void visit (WildcardPattern &pattern) override; + virtual void visit (RangePatternBoundLiteral &bound) override; + virtual void visit (RangePatternBoundPath &bound) override; + virtual void visit (RangePatternBoundQualPath &bound) override; + virtual void visit (RangePattern &pattern) override; + virtual void visit (ReferencePattern &pattern) override; + virtual void visit (StructPatternFieldTuplePat &field) override; + virtual void visit (StructPatternFieldIdentPat &field) override; + virtual void visit (StructPatternFieldIdent &field) override; + virtual void visit (StructPattern &pattern) override; + virtual void visit (TupleStructItemsNoRange &tuple_items) override; + virtual void visit (TupleStructItemsRange &tuple_items) override; + virtual void visit (TupleStructPattern &pattern) override; + virtual void visit (TuplePatternItemsMultiple &tuple_items) override; + virtual void visit (TuplePatternItemsRanged &tuple_items) override; + virtual void visit (TuplePattern &pattern) override; + virtual void visit (GroupedPattern &pattern) override; + virtual void visit (SlicePattern &pattern) override; + virtual void visit (EmptyStmt &stmt) override; + virtual void visit (LetStmt &stmt) override; + virtual void visit (ExprStmtWithoutBlock &stmt) override; + virtual void visit (ExprStmtWithBlock &stmt) override; + virtual void visit (TraitBound &bound) override; + virtual void visit (ImplTraitType &type) override; + virtual void visit (TraitObjectType &type) override; + virtual void visit (ParenthesisedType &type) override; + virtual void visit (ImplTraitTypeOneBound &type) override; + virtual void visit (TupleType &type) override; + virtual void visit (NeverType &type) override; + virtual void visit (RawPointerType &type) override; + virtual void visit (ReferenceType &type) override; + virtual void visit (ArrayType &type) override; + virtual void visit (SliceType &type) override; + virtual void visit (InferredType &type) override; + virtual void visit (BareFunctionType &type) override; +}; + +} // namespace HIR +} // namespace Rust + +#endif /* !RUST_CONST_CHECKER_H */ -- 2.37.2