]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/cp-objcp-common.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / cp / cp-objcp-common.cc
index 0b70d5567e47e73308173d009eb0baffa84ca21e..2bec8e61cc07d7e8823904d2266b99aa52a2b2e9 100644 (file)
@@ -1,5 +1,5 @@
 /* Some code common to C++ and ObjC++ front ends.
-   Copyright (C) 2004-2022 Free Software Foundation, Inc.
+   Copyright (C) 2004-2024 Free Software Foundation, Inc.
    Contributed by Ziemowit Laski  <zlaski@apple.com>
 
 This file is part of GCC.
@@ -23,8 +23,153 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "cp-tree.h"
 #include "cp-objcp-common.h"
+#include "c-family/c-common.h"
 #include "dwarf2.h"
 #include "stringpool.h"
+#include "contracts.h"
+
+/* Class to determine whether a given C++ language feature is available.
+   Used to implement __has_{feature,extension}.  */
+
+struct cp_feature_selector
+{
+  enum
+  {
+    DIALECT,
+    FLAG
+  } kind;
+
+  enum class result
+  {
+    NONE,
+    EXT,
+    FEAT
+  };
+
+  union
+  {
+    const int *enable_flag;
+    struct {
+      enum cxx_dialect feat;
+      enum cxx_dialect ext;
+    } dialect;
+  };
+
+  constexpr cp_feature_selector (const int *flag)
+    : kind (FLAG), enable_flag (flag) {}
+  constexpr cp_feature_selector (enum cxx_dialect feat,
+                                enum cxx_dialect ext)
+    : kind (DIALECT), dialect{feat, ext} {}
+  constexpr cp_feature_selector (enum cxx_dialect feat)
+    : cp_feature_selector (feat, feat) {}
+
+  inline result has_feature () const;
+};
+
+/* Check whether this language feature is available as a feature,
+   extension, or not at all.  */
+
+cp_feature_selector::result
+cp_feature_selector::has_feature () const
+{
+  switch (kind)
+    {
+    case DIALECT:
+      if (cxx_dialect >= dialect.feat)
+       return result::FEAT;
+      else if (cxx_dialect >= dialect.ext)
+       return result::EXT;
+      else
+       return result::NONE;
+    case FLAG:
+      return *enable_flag ? result::FEAT : result::NONE;
+    }
+
+  gcc_unreachable ();
+}
+
+/* Information about a C++ language feature which can be queried
+   through __has_{feature,extension}.  IDENT is the name of the feature,
+   and SELECTOR encodes how to compute whether the feature is available.  */
+
+struct cp_feature_info
+{
+  const char *ident;
+  cp_feature_selector selector;
+};
+
+/* Table of features for __has_{feature,extension}.  */
+
+static constexpr cp_feature_info cp_feature_table[] =
+{
+  { "cxx_exceptions", &flag_exceptions },
+  { "cxx_rtti", &flag_rtti },
+  { "cxx_access_control_sfinae", { cxx11, cxx98 } },
+  { "cxx_alias_templates", cxx11 },
+  { "cxx_alignas", cxx11 },
+  { "cxx_alignof", cxx11 },
+  { "cxx_attributes", cxx11 },
+  { "cxx_constexpr", cxx11 },
+  { "cxx_constexpr_string_builtins", cxx11 },
+  { "cxx_decltype", cxx11 },
+  { "cxx_decltype_incomplete_return_types", cxx11 },
+  { "cxx_default_function_template_args", cxx11 },
+  { "cxx_defaulted_functions", cxx11 },
+  { "cxx_delegating_constructors", cxx11 },
+  { "cxx_deleted_functions", cxx11 },
+  { "cxx_explicit_conversions", cxx11 },
+  { "cxx_generalized_initializers", cxx11 },
+  { "cxx_implicit_moves", cxx11 },
+  { "cxx_inheriting_constructors", cxx11 },
+  { "cxx_inline_namespaces", { cxx11, cxx98 } },
+  { "cxx_lambdas", cxx11 },
+  { "cxx_local_type_template_args", cxx11 },
+  { "cxx_noexcept", cxx11 },
+  { "cxx_nonstatic_member_init", cxx11 },
+  { "cxx_nullptr", cxx11 },
+  { "cxx_override_control", cxx11 },
+  { "cxx_reference_qualified_functions", cxx11 },
+  { "cxx_range_for", cxx11 },
+  { "cxx_raw_string_literals", cxx11 },
+  { "cxx_rvalue_references", cxx11 },
+  { "cxx_static_assert", cxx11 },
+  { "cxx_thread_local", cxx11 },
+  { "cxx_auto_type", cxx11 },
+  { "cxx_strong_enums", cxx11 },
+  { "cxx_trailing_return", cxx11 },
+  { "cxx_unicode_literals", cxx11 },
+  { "cxx_unrestricted_unions", cxx11 },
+  { "cxx_user_literals", cxx11 },
+  { "cxx_variadic_templates", { cxx11, cxx98 } },
+  { "cxx_binary_literals", { cxx14, cxx98 } },
+  { "cxx_contextual_conversions", { cxx14, cxx98 } },
+  { "cxx_decltype_auto", cxx14 },
+  { "cxx_aggregate_nsdmi", cxx14 },
+  { "cxx_init_captures", { cxx14, cxx11 } },
+  { "cxx_generic_lambdas", cxx14 },
+  { "cxx_relaxed_constexpr", cxx14 },
+  { "cxx_return_type_deduction", cxx14 },
+  { "cxx_variable_templates", cxx14 },
+  { "modules", &flag_modules },
+};
+
+/* Register C++ language features for __has_{feature,extension}.  */
+
+void
+cp_register_features ()
+{
+  using result = cp_feature_selector::result;
+
+  for (unsigned i = 0; i < ARRAY_SIZE (cp_feature_table); i++)
+    {
+      const cp_feature_info *info = cp_feature_table + i;
+      const auto res = info->selector.has_feature ();
+      if (res == result::NONE)
+       continue;
+
+      c_common_register_feature (info->ident, res == result::FEAT);
+    }
+}
 
 /* Special routine to get the alias set for C++.  */
 
@@ -86,6 +231,9 @@ cp_tree_size (enum tree_code code)
     case CONSTRAINT_INFO:       return sizeof (tree_constraint_info);
     case USERDEF_LITERAL:      return sizeof (tree_userdef_literal);
     case TEMPLATE_DECL:                return sizeof (tree_template_decl);
+    case ASSERTION_STMT:       return sizeof (tree_exp);
+    case PRECONDITION_STMT:    return sizeof (tree_exp);
+    case POSTCONDITION_STMT:   return sizeof (tree_exp);
     default:
       switch (TREE_CODE_CLASS (code))
        {
@@ -417,6 +565,10 @@ names_builtin_p (const char *name)
        }
     }
 
+  /* Check for built-in traits.  */
+  if (IDENTIFIER_TRAIT_P (id))
+    return true;
+
   /* Also detect common reserved C++ words that aren't strictly built-in
      functions.  */
   switch (C_RID_CODE (id))
@@ -430,37 +582,6 @@ names_builtin_p (const char *name)
     case RID_BUILTIN_ASSOC_BARRIER:
     case RID_BUILTIN_BIT_CAST:
     case RID_OFFSETOF:
-    case RID_HAS_NOTHROW_ASSIGN:
-    case RID_HAS_NOTHROW_CONSTRUCTOR:
-    case RID_HAS_NOTHROW_COPY:
-    case RID_HAS_TRIVIAL_ASSIGN:
-    case RID_HAS_TRIVIAL_CONSTRUCTOR:
-    case RID_HAS_TRIVIAL_COPY:
-    case RID_HAS_TRIVIAL_DESTRUCTOR:
-    case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
-    case RID_HAS_VIRTUAL_DESTRUCTOR:
-    case RID_IS_ABSTRACT:
-    case RID_IS_AGGREGATE:
-    case RID_IS_BASE_OF:
-    case RID_IS_CLASS:
-    case RID_IS_EMPTY:
-    case RID_IS_ENUM:
-    case RID_IS_FINAL:
-    case RID_IS_LAYOUT_COMPATIBLE:
-    case RID_IS_LITERAL_TYPE:
-    case RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF:
-    case RID_IS_POD:
-    case RID_IS_POLYMORPHIC:
-    case RID_IS_SAME_AS:
-    case RID_IS_STD_LAYOUT:
-    case RID_IS_TRIVIAL:
-    case RID_IS_TRIVIALLY_ASSIGNABLE:
-    case RID_IS_TRIVIALLY_CONSTRUCTIBLE:
-    case RID_IS_TRIVIALLY_COPYABLE:
-    case RID_IS_UNION:
-    case RID_IS_ASSIGNABLE:
-    case RID_IS_CONSTRUCTIBLE:
-    case RID_UNDERLYING_TYPE:
       return true;
     default:
       break;
@@ -500,7 +621,6 @@ cp_common_init_ts (void)
   /* New decls.  */
   MARK_TS_DECL_COMMON (TEMPLATE_DECL);
   MARK_TS_DECL_COMMON (WILDCARD_DECL);
-  MARK_TS_DECL_COMMON (CONCEPT_DECL);
 
   MARK_TS_DECL_NON_COMMON (USING_DECL);
 
@@ -512,7 +632,7 @@ cp_common_init_ts (void)
   MARK_TS_TYPE_NON_COMMON (DECLTYPE_TYPE);
   MARK_TS_TYPE_NON_COMMON (TYPENAME_TYPE);
   MARK_TS_TYPE_NON_COMMON (TYPEOF_TYPE);
-  MARK_TS_TYPE_NON_COMMON (UNDERLYING_TYPE);
+  MARK_TS_TYPE_NON_COMMON (TRAIT_TYPE);
   MARK_TS_TYPE_NON_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM);
   MARK_TS_TYPE_NON_COMMON (TEMPLATE_TEMPLATE_PARM);
   MARK_TS_TYPE_NON_COMMON (TEMPLATE_TYPE_PARM);
@@ -549,7 +669,6 @@ cp_common_init_ts (void)
   MARK_TS_EXP (MUST_NOT_THROW_EXPR);
   MARK_TS_EXP (NEW_EXPR);
   MARK_TS_EXP (NOEXCEPT_EXPR);
-  MARK_TS_EXP (NON_DEPENDENT_EXPR);
   MARK_TS_EXP (OFFSETOF_EXPR);
   MARK_TS_EXP (OFFSET_REF);
   MARK_TS_EXP (PSEUDO_DTOR_EXPR);
@@ -592,6 +711,10 @@ cp_common_init_ts (void)
   MARK_TS_EXP (CO_YIELD_EXPR);
   MARK_TS_EXP (CO_RETURN_EXPR);
 
+  MARK_TS_EXP (ASSERTION_STMT);
+  MARK_TS_EXP (PRECONDITION_STMT);
+  MARK_TS_EXP (POSTCONDITION_STMT);
+
   c_common_init_ts ();
 }
 
@@ -604,6 +727,39 @@ cp_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
 {
   if (handle_module_option (unsigned (scode), arg, value))
     return true;
+
+  enum opt_code code = (enum opt_code) scode;
+  bool handled_p = true;
+
+  switch (code)
+    {
+    case OPT_fcontract_build_level_:
+      handle_OPT_fcontract_build_level_ (arg);
+      break;
+
+    case OPT_fcontract_assumption_mode_:
+      handle_OPT_fcontract_assumption_mode_ (arg);
+      break;
+
+    case OPT_fcontract_continuation_mode_:
+      handle_OPT_fcontract_continuation_mode_ (arg);
+      break;
+
+    case OPT_fcontract_role_:
+      handle_OPT_fcontract_role_ (arg);
+      break;
+
+    case OPT_fcontract_semantic_:
+      handle_OPT_fcontract_semantic_ (arg);
+      break;
+
+    default:
+      handled_p = false;
+      break;
+    }
+  if (handled_p)
+    return handled_p;
+
   return c_common_handle_option (scode, arg, value, kind, loc, handlers);
 }