Bug Summary

File:.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow/tensorflow/python/util/util.cc
Warning:line 538, column 20
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name util.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/tensorflow/csa-scan,ctu-index-name=/tmp/pyrefcon/tensorflow/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/tensorflow/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/pyrefcon/.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -iquote . -iquote bazel-out/k8-opt/bin -iquote external/com_google_absl -iquote bazel-out/k8-opt/bin/external/com_google_absl -iquote external/nsync -iquote bazel-out/k8-opt/bin/external/nsync -iquote external/eigen_archive -iquote bazel-out/k8-opt/bin/external/eigen_archive -iquote external/gif -iquote bazel-out/k8-opt/bin/external/gif -iquote external/libjpeg_turbo -iquote bazel-out/k8-opt/bin/external/libjpeg_turbo -iquote external/com_google_protobuf -iquote bazel-out/k8-opt/bin/external/com_google_protobuf -iquote external/com_googlesource_code_re2 -iquote bazel-out/k8-opt/bin/external/com_googlesource_code_re2 -iquote external/farmhash_archive -iquote bazel-out/k8-opt/bin/external/farmhash_archive -iquote external/fft2d -iquote bazel-out/k8-opt/bin/external/fft2d -iquote external/highwayhash -iquote bazel-out/k8-opt/bin/external/highwayhash -iquote external/zlib -iquote bazel-out/k8-opt/bin/external/zlib -iquote external/local_config_python -iquote bazel-out/k8-opt/bin/external/local_config_python -iquote external/double_conversion -iquote bazel-out/k8-opt/bin/external/double_conversion -iquote external/snappy -iquote bazel-out/k8-opt/bin/external/snappy -iquote external/llvm-project -iquote bazel-out/k8-opt/bin/external/llvm-project -iquote external/llvm_terminfo -iquote bazel-out/k8-opt/bin/external/llvm_terminfo -iquote external/llvm_zlib -iquote bazel-out/k8-opt/bin/external/llvm_zlib -iquote external/curl -iquote bazel-out/k8-opt/bin/external/curl -iquote external/boringssl -iquote bazel-out/k8-opt/bin/external/boringssl -iquote external/jsoncpp_git -iquote bazel-out/k8-opt/bin/external/jsoncpp_git -iquote external/local_config_cuda -iquote bazel-out/k8-opt/bin/external/local_config_cuda -iquote external/local_config_rocm -iquote bazel-out/k8-opt/bin/external/local_config_rocm -iquote external/local_config_tensorrt -iquote bazel-out/k8-opt/bin/external/local_config_tensorrt -iquote external/mkl_dnn_v1 -iquote bazel-out/k8-opt/bin/external/mkl_dnn_v1 -iquote external/com_github_grpc_grpc -iquote bazel-out/k8-opt/bin/external/com_github_grpc_grpc -iquote external/upb -iquote bazel-out/k8-opt/bin/external/upb -iquote external/lmdb -iquote bazel-out/k8-opt/bin/external/lmdb -iquote external/png -iquote bazel-out/k8-opt/bin/external/png -iquote external/gemmlowp -iquote bazel-out/k8-opt/bin/external/gemmlowp -iquote external/icu -iquote bazel-out/k8-opt/bin/external/icu -iquote external/org_sqlite -iquote bazel-out/k8-opt/bin/external/org_sqlite -isystem external/nsync/public -isystem bazel-out/k8-opt/bin/external/nsync/public -isystem third_party/eigen3/mkl_include -isystem bazel-out/k8-opt/bin/third_party/eigen3/mkl_include -isystem external/eigen_archive -isystem bazel-out/k8-opt/bin/external/eigen_archive -isystem external/gif -isystem bazel-out/k8-opt/bin/external/gif -isystem external/com_google_protobuf/src -isystem bazel-out/k8-opt/bin/external/com_google_protobuf/src -isystem external/farmhash_archive/src -isystem bazel-out/k8-opt/bin/external/farmhash_archive/src -isystem external/zlib -isystem bazel-out/k8-opt/bin/external/zlib -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -isystem external/double_conversion -isystem bazel-out/k8-opt/bin/external/double_conversion -isystem external/llvm-project/llvm/include -isystem bazel-out/k8-opt/bin/external/llvm-project/llvm/include -isystem external/llvm-project/mlir/include -isystem bazel-out/k8-opt/bin/external/llvm-project/mlir/include -isystem external/curl/include -isystem bazel-out/k8-opt/bin/external/curl/include -isystem external/boringssl/src/include -isystem bazel-out/k8-opt/bin/external/boringssl/src/include -isystem external/jsoncpp_git/include -isystem bazel-out/k8-opt/bin/external/jsoncpp_git/include -isystem external/local_config_cuda/cuda -isystem bazel-out/k8-opt/bin/external/local_config_cuda/cuda -isystem external/local_config_cuda/cuda/cuda/include -isystem bazel-out/k8-opt/bin/external/local_config_cuda/cuda/cuda/include -isystem external/local_config_rocm/rocm -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm -isystem external/local_config_rocm/rocm/rocm/include -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include -isystem external/local_config_rocm/rocm/rocm/include/rocrand -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include/rocrand -isystem external/local_config_rocm/rocm/rocm/include/roctracer -isystem bazel-out/k8-opt/bin/external/local_config_rocm/rocm/rocm/include/roctracer -isystem tensorflow/compiler/mlir/tensorflow/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/tensorflow/include -isystem tensorflow/compiler/mlir/hlo/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/include -isystem tensorflow/compiler/mlir/xla/include -isystem bazel-out/k8-opt/bin/tensorflow/compiler/mlir/xla/include -isystem external/mkl_dnn_v1/include -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/include -isystem external/mkl_dnn_v1/src -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src -isystem external/mkl_dnn_v1/src/common -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/common -isystem external/mkl_dnn_v1/src/common/ittnotify -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/common/ittnotify -isystem external/mkl_dnn_v1/src/cpu -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu -isystem external/mkl_dnn_v1/src/cpu/gemm -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu/gemm -isystem external/mkl_dnn_v1/src/cpu/x64/xbyak -isystem bazel-out/k8-opt/bin/external/mkl_dnn_v1/src/cpu/x64/xbyak -isystem external/com_github_grpc_grpc/include -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/include -isystem external/com_github_grpc_grpc/src/core/ext/upb-generated -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/src/core/ext/upb-generated -isystem external/com_github_grpc_grpc/third_party/address_sorting/include -isystem bazel-out/k8-opt/bin/external/com_github_grpc_grpc/third_party/address_sorting/include -isystem external/png -isystem bazel-out/k8-opt/bin/external/png -isystem external/icu/icu4c/source/common -isystem bazel-out/k8-opt/bin/external/icu/icu4c/source/common -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=1 -D NDEBUG -D SQLITE_OMIT_DEPRECATED -D EIGEN_ALTIVEC_USE_CUSTOM_PACK=0 -D GRPC_ARES=0 -D TENSORFLOW_USE_CUSTOM_CONTRACTION_KERNEL -D TENSORFLOW_USE_MKLDNN_CONTRACTION_KERNEL -D HAVE_SYS_UIO_H -D TF_USE_SNAPPY -D CURL_STATICLIB -D EIGEN_MPL2_ONLY -D EIGEN_MAX_ALIGN_BYTES=64 -D LLVM_ON_UNIX=1 -D HAVE_BACKTRACE=1 -D BACKTRACE_HEADER=<execinfo.h> -D LTDL_SHLIB_EXT=".so" -D LLVM_PLUGIN_EXT=".so" -D LLVM_ENABLE_THREADS=1 -D HAVE_SYSEXITS_H=1 -D HAVE_UNISTD_H=1 -D HAVE_STRERROR_R=1 -D HAVE_LIBPTHREAD=1 -D HAVE_PTHREAD_GETNAME_NP=1 -D HAVE_PTHREAD_SETNAME_NP=1 -D HAVE_PTHREAD_GETSPECIFIC=1 -D HAVE_REGISTER_FRAME=1 -D HAVE_DEREGISTER_FRAME=1 -D _GNU_SOURCE -D HAVE_LINK_H=1 -D HAVE_LSEEK64=1 -D HAVE_MALLINFO=1 -D HAVE_POSIX_FALLOCATE=1 -D HAVE_SBRK=1 -D HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1 -D LLVM_NATIVE_ARCH="X86" -D LLVM_NATIVE_ASMPARSER=LLVMInitializeX86AsmParser -D LLVM_NATIVE_ASMPRINTER=LLVMInitializeX86AsmPrinter -D LLVM_NATIVE_DISASSEMBLER=LLVMInitializeX86Disassembler -D LLVM_NATIVE_TARGET=LLVMInitializeX86Target -D LLVM_NATIVE_TARGETINFO=LLVMInitializeX86TargetInfo -D LLVM_NATIVE_TARGETMC=LLVMInitializeX86TargetMC -D LLVM_NATIVE_TARGETMCA=LLVMInitializeX86TargetMCA -D LLVM_HOST_TRIPLE="x86_64-unknown-linux-gnu" -D LLVM_DEFAULT_TARGET_TRIPLE="x86_64-unknown-linux-gnu" -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinDialectIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinLocationAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinTypeInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/BuiltinTypesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CallOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CastOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/InferTypeOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/OpAsmInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/RegionKindInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SideEffectInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SubElementInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SymbolInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TensorEncodingIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ControlFlowInterfacesIncGen -I bazel-out/k8-opt/bin/external/local_config_cuda/cuda/_virtual_includes/cuda_headers_virtual -I bazel-out/k8-opt/bin/external/local_config_tensorrt/_virtual_includes/tensorrt_headers -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ParserTokenKinds -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/DerivedAttributeOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LoopLikeInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/StandardOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/VectorInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AffineMemoryOpInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/AffineOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/CopyOpInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MemRefBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MemRefOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TensorOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ViewLikeInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgInterfacesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgStructuredOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LinalgOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MathBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MathOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SCFIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/SCFPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TilingInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ComplexBaseIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ComplexOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLTypesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/PDLInterpOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ConversionPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/TransformsPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/QuantOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/QuantPassIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/MLIRShapeCanonicalizationIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/ShapeOpsIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMDialectAttributesIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMDialectInterfaceIncGen -I bazel-out/k8-opt/bin/external/llvm-project/mlir/_virtual_includes/LLVMOpsIncGen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/canonicalize_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/chlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_base_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/hlo_ops_pattern_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_ops_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/lhlo_ops_structs_inc_gen -I bazel-out/k8-opt/bin/tensorflow/compiler/mlir/hlo/_virtual_includes/chlo_legalize_to_hlo_inc_gen -D AUTOLOAD_DYNAMIC_KERNELS -D __DATE__="redacted" -D __TIMESTAMP__="redacted" -D __TIME__="redacted" -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -Wno-builtin-macro-redefined -w -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/home/pyrefcon/.cache/bazel/_bazel_alan/39be661231df2a680c9b74265384c13c/execroot/org_tensorflow -ferror-limit 19 -stack-protector 1 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/tensorflow/csa-scan/reports -x c++ tensorflow/python/util/util.cc

tensorflow/python/util/util.cc

1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15#include "tensorflow/python/util/util.h"
16
17#include <functional>
18#include <memory>
19#include <unordered_map>
20#include <vector>
21
22#include "absl/memory/memory.h"
23#include "tensorflow/core/lib/gtl/map_util.h"
24#include "tensorflow/core/lib/strings/strcat.h"
25#include "tensorflow/core/platform/logging.h"
26#include "tensorflow/core/platform/mutex.h"
27#include "tensorflow/python/lib/core/safe_pyobject_ptr.h"
28
29namespace tensorflow {
30namespace swig {
31
32namespace {
33string PyObjectToString(PyObject* o);
34} // namespace
35
36std::unordered_map<string, PyObject*>* RegisteredPyObjectMap() {
37 static auto* m = new std::unordered_map<string, PyObject*>();
38 return m;
39}
40
41PyObject* GetRegisteredPyObject(const string& name) {
42 const auto* m = RegisteredPyObjectMap();
43 auto it = m->find(name);
44 if (it == m->end()) {
45 PyErr_SetString(PyExc_TypeError,
46 tensorflow::strings::StrCat("No object with name ", name,
47 " has been registered.")
48 .c_str());
49 return nullptr;
50 }
51 return it->second;
52}
53
54PyObject* RegisterType(PyObject* type_name, PyObject* type) {
55 if (!PyType_Check(type)((((((PyObject*)(type))->ob_type))->tp_flags & ((1UL
<< 31))) != 0)
) {
56 PyErr_SetString(PyExc_TypeError,
57 tensorflow::strings::StrCat("Expecting a type, got ",
58 Py_TYPE(type)(((PyObject*)(type))->ob_type)->tp_name)
59 .c_str());
60 return nullptr;
61 }
62 return RegisterPyObject(type_name, type);
63}
64
65PyObject* RegisterPyObject(PyObject* name, PyObject* value) {
66 string key;
67 if (PyBytes_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL
<< 27))) != 0)
) {
68 key = PyBytes_AsString(name);
69#if PY_MAJOR_VERSION3 >= 3
70 } else if (PyUnicode_Check(name)((((((PyObject*)(name))->ob_type))->tp_flags & ((1UL
<< 28))) != 0)
) {
71 key = PyUnicode_AsUTF8(name);
72#endif
73 } else {
74 PyErr_SetString(PyExc_TypeError, tensorflow::strings::StrCat(
75 "Expected name to be a str, got",
76 PyObjectToString(name))
77 .c_str());
78 return nullptr;
79 }
80
81 auto* m = RegisteredPyObjectMap();
82 if (m->find(key) != m->end()) {
83 PyErr_SetString(PyExc_TypeError, tensorflow::strings::StrCat(
84 "Value already registered for ", key)
85 .c_str());
86 return nullptr;
87 }
88
89 Py_INCREF(value)_Py_INCREF(((PyObject*)(value)));
90 m->emplace(key, value);
91
92 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
93}
94
95namespace {
96const int kMaxItemsInCache = 1024;
97
98bool WarnedThatSetIsNotSequence = false;
99
100bool IsString(PyObject* o) {
101 return PyBytes_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
27))) != 0)
||
102#if PY_MAJOR_VERSION3 < 3
103 PyString_Check(o) ||
104#endif
105 PyUnicode_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
;
106}
107
108// Equivalent to Python's 'o.__class__.__name__'
109// Note that '__class__' attribute is set only in new-style classes.
110// A lot of tensorflow code uses __class__ without checks, so it seems like
111// we only support new-style classes.
112StringPiece GetClassName(PyObject* o) {
113 // __class__ is equivalent to type() for new style classes.
114 // type() is equivalent to PyObject_Type()
115 // (https://docs.python.org/3.5/c-api/object.html#c.PyObject_Type)
116 // PyObject_Type() is equivalent to o->ob_type except for Py_INCREF, which
117 // we don't need here.
118 PyTypeObject* type = o->ob_type;
119
120 // __name__ is the value of `tp_name` after the last '.'
121 // (https://docs.python.org/2/c-api/typeobj.html#c.PyTypeObject.tp_name)
122 StringPiece name(type->tp_name);
123 size_t pos = name.rfind('.');
124 if (pos != StringPiece::npos) {
125 name.remove_prefix(pos + 1);
126 }
127 return name;
128}
129
130string PyObjectToString(PyObject* o) {
131 if (o == nullptr) {
132 return "<null object>";
133 }
134 PyObject* str = PyObject_Str(o);
135 if (str) {
136#if PY_MAJOR_VERSION3 < 3
137 string s(PyString_AS_STRING(str));
138#else
139 string s(PyUnicode_AsUTF8(str));
140#endif
141 Py_DECREF(str)_Py_DECREF(((PyObject*)(str)));
142 return tensorflow::strings::StrCat("type=", GetClassName(o), " str=", s);
143 } else {
144 return "<failed to execute str() on object>";
145 }
146}
147
148class CachedTypeCheck {
149 public:
150 explicit CachedTypeCheck(std::function<int(PyObject*)> ternary_predicate)
151 : ternary_predicate_(std::move(ternary_predicate)) {}
152
153 ~CachedTypeCheck() {
154 mutex_lock l(type_to_sequence_map_mu_);
155 for (const auto& pair : type_to_sequence_map_) {
156 Py_DECREF(pair.first)_Py_DECREF(((PyObject*)(pair.first)));
157 }
158 }
159
160 // Caches successful executions of the one-argument (PyObject*) callable
161 // "ternary_predicate" based on the type of "o". -1 from the callable
162 // indicates an unsuccessful check (not cached), 0 indicates that "o"'s type
163 // does not match the predicate, and 1 indicates that it does. Used to avoid
164 // calling back into Python for expensive isinstance checks.
165 int CachedLookup(PyObject* o) {
166 // Try not to return to Python - see if the type has already been seen
167 // before.
168
169 auto* type = Py_TYPE(o)(((PyObject*)(o))->ob_type);
170
171 {
172 tf_shared_lock l(type_to_sequence_map_mu_);
173 auto it = type_to_sequence_map_.find(type);
174 if (it != type_to_sequence_map_.end()) {
175 return it->second;
176 }
177 }
178
179 int check_result = ternary_predicate_(o);
180
181 if (check_result == -1) {
182 return -1; // Type check error, not cached.
183 }
184
185 // NOTE: This is never decref'd as long as the object lives, which is likely
186 // forever, but we don't want the type to get deleted as long as it is in
187 // the map. This should not be too much of a leak, as there should only be a
188 // relatively small number of types in the map, and an even smaller number
189 // that are eligible for decref. As a precaution, we limit the size of the
190 // map to 1024.
191 {
192 mutex_lock l(type_to_sequence_map_mu_);
193 if (type_to_sequence_map_.size() < kMaxItemsInCache) {
194 Py_INCREF(type)_Py_INCREF(((PyObject*)(type)));
195 auto insert_result = type_to_sequence_map_.insert({type, check_result});
196 if (!insert_result.second) {
197 // The type was added to the cache by a concurrent thread after we
198 // looked it up above.
199 Py_DECREF(type)_Py_DECREF(((PyObject*)(type)));
200 }
201 }
202 }
203
204 return check_result;
205 }
206
207 private:
208 std::function<int(PyObject*)> ternary_predicate_;
209 mutex type_to_sequence_map_mu_;
210 std::unordered_map<PyTypeObject*, bool> type_to_sequence_map_
211 TF_GUARDED_BY(type_to_sequence_map_mu_)__attribute__((guarded_by(type_to_sequence_map_mu_)));
212};
213
214// Returns 1 if 'obj' is an instance of 'type_name'
215// Returns 0 otherwise.
216// Returns -1 if an error occurred (e.g., if 'type_name' is not registered.)
217int IsInstanceOfRegisteredType(PyObject* obj, const char* type_name) {
218 PyObject* type_obj = GetRegisteredPyObject(type_name);
219 if (TF_PREDICT_FALSE(type_obj == nullptr)(__builtin_expect(type_obj == nullptr, 0))) {
220 PyErr_SetString(PyExc_RuntimeError,
221 tensorflow::strings::StrCat(
222 type_name,
223 " type has not been set. "
224 "Please register the type with the identifier \"",
225 type_name, "\" using RegisterType.")
226 .c_str());
227 return -1;
228 }
229 return PyObject_IsInstance(obj, type_obj);
230}
231
232// Returns 1 if `o` is considered a mapping for the purposes of Flatten().
233// Returns 0 otherwise.
234// Returns -1 if an error occurred.
235int IsMappingHelper(PyObject* o) {
236 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
237 return IsInstanceOfRegisteredType(to_check, "Mapping");
238 });
239 if (PyDict_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
29))) != 0)
) return true;
240 return check_cache->CachedLookup(o);
241}
242
243// Returns 1 if `o` is considered a mutable mapping for the purposes of
244// Flatten(). Returns 0 otherwise. Returns -1 if an error occurred.
245int IsMutableMappingHelper(PyObject* o) {
246 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
247 return IsInstanceOfRegisteredType(to_check, "MutableMapping");
248 });
249 if (PyDict_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
29))) != 0)
) return true;
250 return check_cache->CachedLookup(o);
251}
252
253// Returns 1 if `o` is considered a mapping view for the purposes of Flatten().
254// Returns 0 otherwise.
255// Returns -1 if an error occurred.
256int IsMappingViewHelper(PyObject* o) {
257 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
258 return IsInstanceOfRegisteredType(to_check, "MappingView");
259 });
260 return check_cache->CachedLookup(o);
261}
262
263// Returns 1 if `o` is considered an object proxy
264// Returns 0 otherwise.
265// Returns -1 if an error occurred.
266int IsObjectProxy(PyObject* o) {
267 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
268 return IsInstanceOfRegisteredType(to_check, "ObjectProxy");
269 });
270 return check_cache->CachedLookup(o);
271}
272
273// Returns 1 if `o` is an instance of attrs-decorated class.
274// Returns 0 otherwise.
275int IsAttrsHelper(PyObject* o) {
276 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
277 Safe_PyObjectPtr cls(PyObject_GetAttrString(to_check, "__class__"));
278 if (cls) {
279 return PyObject_HasAttrString(cls.get(), "__attrs_attrs__");
280 }
281
282 // PyObject_GetAttrString returns null on error
283 PyErr_Clear();
284 return 0;
285 });
286 return check_cache->CachedLookup(o);
287}
288
289// Returns 1 if `o` is an object of type IndexedSlices.
290// Returns 0 otherwise.
291// Returns -1 if an error occurred.
292int IsIndexedSlicesHelper(PyObject* o) {
293 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
294 return IsInstanceOfRegisteredType(to_check, "IndexedSlices");
295 });
296 return check_cache->CachedLookup(o);
297}
298
299// Returns 1 if `o` is a Tensor.
300// Returns 0 otherwise.
301// Returns -1 if an error occurred.
302int IsTensorHelper(PyObject* o) {
303 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
304 return IsInstanceOfRegisteredType(to_check, "Tensor");
305 });
306 return check_cache->CachedLookup(o);
307}
308
309// Returns 1 if `o` is a TensorSpec.
310// Returns 0 otherwise.
311// Returns -1 if an error occurred.
312int IsTensorSpecHelper(PyObject* o) {
313 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
314 return IsInstanceOfRegisteredType(to_check, "TensorSpec");
315 });
316 return check_cache->CachedLookup(o);
317}
318
319// Returns 1 if `o` is an EagerTensor.
320// Returns 0 otherwise.
321// Returns -1 if an error occurred.
322int IsEagerTensorHelper(PyObject* o) {
323 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
324 return IsInstanceOfRegisteredType(to_check, "EagerTensor");
325 });
326 return check_cache->CachedLookup(o);
327}
328
329// Returns 1 if `o` is a ResourceVariable.
330// Returns 0 otherwise.
331// Returns -1 if an error occurred.
332int IsResourceVariableHelper(PyObject* o) {
333 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
334 return IsInstanceOfRegisteredType(to_check, "ResourceVariable");
335 });
336 return check_cache->CachedLookup(o);
337}
338
339// Returns 1 if `o` is a OwnedIterator.
340// Returns 0 otherwise.
341// Returns -1 if an error occurred.
342int IsOwnedIteratorHelper(PyObject* o) {
343 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
344 return IsInstanceOfRegisteredType(to_check, "OwnedIterator");
345 });
346 return check_cache->CachedLookup(o);
347}
348
349// Returns 1 if `o` is a ResourceVariable.
350// Returns 0 otherwise.
351// Returns -1 if an error occurred.
352int IsVariableHelper(PyObject* o) {
353 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
354 return IsInstanceOfRegisteredType(to_check, "Variable");
355 });
356 return check_cache->CachedLookup(o);
357}
358
359// Returns 1 if `o` is considered a sequence for the purposes of Flatten().
360// Returns 0 otherwise.
361// Returns -1 if an error occurred.
362int IsSequenceHelper(PyObject* o) {
363 // We treat dicts and other mappings as special cases of sequences.
364 if (IsMappingHelper(o)) return true;
365 if (IsMappingViewHelper(o)) return true;
366 if (IsAttrsHelper(o)) return true;
367 if (PySet_Check(o)((((PyObject*)(o))->ob_type) == &PySet_Type || PyType_IsSubtype
((((PyObject*)(o))->ob_type), &PySet_Type))
&& !WarnedThatSetIsNotSequence) {
368 LOG(WARNING)::tensorflow::internal::LogMessage("tensorflow/python/util/util.cc"
, 368, ::tensorflow::WARNING)
<< "Sets are not currently considered sequences, "
369 "but this may change in the future, "
370 "so consider avoiding using them.";
371 WarnedThatSetIsNotSequence = true;
372 }
373 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
374 int is_instance = IsInstanceOfRegisteredType(to_check, "Sequence");
375
376 // Don't cache a failed is_instance check.
377 if (is_instance == -1) return -1;
378
379 return static_cast<int>(is_instance != 0 && !IsString(to_check));
380 });
381 return check_cache->CachedLookup(o);
382}
383
384// Returns 1 if `o`'s class has a `__tf_dispatch__` attribute.
385// Returns 0 otherwise.
386int IsDispatchableHelper(PyObject* o) {
387 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
388 return PyObject_HasAttrString(
389 reinterpret_cast<PyObject*>(to_check->ob_type), "__tf_dispatch__");
390 });
391 return check_cache->CachedLookup(o);
392}
393
394// ValueIterator interface
395class ValueIterator {
396 public:
397 virtual ~ValueIterator() {}
398 virtual Safe_PyObjectPtr next() = 0;
399
400 bool valid() const { return is_valid_; }
401
402 protected:
403 void invalidate() { is_valid_ = false; }
404
405 private:
406 bool is_valid_ = true;
407};
408
409using ValueIteratorPtr = std::unique_ptr<ValueIterator>;
410
411// Iterate through dictionaries in a deterministic order by sorting the
412// keys. Notice this means that we ignore the original order of
413// `OrderedDict` instances. This is intentional, to avoid potential
414// bugs caused by mixing ordered and plain dicts (e.g., flattening
415// a dict but using a corresponding `OrderedDict` to pack it back).
416class DictValueIterator : public ValueIterator {
417 public:
418 explicit DictValueIterator(PyObject* dict)
419 : dict_(dict), keys_(PyDict_Keys(dict)) {
420 if (PyList_Sort(keys_.get()) == -1) {
421 invalidate();
422 } else {
423 iter_.reset(PyObject_GetIter(keys_.get()));
424 }
425 }
426
427 Safe_PyObjectPtr next() override {
428 Safe_PyObjectPtr result;
429 Safe_PyObjectPtr key(PyIter_Next(iter_.get()));
430 if (key) {
431 // PyDict_GetItem returns a borrowed reference.
432 PyObject* elem = PyDict_GetItem(dict_, key.get());
433 if (elem) {
434 Py_INCREF(elem)_Py_INCREF(((PyObject*)(elem)));
435 result.reset(elem);
436 } else {
437 PyErr_SetString(PyExc_RuntimeError,
438 "Dictionary was modified during iteration over it");
439 }
440 }
441 return result;
442 }
443
444 private:
445 PyObject* dict_;
446 Safe_PyObjectPtr keys_;
447 Safe_PyObjectPtr iter_;
448};
449
450// Iterate over mapping objects by sorting the keys first
451class MappingValueIterator : public ValueIterator {
452 public:
453 explicit MappingValueIterator(PyObject* mapping)
454 : mapping_(mapping), keys_(MappingKeys(mapping)) {
455 if (!keys_ || PyList_Sort(keys_.get()) == -1) {
456 invalidate();
457 } else {
458 iter_.reset(PyObject_GetIter(keys_.get()));
459 }
460 }
461
462 Safe_PyObjectPtr next() override {
463 Safe_PyObjectPtr result;
464 Safe_PyObjectPtr key(PyIter_Next(iter_.get()));
465 if (key) {
466 // Unlike PyDict_GetItem, PyObject_GetItem returns a new reference.
467 PyObject* elem = PyObject_GetItem(mapping_, key.get());
468 if (elem) {
469 result.reset(elem);
470 } else {
471 PyErr_SetString(PyExc_RuntimeError,
472 "Mapping was modified during iteration over it");
473 }
474 }
475 return result;
476 }
477
478 private:
479 PyObject* mapping_;
480 Safe_PyObjectPtr keys_;
481 Safe_PyObjectPtr iter_;
482};
483
484// Iterate over a sequence, by index.
485class SequenceValueIterator : public ValueIterator {
486 public:
487 explicit SequenceValueIterator(PyObject* iterable)
488 : seq_(PySequence_Fast(iterable, "")),
489 size_(seq_.get() ? PySequence_Fast_GET_SIZE(seq_.get())(((((((PyObject*)(seq_.get()))->ob_type))->tp_flags &
((1UL << 25))) != 0) ? ((static_cast<void> (0)),
(((PyVarObject*)(seq_.get()))->ob_size)) : (((PyVarObject
*)(((static_cast<void> (0)), (PyTupleObject *)(seq_.get
()))))->ob_size))
: 0),
490 index_(0) {}
491
492 Safe_PyObjectPtr next() override {
493 Safe_PyObjectPtr result;
494 if (index_ < size_) {
495 // PySequence_Fast_GET_ITEM returns a borrowed reference.
496 PyObject* elem = PySequence_Fast_GET_ITEM(seq_.get(), index_)(((((((PyObject*)(seq_.get()))->ob_type))->tp_flags &
((1UL << 25))) != 0) ? (((PyListObject *)(seq_.get()))
->ob_item[index_]) : (((static_cast<void> (0)), (PyTupleObject
*)(seq_.get()))->ob_item[index_]))
;
497 ++index_;
498 if (elem) {
499 Py_INCREF(elem)_Py_INCREF(((PyObject*)(elem)));
500 result.reset(elem);
501 }
502 }
503
504 return result;
505 }
506
507 private:
508 Safe_PyObjectPtr seq_;
509 const Py_ssize_t size_;
510 Py_ssize_t index_;
511};
512
513// Iterator that just returns a single python object.
514class SingleValueIterator : public ValueIterator {
515 public:
516 explicit SingleValueIterator(PyObject* x) : x_(x) { Py_INCREF(x)_Py_INCREF(((PyObject*)(x))); }
517
518 Safe_PyObjectPtr next() override { return std::move(x_); }
519
520 private:
521 Safe_PyObjectPtr x_;
522};
523
524// Returns nullptr (to raise an exception) when next() is called. Caller
525// should have already called PyErr_SetString.
526class ErrorValueIterator : public ValueIterator {
527 public:
528 ErrorValueIterator() {}
529 Safe_PyObjectPtr next() override { return nullptr; }
530};
531
532class AttrsValueIterator : public ValueIterator {
533 public:
534 explicit AttrsValueIterator(PyObject* nested) : nested_(nested) {
535 Py_INCREF(nested)_Py_INCREF(((PyObject*)(nested)));
536 cls_.reset(PyObject_GetAttrString(nested_.get(), "__class__"));
537 if (cls_) {
18
Assuming the condition is true
19
Taking true branch
538 attrs_.reset(PyObject_GetAttrString(cls_.get(), "__attrs_attrs__"));
20
Calling 'PyObject_GetAttrString'
22
Returning from 'PyObject_GetAttrString'
23
PyObject ownership leak with reference count of 1
539 if (attrs_) {
540 iter_.reset(PyObject_GetIter(attrs_.get()));
541 }
542 }
543 if (!iter_ || PyErr_Occurred()) invalidate();
544 }
545
546 Safe_PyObjectPtr next() override {
547 Safe_PyObjectPtr result;
548 Safe_PyObjectPtr item(PyIter_Next(iter_.get()));
549 if (item) {
550 Safe_PyObjectPtr name(PyObject_GetAttrString(item.get(), "name"));
551 result.reset(PyObject_GetAttr(nested_.get(), name.get()));
552 }
553
554 return result;
555 }
556
557 private:
558 Safe_PyObjectPtr nested_;
559 Safe_PyObjectPtr cls_;
560 Safe_PyObjectPtr attrs_;
561 Safe_PyObjectPtr iter_;
562};
563
564bool IsSparseTensorValueType(PyObject* o) {
565 PyObject* sparse_tensor_value_type =
566 GetRegisteredPyObject("SparseTensorValue");
567 if (TF_PREDICT_FALSE(sparse_tensor_value_type == nullptr)(__builtin_expect(sparse_tensor_value_type == nullptr, 0))) {
568 return false;
569 }
570
571 return PyObject_TypeCheck(((((PyObject*)(o))->ob_type) == (reinterpret_cast<PyTypeObject
*>(sparse_tensor_value_type)) || PyType_IsSubtype((((PyObject
*)(o))->ob_type), (reinterpret_cast<PyTypeObject*>(sparse_tensor_value_type
))))
572 o, reinterpret_cast<PyTypeObject*>(sparse_tensor_value_type))((((PyObject*)(o))->ob_type) == (reinterpret_cast<PyTypeObject
*>(sparse_tensor_value_type)) || PyType_IsSubtype((((PyObject
*)(o))->ob_type), (reinterpret_cast<PyTypeObject*>(sparse_tensor_value_type
))))
== 1;
573}
574
575// Returns 1 if `o` is an instance of CompositeTensor.
576// Returns 0 otherwise.
577// Returns -1 if an error occurred.
578bool IsCompositeTensorHelper(PyObject* o) {
579 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
580 return IsInstanceOfRegisteredType(to_check, "CompositeTensor");
581 });
582 return check_cache->CachedLookup(o);
583}
584
585// Returns 1 if `o` is an instance of TypeSpec, but is not TensorSpec or
586// VariableSpec.
587// Returns 0 otherwise.
588// Returns -1 if an error occurred.
589bool IsTypeSpecHelper(PyObject* o) {
590 static auto* const check_cache = new CachedTypeCheck([](PyObject* to_check) {
591 int is_type_spec = IsInstanceOfRegisteredType(to_check, "TypeSpec");
592 int is_dense_spec = (IsInstanceOfRegisteredType(to_check, "TensorSpec") ||
593 IsInstanceOfRegisteredType(to_check, "VariableSpec"));
594 if ((is_type_spec == -1) || (is_dense_spec == -1)) return -1;
595 return static_cast<int>(is_type_spec && !is_dense_spec);
596 });
597 return check_cache->CachedLookup(o);
598}
599
600// Returns 1 if `o` is a (non-string) sequence or CompositeTensor or
601// (non-TensorSpec and non-VariableSpec) TypeSpec.
602// Returns 0 otherwise.
603// Returns -1 if an error occurred.
604int IsSequenceOrCompositeHelper(PyObject* o) {
605 int is_sequence = IsSequenceHelper(o);
606 int is_composite = IsCompositeTensorHelper(o);
607 int is_type_spec = IsTypeSpecHelper(o);
608 if ((is_sequence == -1) || (is_composite == -1) || (is_type_spec == -1)) {
609 return -1;
610 }
611 return is_sequence || is_composite || is_type_spec;
612}
613
614int IsSequenceForDataHelper(PyObject* o) {
615 return IsSequenceHelper(o) == 1 && !PyList_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
25))) != 0)
&&
616 !IsSparseTensorValueType(o);
617}
618
619ValueIteratorPtr GetValueIterator(PyObject* nested) {
620 if (PyDict_Check(nested)((((((PyObject*)(nested))->ob_type))->tp_flags & ((
1UL << 29))) != 0)
) {
621 return absl::make_unique<DictValueIterator>(nested);
622 } else if (IsMappingHelper(nested)) {
623 return absl::make_unique<MappingValueIterator>(nested);
624 } else if (IsAttrsHelper(nested)) {
625 return absl::make_unique<AttrsValueIterator>(nested);
626 } else {
627 return absl::make_unique<SequenceValueIterator>(nested);
628 }
629}
630
631// Similar to above, just specialized for the functions in the data package.
632ValueIteratorPtr GetValueIteratorForData(PyObject* nested) {
633 if (PyDict_Check(nested)((((((PyObject*)(nested))->ob_type))->tp_flags & ((
1UL << 29))) != 0)
) {
10
Assuming the condition is false
11
Taking false branch
634 return absl::make_unique<DictValueIterator>(nested);
635 } else if (IsMappingHelper(nested)) {
12
Assuming the condition is false
13
Taking false branch
636 return absl::make_unique<MappingValueIterator>(nested);
637 } else if (IsAttrsHelper(nested)) {
14
Assuming the condition is true
15
Taking true branch
638 return absl::make_unique<AttrsValueIterator>(nested);
16
Calling 'make_unique<tensorflow::swig::(anonymous namespace)::AttrsValueIterator, _object *&>'
639 } else if (IsSparseTensorValueType(nested)) {
640 return absl::make_unique<SingleValueIterator>(nested);
641 } else {
642 return absl::make_unique<SequenceValueIterator>(nested);
643 }
644}
645
646// Similar to GetValueIterator above, but expands CompositeTensor and TypeSpec.
647ValueIteratorPtr GetValueIteratorForComposite(PyObject* nested) {
648 if (IsCompositeTensor(nested)) {
649 Safe_PyObjectPtr spec(PyObject_GetAttrString(nested, "_type_spec"));
650 if (PyErr_Occurred() || !spec) {
651 return absl::make_unique<ErrorValueIterator>();
652 }
653
654 static char to_components[] = "_to_components";
655 static char argspec[] = "(O)";
656 Safe_PyObjectPtr components(
657 PyObject_CallMethod(spec.get(), to_components, argspec, nested));
658 if (PyErr_Occurred() || components == nullptr) {
659 return absl::make_unique<ErrorValueIterator>();
660 }
661 return absl::make_unique<SingleValueIterator>(components.get());
662 }
663
664 if (IsTypeSpec(nested)) {
665 Safe_PyObjectPtr specs(PyObject_GetAttrString(nested, "_component_specs"));
666 if (PyErr_Occurred() || specs == nullptr) {
667 return absl::make_unique<ErrorValueIterator>();
668 }
669 return absl::make_unique<SingleValueIterator>(specs.get());
670 }
671
672 return GetValueIterator(nested);
673}
674
675bool FlattenHelper(
676 PyObject* nested, PyObject* list,
677 const std::function<int(PyObject*)>& is_sequence_helper,
678 const std::function<ValueIteratorPtr(PyObject*)>& value_iterator_getter) {
679 // if nested is not a sequence, append itself and exit
680 int is_seq = is_sequence_helper(nested);
681 if (is_seq == -1) return false;
2
Taking false branch
682 if (!is_seq
2.1
'is_seq' is 1
2.1
'is_seq' is 1
2.1
'is_seq' is 1
2.1
'is_seq' is 1
2.1
'is_seq' is 1
) {
3
Taking false branch
683 return PyList_Append(list, nested) != -1;
684 }
685
686 ValueIteratorPtr iter = value_iterator_getter(nested);
4
Calling 'function::operator()'
687 if (!iter->valid()) return false;
688
689 for (Safe_PyObjectPtr item = iter->next(); item; item = iter->next()) {
690 if (Py_EnterRecursiveCall(" in flatten")((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit
) && _Py_CheckRecursiveCall(" in flatten"))
) {
691 return false;
692 }
693 const bool success = FlattenHelper(item.get(), list, is_sequence_helper,
694 value_iterator_getter);
695 Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit
) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit
) >> 2))))) PyThreadState_Get()->overflowed = 0; } while
(0)
;
696 if (!success) {
697 return false;
698 }
699 }
700 return true;
701}
702
703// Sets error using keys of 'dict1' and 'dict2'.
704// 'dict1' and 'dict2' are assumed to be Python dictionaries.
705void SetDifferentKeysError(PyObject* dict1, PyObject* dict2, string* error_msg,
706 bool* is_type_error) {
707 Safe_PyObjectPtr k1(MappingKeys(dict1));
708 if (PyErr_Occurred() || k1.get() == nullptr) {
709 *error_msg =
710 ("The two dictionaries don't have the same set of keys. Failed to "
711 "fetch keys.");
712 return;
713 }
714 Safe_PyObjectPtr k2(MappingKeys(dict2));
715 if (PyErr_Occurred() || k2.get() == nullptr) {
716 *error_msg =
717 ("The two dictionaries don't have the same set of keys. Failed to "
718 "fetch keys.");
719 return;
720 }
721 *is_type_error = false;
722 *error_msg = tensorflow::strings::StrCat(
723 "The two dictionaries don't have the same set of keys. "
724 "First structure has keys ",
725 PyObjectToString(k1.get()), ", while second structure has keys ",
726 PyObjectToString(k2.get()));
727}
728
729// Returns true iff there were no "internal" errors. In other words,
730// errors that has nothing to do with structure checking.
731// If an "internal" error occurred, the appropriate Python error will be
732// set and the caller can propage it directly to the user.
733//
734// Both `error_msg` and `is_type_error` must be non-null. `error_msg` must
735// be empty.
736// Leaves `error_msg` empty if structures matched. Else, fills `error_msg`
737// with appropriate error and sets `is_type_error` to true iff
738// the error to be raised should be TypeError.
739bool AssertSameStructureHelper(
740 PyObject* o1, PyObject* o2, bool check_types, string* error_msg,
741 bool* is_type_error,
742 const std::function<int(PyObject*)>& is_sequence_helper,
743 const std::function<ValueIteratorPtr(PyObject*)>& value_iterator_getter,
744 bool check_composite_tensor_type_spec) {
745 DCHECK(error_msg)while (false && (error_msg)) ::tensorflow::internal::
LogMessageFatal("tensorflow/python/util/util.cc", 745)
;
746 DCHECK(is_type_error)while (false && (is_type_error)) ::tensorflow::internal
::LogMessageFatal("tensorflow/python/util/util.cc", 746)
;
747 const bool is_seq1 = is_sequence_helper(o1);
748 const bool is_seq2 = is_sequence_helper(o2);
749 if (PyErr_Occurred()) return false;
750 if (is_seq1 != is_seq2) {
751 string seq_str = is_seq1 ? PyObjectToString(o1) : PyObjectToString(o2);
752 string non_seq_str = is_seq1 ? PyObjectToString(o2) : PyObjectToString(o1);
753 *is_type_error = false;
754 *error_msg = tensorflow::strings::StrCat(
755 "Substructure \"", seq_str, "\" is a sequence, while substructure \"",
756 non_seq_str, "\" is not");
757 return true;
758 }
759
760 // Got to objects that are considered non-sequences. Note that in tf.data
761 // use case lists and sparse_tensors are not considered sequences. So finished
762 // checking, structures are the same.
763 if (!is_seq1) return true;
764
765 if (check_types) {
766 // Treat wrapped tuples as tuples.
767 tensorflow::Safe_PyObjectPtr o1_wrapped;
768 if (IsObjectProxy(o1)) {
769 o1_wrapped.reset(PyObject_GetAttrString(o1, "__wrapped__"));
770 o1 = o1_wrapped.get();
771 }
772 tensorflow::Safe_PyObjectPtr o2_wrapped;
773 if (IsObjectProxy(o2)) {
774 o2_wrapped.reset(PyObject_GetAttrString(o2, "__wrapped__"));
775 o2 = o2_wrapped.get();
776 }
777
778 const PyTypeObject* type1 = o1->ob_type;
779 const PyTypeObject* type2 = o2->ob_type;
780
781 // We treat two different namedtuples with identical name and fields
782 // as having the same type.
783 const PyObject* o1_tuple = IsNamedtuple(o1, false);
784 if (o1_tuple == nullptr) return false;
785 const PyObject* o2_tuple = IsNamedtuple(o2, false);
786 if (o2_tuple == nullptr) {
787 Py_DECREF(o1_tuple)_Py_DECREF(((PyObject*)(o1_tuple)));
788 return false;
789 }
790 bool both_tuples = o1_tuple == Py_True((PyObject *) &_Py_TrueStruct) && o2_tuple == Py_True((PyObject *) &_Py_TrueStruct);
791 Py_DECREF(o1_tuple)_Py_DECREF(((PyObject*)(o1_tuple)));
792 Py_DECREF(o2_tuple)_Py_DECREF(((PyObject*)(o2_tuple)));
793
794 if (both_tuples) {
795 const PyObject* same_tuples = SameNamedtuples(o1, o2);
796 if (same_tuples == nullptr) return false;
797 bool not_same_tuples = same_tuples != Py_True((PyObject *) &_Py_TrueStruct);
798 Py_DECREF(same_tuples)_Py_DECREF(((PyObject*)(same_tuples)));
799 if (not_same_tuples) {
800 *is_type_error = true;
801 *error_msg = tensorflow::strings::StrCat(
802 "The two namedtuples don't have the same sequence type. "
803 "First structure ",
804 PyObjectToString(o1), " has type ", type1->tp_name,
805 ", while second structure ", PyObjectToString(o2), " has type ",
806 type2->tp_name);
807 return true;
808 }
809 } else if (type1 != type2
810 /* If both sequences are list types, don't complain. This allows
811 one to be a list subclass (e.g. _ListWrapper used for
812 automatic dependency tracking.) */
813 && !(PyList_Check(o1)((((((PyObject*)(o1))->ob_type))->tp_flags & ((1UL <<
25))) != 0)
&& PyList_Check(o2)((((((PyObject*)(o2))->ob_type))->tp_flags & ((1UL <<
25))) != 0)
)
814 /* Two mapping types will also compare equal, making _DictWrapper
815 and dict compare equal. */
816 && !(IsMappingHelper(o1) && IsMappingHelper(o2))
817 /* For CompositeTensor & TypeSpec, we check below. */
818 && !(check_composite_tensor_type_spec &&
819 (IsCompositeTensor(o1) || IsCompositeTensor(o2)) &&
820 (IsTypeSpec(o1) || IsTypeSpec(o2)))) {
821 *is_type_error = true;
822 *error_msg = tensorflow::strings::StrCat(
823 "The two namedtuples don't have the same sequence type. "
824 "First structure ",
825 PyObjectToString(o1), " has type ", type1->tp_name,
826 ", while second structure ", PyObjectToString(o2), " has type ",
827 type2->tp_name);
828 return true;
829 }
830
831 if (PyDict_Check(o1)((((((PyObject*)(o1))->ob_type))->tp_flags & ((1UL <<
29))) != 0)
&& PyDict_Check(o2)((((((PyObject*)(o2))->ob_type))->tp_flags & ((1UL <<
29))) != 0)
) {
832 if (PyDict_Size(o1) != PyDict_Size(o2)) {
833 SetDifferentKeysError(o1, o2, error_msg, is_type_error);
834 return true;
835 }
836
837 PyObject* key;
838 Py_ssize_t pos = 0;
839 while (PyDict_Next(o1, &pos, &key, nullptr)) {
840 if (PyDict_GetItem(o2, key) == nullptr) {
841 SetDifferentKeysError(o1, o2, error_msg, is_type_error);
842 return true;
843 }
844 }
845 } else if (IsMappingHelper(o1)) {
846 // Fallback for custom mapping types. Instead of using PyDict methods
847 // which stay in C, we call iter(o1).
848 if (PyMapping_Size(o1) != PyMapping_Size(o2)) {
849 SetDifferentKeysError(o1, o2, error_msg, is_type_error);
850 return true;
851 }
852
853 Safe_PyObjectPtr iter(PyObject_GetIter(o1));
854 PyObject* key;
855 while ((key = PyIter_Next(iter.get())) != nullptr) {
856 if (!PyMapping_HasKey(o2, key)) {
857 SetDifferentKeysError(o1, o2, error_msg, is_type_error);
858 Py_DECREF(key)_Py_DECREF(((PyObject*)(key)));
859 return true;
860 }
861 Py_DECREF(key)_Py_DECREF(((PyObject*)(key)));
862 }
863 }
864 }
865
866 if (check_composite_tensor_type_spec &&
867 (IsCompositeTensor(o1) || IsCompositeTensor(o2))) {
868 Safe_PyObjectPtr owned_type_spec_1;
869 PyObject* type_spec_1 = o1;
870 if (IsCompositeTensor(o1)) {
871 owned_type_spec_1.reset(PyObject_GetAttrString(o1, "_type_spec"));
872 type_spec_1 = owned_type_spec_1.get();
873 }
874
875 Safe_PyObjectPtr owned_type_spec_2;
876 PyObject* type_spec_2 = o2;
877 if (IsCompositeTensor(o2)) {
878 owned_type_spec_2.reset(PyObject_GetAttrString(o2, "_type_spec"));
879 type_spec_2 = owned_type_spec_2.get();
880 }
881
882 // Two composite tensors are considered to have the same structure if
883 // there is some type spec that is compatible with both of them. Thus,
884 // we use most_specific_compatible_type(), and check if it raises an
885 // exception. We do *not* use is_compatible_with, since that would
886 // prevent us from e.g. using a cond statement where the two sides have
887 // different shapes.
888 static char compatible_type[] = "most_specific_compatible_type";
889 static char argspec[] = "(O)";
890 Safe_PyObjectPtr struct_compatible(PyObject_CallMethod(
891 type_spec_1, compatible_type, argspec, type_spec_2));
892 if (PyErr_Occurred() || struct_compatible == nullptr) {
893 PyErr_Clear();
894 *is_type_error = false;
895 *error_msg = tensorflow::strings::StrCat(
896 "Incompatible CompositeTensor TypeSpecs: ",
897 PyObjectToString(type_spec_1), " vs. ",
898 PyObjectToString(type_spec_2));
899 return true;
900 }
901 }
902
903 ValueIteratorPtr iter1 = value_iterator_getter(o1);
904 ValueIteratorPtr iter2 = value_iterator_getter(o2);
905
906 if (!iter1->valid() || !iter2->valid()) return false;
907
908 while (true) {
909 Safe_PyObjectPtr v1 = iter1->next();
910 Safe_PyObjectPtr v2 = iter2->next();
911 if (v1 && v2) {
912 if (Py_EnterRecursiveCall(" in assert_same_structure")((++(PyThreadState_Get()->recursion_depth) > _Py_CheckRecursionLimit
) && _Py_CheckRecursiveCall(" in assert_same_structure"
))
) {
913 return false;
914 }
915 bool no_internal_errors = AssertSameStructureHelper(
916 v1.get(), v2.get(), check_types, error_msg, is_type_error,
917 is_sequence_helper, value_iterator_getter,
918 check_composite_tensor_type_spec);
919 Py_LeaveRecursiveCall()do{ if((--(PyThreadState_Get()->recursion_depth) < (((_Py_CheckRecursionLimit
) > 200) ? ((_Py_CheckRecursionLimit) - 50) : (3 * ((_Py_CheckRecursionLimit
) >> 2))))) PyThreadState_Get()->overflowed = 0; } while
(0)
;
920 if (!no_internal_errors) return false;
921 if (!error_msg->empty()) return true;
922 } else if (!v1 && !v2) {
923 // Done with all recursive calls. Structure matched.
924 return true;
925 } else {
926 *is_type_error = false;
927 *error_msg = tensorflow::strings::StrCat(
928 "The two structures don't have the same number of elements. ",
929 "First structure: ", PyObjectToString(o1),
930 ". Second structure: ", PyObjectToString(o2));
931 return true;
932 }
933 }
934}
935
936} // namespace
937
938bool IsSequence(PyObject* o) { return IsSequenceHelper(o) == 1; }
939bool IsMapping(PyObject* o) { return IsMappingHelper(o) == 1; }
940bool IsMutableMapping(PyObject* o) { return IsMutableMappingHelper(o) == 1; }
941bool IsMappingView(PyObject* o) { return IsMappingViewHelper(o) == 1; }
942bool IsAttrs(PyObject* o) { return IsAttrsHelper(o) == 1; }
943bool IsTensor(PyObject* o) { return IsTensorHelper(o) == 1; }
944bool IsTensorSpec(PyObject* o) { return IsTensorSpecHelper(o) == 1; }
945bool IsEagerTensorSlow(PyObject* o) { return IsEagerTensorHelper(o) == 1; }
946bool IsResourceVariable(PyObject* o) {
947 return IsResourceVariableHelper(o) == 1;
948}
949bool IsOwnedIterator(PyObject* o) { return IsOwnedIteratorHelper(o) == 1; }
950bool IsVariable(PyObject* o) { return IsVariableHelper(o) == 1; }
951bool IsIndexedSlices(PyObject* o) { return IsIndexedSlicesHelper(o) == 1; }
952bool IsDispatchable(PyObject* o) { return IsDispatchableHelper(o) == 1; }
953
954bool IsTuple(PyObject* o) {
955 tensorflow::Safe_PyObjectPtr wrapped;
956 if (IsObjectProxy(o)) {
957 wrapped.reset(PyObject_GetAttrString(o, "__wrapped__"));
958 o = wrapped.get();
959 }
960 return PyTuple_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
26))) != 0)
;
961}
962
963// Work around a writable-strings warning with Python 2's PyMapping_Keys macro,
964// and while we're at it give them consistent behavior by making sure the
965// returned value is a list.
966//
967// As with PyMapping_Keys, returns a new reference.
968//
969// On failure, returns nullptr.
970PyObject* MappingKeys(PyObject* o) {
971#if PY_MAJOR_VERSION3 >= 3
972 return PyMapping_Keys(o);
973#else
974 static char key_method_name[] = "keys";
975 Safe_PyObjectPtr raw_result(PyObject_CallMethod(o, key_method_name, nullptr));
976 if (PyErr_Occurred() || raw_result.get() == nullptr) {
977 return nullptr;
978 }
979 return PySequence_Fast(
980 raw_result.get(),
981 "The '.keys()' method of a custom mapping returned a non-sequence.");
982#endif
983}
984
985PyObject* Flatten(PyObject* nested, bool expand_composites) {
986 PyObject* list = PyList_New(0);
987 const std::function<int(PyObject*)>& is_sequence_helper =
988 expand_composites ? IsSequenceOrCompositeHelper : IsSequenceHelper;
989 const std::function<ValueIteratorPtr(PyObject*)>& get_value_iterator =
990 expand_composites ? GetValueIteratorForComposite : GetValueIterator;
991 if (FlattenHelper(nested, list, is_sequence_helper, get_value_iterator)) {
992 return list;
993 } else {
994 Py_DECREF(list)_Py_DECREF(((PyObject*)(list)));
995 return nullptr;
996 }
997}
998
999bool IsSequenceOrComposite(PyObject* o) {
1000 return IsSequenceOrCompositeHelper(o) == 1;
1001}
1002
1003bool IsCompositeTensor(PyObject* o) { return IsCompositeTensorHelper(o) == 1; }
1004
1005bool IsTypeSpec(PyObject* o) { return IsTypeSpecHelper(o) == 1; }
1006
1007bool IsSequenceForData(PyObject* o) { return IsSequenceForDataHelper(o) == 1; }
1008
1009PyObject* FlattenForData(PyObject* nested) {
1010 PyObject* list = PyList_New(0);
1011 if (FlattenHelper(nested, list, IsSequenceForDataHelper,
1
Calling 'FlattenHelper'
1012 GetValueIteratorForData)) {
1013 return list;
1014 } else {
1015 Py_DECREF(list)_Py_DECREF(((PyObject*)(list)));
1016 return nullptr;
1017 }
1018}
1019
1020PyObject* IsNamedtuple(PyObject* o, bool strict) {
1021 // Some low-level CPython calls do not work with wrapt.ObjectProxy, so they
1022 // require some unwrapping if we want to treat them like the objects they're
1023 // wrapping.
1024 tensorflow::Safe_PyObjectPtr o_wrapped;
1025 if (IsObjectProxy(o)) {
1026 o_wrapped.reset(PyObject_GetAttrString(o, "__wrapped__"));
1027 o = o_wrapped.get();
1028 }
1029
1030 // Must be subclass of tuple
1031 if (!PyTuple_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
26))) != 0)
) {
1032 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1033 }
1034
1035 // If strict, o.__class__.__base__ must be tuple
1036 if (strict) {
1037 PyObject* klass = PyObject_GetAttrString(o, "__class__");
1038 if (klass == nullptr) return nullptr;
1039 PyObject* base = PyObject_GetAttrString(klass, "__base__");
1040 Py_DECREF(klass)_Py_DECREF(((PyObject*)(klass)));
1041 if (base == nullptr) return nullptr;
1042
1043 const PyTypeObject* base_type = reinterpret_cast<PyTypeObject*>(base);
1044 // built-in object types are singletons
1045 bool tuple_base = base_type == &PyTuple_Type;
1046 Py_DECREF(base)_Py_DECREF(((PyObject*)(base)));
1047 if (!tuple_base) {
1048 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1049 }
1050 }
1051
1052 // o must have attribute '_fields' and every element in
1053 // '_fields' must be a string.
1054 int has_fields = PyObject_HasAttrString(o, "_fields");
1055 if (!has_fields) {
1056 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1057 }
1058
1059 Safe_PyObjectPtr fields = make_safe(PyObject_GetAttrString(o, "_fields"));
1060 int is_instance = IsInstanceOfRegisteredType(fields.get(), "Sequence");
1061 if (is_instance == 0) {
1062 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1063 } else if (is_instance == -1) {
1064 return nullptr;
1065 }
1066
1067 Safe_PyObjectPtr seq = make_safe(PySequence_Fast(fields.get(), ""));
1068 const Py_ssize_t s = PySequence_Fast_GET_SIZE(seq.get())(((((((PyObject*)(seq.get()))->ob_type))->tp_flags &
((1UL << 25))) != 0) ? ((static_cast<void> (0)),
(((PyVarObject*)(seq.get()))->ob_size)) : (((PyVarObject*
)(((static_cast<void> (0)), (PyTupleObject *)(seq.get()
))))->ob_size))
;
1069 for (Py_ssize_t i = 0; i < s; ++i) {
1070 // PySequence_Fast_GET_ITEM returns borrowed ref
1071 PyObject* elem = PySequence_Fast_GET_ITEM(seq.get(), i)(((((((PyObject*)(seq.get()))->ob_type))->tp_flags &
((1UL << 25))) != 0) ? (((PyListObject *)(seq.get()))->
ob_item[i]) : (((static_cast<void> (0)), (PyTupleObject
*)(seq.get()))->ob_item[i]))
;
1072 if (!IsString(elem)) {
1073 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1074 }
1075 }
1076
1077 Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct
)))), ((PyObject *) &_Py_TrueStruct)
;
1078}
1079
1080PyObject* SameNamedtuples(PyObject* o1, PyObject* o2) {
1081 Safe_PyObjectPtr f1 = make_safe(PyObject_GetAttrString(o1, "_fields"));
1082 Safe_PyObjectPtr f2 = make_safe(PyObject_GetAttrString(o2, "_fields"));
1083 if (f1 == nullptr || f2 == nullptr) {
1084 PyErr_SetString(
1085 PyExc_RuntimeError,
1086 "Expected namedtuple-like objects (that have _fields attr)");
1087 return nullptr;
1088 }
1089
1090 if (PyObject_RichCompareBool(f1.get(), f2.get(), Py_NE3)) {
1091 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1092 }
1093
1094 if (GetClassName(o1).compare(GetClassName(o2)) == 0) {
1095 Py_RETURN_TRUEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_TrueStruct
)))), ((PyObject *) &_Py_TrueStruct)
;
1096 } else {
1097 Py_RETURN_FALSEreturn _Py_INCREF(((PyObject*)(((PyObject *) &_Py_FalseStruct
)))), ((PyObject *) &_Py_FalseStruct)
;
1098 }
1099}
1100
1101PyObject* AssertSameStructure(PyObject* o1, PyObject* o2, bool check_types,
1102 bool expand_composites) {
1103 const std::function<int(PyObject*)>& is_sequence_helper =
1104 expand_composites ? IsSequenceOrCompositeHelper : IsSequenceHelper;
1105 const std::function<ValueIteratorPtr(PyObject*)>& get_value_iterator =
1106 expand_composites ? GetValueIteratorForComposite : GetValueIterator;
1107 const bool check_composite_tensor_type_spec = expand_composites;
1108 string error_msg;
1109 bool is_type_error = false;
1110 AssertSameStructureHelper(o1, o2, check_types, &error_msg, &is_type_error,
1111 is_sequence_helper, get_value_iterator,
1112 check_composite_tensor_type_spec);
1113 if (PyErr_Occurred()) {
1114 // Don't hide Python exceptions while checking (e.g. errors fetching keys
1115 // from custom mappings).
1116 return nullptr;
1117 }
1118 if (!error_msg.empty()) {
1119 PyErr_SetString(
1120 is_type_error ? PyExc_TypeError : PyExc_ValueError,
1121 tensorflow::strings::StrCat(
1122 "The two structures don't have the same nested structure.\n\n",
1123 "First structure: ", PyObjectToString(o1), "\n\nSecond structure: ",
1124 PyObjectToString(o2), "\n\nMore specifically: ", error_msg)
1125 .c_str());
1126 return nullptr;
1127 }
1128 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1129}
1130
1131PyObject* AssertSameStructureForData(PyObject* o1, PyObject* o2,
1132 bool check_types) {
1133 string error_msg;
1134 bool is_type_error = false;
1135 AssertSameStructureHelper(o1, o2, check_types, &error_msg, &is_type_error,
1136 IsSequenceForDataHelper, GetValueIterator, false);
1137 if (PyErr_Occurred()) {
1138 // Don't hide Python exceptions while checking (e.g. errors fetching keys
1139 // from custom mappings).
1140 return nullptr;
1141 }
1142 if (!error_msg.empty()) {
1143 PyErr_SetString(
1144 is_type_error ? PyExc_TypeError : PyExc_ValueError,
1145 tensorflow::strings::StrCat(
1146 "The two structures don't have the same nested structure.\n\n",
1147 "First structure: ", PyObjectToString(o1), "\n\nSecond structure: ",
1148 PyObjectToString(o2), "\n\nMore specifically: ", error_msg)
1149 .c_str());
1150 return nullptr;
1151 }
1152 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1153}
1154
1155} // namespace swig
1156} // namespace tensorflow

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/std_function.h

1// Implementation of std::function -*- C++ -*-
2
3// Copyright (C) 2004-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/bits/std_function.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_STD_FUNCTION_H1
31#define _GLIBCXX_STD_FUNCTION_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201402L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#if __cpp_rtti199711L
40# include <typeinfo>
41#endif
42#include <bits/stl_function.h>
43#include <bits/invoke.h>
44#include <bits/refwrap.h>
45#include <bits/functexcept.h>
46
47namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
48{
49_GLIBCXX_BEGIN_NAMESPACE_VERSION
50
51 /**
52 * @brief Exception class thrown when class template function's
53 * operator() is called with an empty target.
54 * @ingroup exceptions
55 */
56 class bad_function_call : public std::exception
57 {
58 public:
59 virtual ~bad_function_call() noexcept;
60
61 const char* what() const noexcept;
62 };
63
64 /**
65 * Trait identifying "location-invariant" types, meaning that the
66 * address of the object (or any of its members) will not escape.
67 * Trivially copyable types are location-invariant and users can
68 * specialize this trait for other types.
69 */
70 template<typename _Tp>
71 struct __is_location_invariant
72 : is_trivially_copyable<_Tp>::type
73 { };
74
75 class _Undefined_class;
76
77 union _Nocopy_types
78 {
79 void* _M_object;
80 const void* _M_const_object;
81 void (*_M_function_pointer)();
82 void (_Undefined_class::*_M_member_pointer)();
83 };
84
85 union [[gnu::may_alias]] _Any_data
86 {
87 void* _M_access() { return &_M_pod_data[0]; }
88 const void* _M_access() const { return &_M_pod_data[0]; }
89
90 template<typename _Tp>
91 _Tp&
92 _M_access()
93 { return *static_cast<_Tp*>(_M_access()); }
94
95 template<typename _Tp>
96 const _Tp&
97 _M_access() const
98 { return *static_cast<const _Tp*>(_M_access()); }
99
100 _Nocopy_types _M_unused;
101 char _M_pod_data[sizeof(_Nocopy_types)];
102 };
103
104 enum _Manager_operation
105 {
106 __get_type_info,
107 __get_functor_ptr,
108 __clone_functor,
109 __destroy_functor
110 };
111
112 template<typename _Signature>
113 class function;
114
115 /// Base class of all polymorphic function object wrappers.
116 class _Function_base
117 {
118 public:
119 static const size_t _M_max_size = sizeof(_Nocopy_types);
120 static const size_t _M_max_align = __alignof__(_Nocopy_types);
121
122 template<typename _Functor>
123 class _Base_manager
124 {
125 protected:
126 static const bool __stored_locally =
127 (__is_location_invariant<_Functor>::value
128 && sizeof(_Functor) <= _M_max_size
129 && __alignof__(_Functor) <= _M_max_align
130 && (_M_max_align % __alignof__(_Functor) == 0));
131
132 typedef integral_constant<bool, __stored_locally> _Local_storage;
133
134 // Retrieve a pointer to the function object
135 static _Functor*
136 _M_get_pointer(const _Any_data& __source)
137 {
138 if _GLIBCXX17_CONSTEXPR (__stored_locally)
139 {
140 const _Functor& __f = __source._M_access<_Functor>();
141 return const_cast<_Functor*>(std::__addressof(__f));
142 }
143 else // have stored a pointer
144 return __source._M_access<_Functor*>();
145 }
146
147 // Clone a location-invariant function object that fits within
148 // an _Any_data structure.
149 static void
150 _M_clone(_Any_data& __dest, const _Any_data& __source, true_type)
151 {
152 ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>());
153 }
154
155 // Clone a function object that is not location-invariant or
156 // that cannot fit into an _Any_data structure.
157 static void
158 _M_clone(_Any_data& __dest, const _Any_data& __source, false_type)
159 {
160 __dest._M_access<_Functor*>() =
161 new _Functor(*__source._M_access<const _Functor*>());
162 }
163
164 // Destroying a location-invariant object may still require
165 // destruction.
166 static void
167 _M_destroy(_Any_data& __victim, true_type)
168 {
169 __victim._M_access<_Functor>().~_Functor();
170 }
171
172 // Destroying an object located on the heap.
173 static void
174 _M_destroy(_Any_data& __victim, false_type)
175 {
176 delete __victim._M_access<_Functor*>();
177 }
178
179 public:
180 static bool
181 _M_manager(_Any_data& __dest, const _Any_data& __source,
182 _Manager_operation __op)
183 {
184 switch (__op)
185 {
186#if __cpp_rtti199711L
187 case __get_type_info:
188 __dest._M_access<const type_info*>() = &typeid(_Functor);
189 break;
190#endif
191 case __get_functor_ptr:
192 __dest._M_access<_Functor*>() = _M_get_pointer(__source);
193 break;
194
195 case __clone_functor:
196 _M_clone(__dest, __source, _Local_storage());
197 break;
198
199 case __destroy_functor:
200 _M_destroy(__dest, _Local_storage());
201 break;
202 }
203 return false;
204 }
205
206 static void
207 _M_init_functor(_Any_data& __functor, _Functor&& __f)
208 { _M_init_functor(__functor, std::move(__f), _Local_storage()); }
209
210 template<typename _Signature>
211 static bool
212 _M_not_empty_function(const function<_Signature>& __f)
213 { return static_cast<bool>(__f); }
214
215 template<typename _Tp>
216 static bool
217 _M_not_empty_function(_Tp* __fp)
218 { return __fp != nullptr; }
219
220 template<typename _Class, typename _Tp>
221 static bool
222 _M_not_empty_function(_Tp _Class::* __mp)
223 { return __mp != nullptr; }
224
225 template<typename _Tp>
226 static bool
227 _M_not_empty_function(const _Tp&)
228 { return true; }
229
230 private:
231 static void
232 _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type)
233 { ::new (__functor._M_access()) _Functor(std::move(__f)); }
234
235 static void
236 _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type)
237 { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
238 };
239
240 _Function_base() : _M_manager(nullptr) { }
241
242 ~_Function_base()
243 {
244 if (_M_manager)
245 _M_manager(_M_functor, _M_functor, __destroy_functor);
246 }
247
248 bool _M_empty() const { return !_M_manager; }
249
250 typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
251 _Manager_operation);
252
253 _Any_data _M_functor;
254 _Manager_type _M_manager;
255 };
256
257 template<typename _Signature, typename _Functor>
258 class _Function_handler;
259
260 template<typename _Res, typename _Functor, typename... _ArgTypes>
261 class _Function_handler<_Res(_ArgTypes...), _Functor>
262 : public _Function_base::_Base_manager<_Functor>
263 {
264 typedef _Function_base::_Base_manager<_Functor> _Base;
265
266 public:
267 static bool
268 _M_manager(_Any_data& __dest, const _Any_data& __source,
269 _Manager_operation __op)
270 {
271 switch (__op)
272 {
273#if __cpp_rtti199711L
274 case __get_type_info:
275 __dest._M_access<const type_info*>() = &typeid(_Functor);
276 break;
277#endif
278 case __get_functor_ptr:
279 __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source);
280 break;
281
282 default:
283 _Base::_M_manager(__dest, __source, __op);
284 }
285 return false;
286 }
287
288 static _Res
289 _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
290 {
291 return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor),
7
Calling '__invoke_r<std::unique_ptr<tensorflow::swig::(anonymous namespace)::ValueIterator>, std::unique_ptr<tensorflow::swig::(anonymous namespace)::ValueIterator> (*&)(_object *), _object *>'
292 std::forward<_ArgTypes>(__args)...);
293 }
294 };
295
296 /**
297 * @brief Primary class template for std::function.
298 * @ingroup functors
299 *
300 * Polymorphic function wrapper.
301 */
302 template<typename _Res, typename... _ArgTypes>
303 class function<_Res(_ArgTypes...)>
304 : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
305 private _Function_base
306 {
307 template<typename _Func,
308 typename _Res2 = __invoke_result<_Func&, _ArgTypes...>>
309 struct _Callable
310 : __is_invocable_impl<_Res2, _Res>::type
311 { };
312
313 // Used so the return type convertibility checks aren't done when
314 // performing overload resolution for copy construction/assignment.
315 template<typename _Tp>
316 struct _Callable<function, _Tp> : false_type { };
317
318 template<typename _Cond, typename _Tp>
319 using _Requires = typename enable_if<_Cond::value, _Tp>::type;
320
321 public:
322 typedef _Res result_type;
323
324 // [3.7.2.1] construct/copy/destroy
325
326 /**
327 * @brief Default construct creates an empty function call wrapper.
328 * @post @c !(bool)*this
329 */
330 function() noexcept
331 : _Function_base() { }
332
333 /**
334 * @brief Creates an empty function call wrapper.
335 * @post @c !(bool)*this
336 */
337 function(nullptr_t) noexcept
338 : _Function_base() { }
339
340 /**
341 * @brief %Function copy constructor.
342 * @param __x A %function object with identical call signature.
343 * @post @c bool(*this) == bool(__x)
344 *
345 * The newly-created %function contains a copy of the target of @a
346 * __x (if it has one).
347 */
348 function(const function& __x);
349
350 /**
351 * @brief %Function move constructor.
352 * @param __x A %function object rvalue with identical call signature.
353 *
354 * The newly-created %function contains the target of @a __x
355 * (if it has one).
356 */
357 function(function&& __x) noexcept : _Function_base()
358 {
359 __x.swap(*this);
360 }
361
362 /**
363 * @brief Builds a %function that targets a copy of the incoming
364 * function object.
365 * @param __f A %function object that is callable with parameters of
366 * type @c T1, @c T2, ..., @c TN and returns a value convertible
367 * to @c Res.
368 *
369 * The newly-created %function object will target a copy of
370 * @a __f. If @a __f is @c reference_wrapper<F>, then this function
371 * object will contain a reference to the function object @c
372 * __f.get(). If @a __f is a NULL function pointer or NULL
373 * pointer-to-member, the newly-created object will be empty.
374 *
375 * If @a __f is a non-NULL function pointer or an object of type @c
376 * reference_wrapper<F>, this function will not throw.
377 */
378 template<typename _Functor,
379 typename = _Requires<__not_<is_same<_Functor, function>>, void>,
380 typename = _Requires<_Callable<_Functor>, void>>
381 function(_Functor);
382
383 /**
384 * @brief %Function assignment operator.
385 * @param __x A %function with identical call signature.
386 * @post @c (bool)*this == (bool)x
387 * @returns @c *this
388 *
389 * The target of @a __x is copied to @c *this. If @a __x has no
390 * target, then @c *this will be empty.
391 *
392 * If @a __x targets a function pointer or a reference to a function
393 * object, then this operation will not throw an %exception.
394 */
395 function&
396 operator=(const function& __x)
397 {
398 function(__x).swap(*this);
399 return *this;
400 }
401
402 /**
403 * @brief %Function move-assignment operator.
404 * @param __x A %function rvalue with identical call signature.
405 * @returns @c *this
406 *
407 * The target of @a __x is moved to @c *this. If @a __x has no
408 * target, then @c *this will be empty.
409 *
410 * If @a __x targets a function pointer or a reference to a function
411 * object, then this operation will not throw an %exception.
412 */
413 function&
414 operator=(function&& __x) noexcept
415 {
416 function(std::move(__x)).swap(*this);
417 return *this;
418 }
419
420 /**
421 * @brief %Function assignment to zero.
422 * @post @c !(bool)*this
423 * @returns @c *this
424 *
425 * The target of @c *this is deallocated, leaving it empty.
426 */
427 function&
428 operator=(nullptr_t) noexcept
429 {
430 if (_M_manager)
431 {
432 _M_manager(_M_functor, _M_functor, __destroy_functor);
433 _M_manager = nullptr;
434 _M_invoker = nullptr;
435 }
436 return *this;
437 }
438
439 /**
440 * @brief %Function assignment to a new target.
441 * @param __f A %function object that is callable with parameters of
442 * type @c T1, @c T2, ..., @c TN and returns a value convertible
443 * to @c Res.
444 * @return @c *this
445 *
446 * This %function object wrapper will target a copy of @a
447 * __f. If @a __f is @c reference_wrapper<F>, then this function
448 * object will contain a reference to the function object @c
449 * __f.get(). If @a __f is a NULL function pointer or NULL
450 * pointer-to-member, @c this object will be empty.
451 *
452 * If @a __f is a non-NULL function pointer or an object of type @c
453 * reference_wrapper<F>, this function will not throw.
454 */
455 template<typename _Functor>
456 _Requires<_Callable<typename decay<_Functor>::type>, function&>
457 operator=(_Functor&& __f)
458 {
459 function(std::forward<_Functor>(__f)).swap(*this);
460 return *this;
461 }
462
463 /// @overload
464 template<typename _Functor>
465 function&
466 operator=(reference_wrapper<_Functor> __f) noexcept
467 {
468 function(__f).swap(*this);
469 return *this;
470 }
471
472 // [3.7.2.2] function modifiers
473
474 /**
475 * @brief Swap the targets of two %function objects.
476 * @param __x A %function with identical call signature.
477 *
478 * Swap the targets of @c this function object and @a __f. This
479 * function will not throw an %exception.
480 */
481 void swap(function& __x) noexcept
482 {
483 std::swap(_M_functor, __x._M_functor);
484 std::swap(_M_manager, __x._M_manager);
485 std::swap(_M_invoker, __x._M_invoker);
486 }
487
488 // [3.7.2.3] function capacity
489
490 /**
491 * @brief Determine if the %function wrapper has a target.
492 *
493 * @return @c true when this %function object contains a target,
494 * or @c false when it is empty.
495 *
496 * This function will not throw an %exception.
497 */
498 explicit operator bool() const noexcept
499 { return !_M_empty(); }
500
501 // [3.7.2.4] function invocation
502
503 /**
504 * @brief Invokes the function targeted by @c *this.
505 * @returns the result of the target.
506 * @throws bad_function_call when @c !(bool)*this
507 *
508 * The function call operator invokes the target function object
509 * stored by @c this.
510 */
511 _Res operator()(_ArgTypes... __args) const;
512
513#if __cpp_rtti199711L
514 // [3.7.2.5] function target access
515 /**
516 * @brief Determine the type of the target of this function object
517 * wrapper.
518 *
519 * @returns the type identifier of the target function object, or
520 * @c typeid(void) if @c !(bool)*this.
521 *
522 * This function will not throw an %exception.
523 */
524 const type_info& target_type() const noexcept;
525
526 /**
527 * @brief Access the stored target function object.
528 *
529 * @return Returns a pointer to the stored target function object,
530 * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
531 * pointer.
532 *
533 * This function does not throw exceptions.
534 *
535 * @{
536 */
537 template<typename _Functor> _Functor* target() noexcept;
538
539 template<typename _Functor> const _Functor* target() const noexcept;
540 // @}
541#endif
542
543 private:
544 using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...);
545 _Invoker_type _M_invoker;
546 };
547
548#if __cpp_deduction_guides >= 201606
549 template<typename>
550 struct __function_guide_helper
551 { };
552
553 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
554 struct __function_guide_helper<
555 _Res (_Tp::*) (_Args...) noexcept(_Nx)
556 >
557 { using type = _Res(_Args...); };
558
559 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
560 struct __function_guide_helper<
561 _Res (_Tp::*) (_Args...) & noexcept(_Nx)
562 >
563 { using type = _Res(_Args...); };
564
565 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
566 struct __function_guide_helper<
567 _Res (_Tp::*) (_Args...) const noexcept(_Nx)
568 >
569 { using type = _Res(_Args...); };
570
571 template<typename _Res, typename _Tp, bool _Nx, typename... _Args>
572 struct __function_guide_helper<
573 _Res (_Tp::*) (_Args...) const & noexcept(_Nx)
574 >
575 { using type = _Res(_Args...); };
576
577 template<typename _Res, typename... _ArgTypes>
578 function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>;
579
580 template<typename _Functor, typename _Signature = typename
581 __function_guide_helper<decltype(&_Functor::operator())>::type>
582 function(_Functor) -> function<_Signature>;
583#endif
584
585 // Out-of-line member definitions.
586 template<typename _Res, typename... _ArgTypes>
587 function<_Res(_ArgTypes...)>::
588 function(const function& __x)
589 : _Function_base()
590 {
591 if (static_cast<bool>(__x))
592 {
593 __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
594 _M_invoker = __x._M_invoker;
595 _M_manager = __x._M_manager;
596 }
597 }
598
599 template<typename _Res, typename... _ArgTypes>
600 template<typename _Functor, typename, typename>
601 function<_Res(_ArgTypes...)>::
602 function(_Functor __f)
603 : _Function_base()
604 {
605 typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler;
606
607 if (_My_handler::_M_not_empty_function(__f))
608 {
609 _My_handler::_M_init_functor(_M_functor, std::move(__f));
610 _M_invoker = &_My_handler::_M_invoke;
611 _M_manager = &_My_handler::_M_manager;
612 }
613 }
614
615 template<typename _Res, typename... _ArgTypes>
616 _Res
617 function<_Res(_ArgTypes...)>::
618 operator()(_ArgTypes... __args) const
619 {
620 if (_M_empty())
5
Taking false branch
621 __throw_bad_function_call();
622 return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
6
Calling '_Function_handler::_M_invoke'
623 }
624
625#if __cpp_rtti199711L
626 template<typename _Res, typename... _ArgTypes>
627 const type_info&
628 function<_Res(_ArgTypes...)>::
629 target_type() const noexcept
630 {
631 if (_M_manager)
632 {
633 _Any_data __typeinfo_result;
634 _M_manager(__typeinfo_result, _M_functor, __get_type_info);
635 return *__typeinfo_result._M_access<const type_info*>();
636 }
637 else
638 return typeid(void);
639 }
640
641 template<typename _Res, typename... _ArgTypes>
642 template<typename _Functor>
643 _Functor*
644 function<_Res(_ArgTypes...)>::
645 target() noexcept
646 {
647 const function* __const_this = this;
648 const _Functor* __func = __const_this->template target<_Functor>();
649 return const_cast<_Functor*>(__func);
650 }
651
652 template<typename _Res, typename... _ArgTypes>
653 template<typename _Functor>
654 const _Functor*
655 function<_Res(_ArgTypes...)>::
656 target() const noexcept
657 {
658 if (typeid(_Functor) == target_type() && _M_manager)
659 {
660 _Any_data __ptr;
661 _M_manager(__ptr, _M_functor, __get_functor_ptr);
662 return __ptr._M_access<const _Functor*>();
663 }
664 else
665 return nullptr;
666 }
667#endif
668
669 // [20.7.15.2.6] null pointer comparisons
670
671 /**
672 * @brief Compares a polymorphic function object wrapper against 0
673 * (the NULL pointer).
674 * @returns @c true if the wrapper has no target, @c false otherwise
675 *
676 * This function will not throw an %exception.
677 */
678 template<typename _Res, typename... _Args>
679 inline bool
680 operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
681 { return !static_cast<bool>(__f); }
682
683#if __cpp_impl_three_way_comparison < 201907L
684 /// @overload
685 template<typename _Res, typename... _Args>
686 inline bool
687 operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
688 { return !static_cast<bool>(__f); }
689
690 /**
691 * @brief Compares a polymorphic function object wrapper against 0
692 * (the NULL pointer).
693 * @returns @c false if the wrapper has no target, @c true otherwise
694 *
695 * This function will not throw an %exception.
696 */
697 template<typename _Res, typename... _Args>
698 inline bool
699 operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept
700 { return static_cast<bool>(__f); }
701
702 /// @overload
703 template<typename _Res, typename... _Args>
704 inline bool
705 operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept
706 { return static_cast<bool>(__f); }
707#endif
708
709 // [20.7.15.2.7] specialized algorithms
710
711 /**
712 * @brief Swap the targets of two polymorphic function object wrappers.
713 *
714 * This function will not throw an %exception.
715 */
716 // _GLIBCXX_RESOLVE_LIB_DEFECTS
717 // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps
718 template<typename _Res, typename... _Args>
719 inline void
720 swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept
721 { __x.swap(__y); }
722
723#if __cplusplus201402L >= 201703L
724 namespace __detail::__variant
725 {
726 template<typename> struct _Never_valueless_alt; // see <variant>
727
728 // Provide the strong exception-safety guarantee when emplacing a
729 // function into a variant.
730 template<typename _Signature>
731 struct _Never_valueless_alt<std::function<_Signature>>
732 : std::true_type
733 { };
734 } // namespace __detail::__variant
735#endif // C++17
736
737_GLIBCXX_END_NAMESPACE_VERSION
738} // namespace std
739
740#endif // C++11
741#endif // _GLIBCXX_STD_FUNCTION_H

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/invoke.h

1// Implementation of INVOKE -*- C++ -*-
2
3// Copyright (C) 2016-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/bits/invoke.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{functional}
28 */
29
30#ifndef _GLIBCXX_INVOKE_H1
31#define _GLIBCXX_INVOKE_H1 1
32
33#pragma GCC system_header
34
35#if __cplusplus201402L < 201103L
36# include <bits/c++0x_warning.h>
37#else
38
39#include <type_traits>
40
41namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
42{
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
44
45 /**
46 * @addtogroup utilities
47 * @{
48 */
49
50 // Used by __invoke_impl instead of std::forward<_Tp> so that a
51 // reference_wrapper is converted to an lvalue-reference.
52 template<typename _Tp, typename _Up = typename __inv_unwrap<_Tp>::type>
53 constexpr _Up&&
54 __invfwd(typename remove_reference<_Tp>::type& __t) noexcept
55 { return static_cast<_Up&&>(__t); }
56
57 template<typename _Res, typename _Fn, typename... _Args>
58 constexpr _Res
59 __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
60 { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }
9
Calling 'GetValueIteratorForData'
61
62 template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
63 constexpr _Res
64 __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t,
65 _Args&&... __args)
66 { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); }
67
68 template<typename _Res, typename _MemFun, typename _Tp, typename... _Args>
69 constexpr _Res
70 __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t,
71 _Args&&... __args)
72 {
73 return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...);
74 }
75
76 template<typename _Res, typename _MemPtr, typename _Tp>
77 constexpr _Res
78 __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t)
79 { return __invfwd<_Tp>(__t).*__f; }
80
81 template<typename _Res, typename _MemPtr, typename _Tp>
82 constexpr _Res
83 __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t)
84 { return (*std::forward<_Tp>(__t)).*__f; }
85
86 /// Invoke a callable object.
87 template<typename _Callable, typename... _Args>
88 constexpr typename __invoke_result<_Callable, _Args...>::type
89 __invoke(_Callable&& __fn, _Args&&... __args)
90 noexcept(__is_nothrow_invocable<_Callable, _Args...>::value)
91 {
92 using __result = __invoke_result<_Callable, _Args...>;
93 using __type = typename __result::type;
94 using __tag = typename __result::__invoke_type;
95 return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
96 std::forward<_Args>(__args)...);
97 }
98
99#if __cplusplus201402L >= 201703L
100 // INVOKE<R>: Invoke a callable object and convert the result to R.
101 template<typename _Res, typename _Callable, typename... _Args>
102 constexpr enable_if_t<is_invocable_r_v<_Res, _Callable, _Args...>, _Res>
103 __invoke_r(_Callable&& __fn, _Args&&... __args)
104 noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>)
105 {
106 using __result = __invoke_result<_Callable, _Args...>;
107 using __type = typename __result::type;
108 using __tag = typename __result::__invoke_type;
109 if constexpr (is_void_v<_Res>)
110 std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
111 std::forward<_Args>(__args)...);
112 else
113 return std::__invoke_impl<__type>(__tag{},
114 std::forward<_Callable>(__fn),
115 std::forward<_Args>(__args)...);
116 }
117#else // C++11
118 template<typename _Res, typename _Callable, typename... _Args>
119 using __can_invoke_as_void = __enable_if_t<
120 __and_<is_void<_Res>, __is_invocable<_Callable, _Args...>>::value,
121 _Res
122 >;
123
124 template<typename _Res, typename _Callable, typename... _Args>
125 using __can_invoke_as_nonvoid = __enable_if_t<
126 __and_<__not_<is_void<_Res>>,
127 is_convertible<typename __invoke_result<_Callable, _Args...>::type,
128 _Res>
129 >::value,
130 _Res
131 >;
132
133 // INVOKE<R>: Invoke a callable object and convert the result to R.
134 template<typename _Res, typename _Callable, typename... _Args>
135 constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...>
136 __invoke_r(_Callable&& __fn, _Args&&... __args)
137 {
138 using __result = __invoke_result<_Callable, _Args...>;
139 using __type = typename __result::type;
140 using __tag = typename __result::__invoke_type;
141 return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
8
Calling '__invoke_impl<std::unique_ptr<tensorflow::swig::(anonymous namespace)::ValueIterator>, std::unique_ptr<tensorflow::swig::(anonymous namespace)::ValueIterator> (*&)(_object *), _object *>'
142 std::forward<_Args>(__args)...);
143 }
144
145 // INVOKE<R> when R is cv void
146 template<typename _Res, typename _Callable, typename... _Args>
147 _GLIBCXX14_CONSTEXPRconstexpr __can_invoke_as_void<_Res, _Callable, _Args...>
148 __invoke_r(_Callable&& __fn, _Args&&... __args)
149 {
150 using __result = __invoke_result<_Callable, _Args...>;
151 using __type = typename __result::type;
152 using __tag = typename __result::__invoke_type;
153 std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
154 std::forward<_Args>(__args)...);
155 }
156#endif // C++11
157
158_GLIBCXX_END_NAMESPACE_VERSION
159} // namespace std
160
161#endif // C++11
162
163#endif // _GLIBCXX_INVOKE_H

/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unique_ptr.h

1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2020 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <utility>
37#include <tuple>
38#include <bits/stl_function.h>
39#include <bits/functional_hash.h>
40#if __cplusplus201402L > 201703L
41# include <compare>
42# include <ostream>
43#endif
44
45namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
46{
47_GLIBCXX_BEGIN_NAMESPACE_VERSION
48
49 /**
50 * @addtogroup pointer_abstractions
51 * @{
52 */
53
54#if _GLIBCXX_USE_DEPRECATED1
55#pragma GCC diagnostic push
56#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
57 template<typename> class auto_ptr;
58#pragma GCC diagnostic pop
59#endif
60
61 /// Primary template of default_delete, used by unique_ptr for single objects
62 template<typename _Tp>
63 struct default_delete
64 {
65 /// Default constructor
66 constexpr default_delete() noexcept = default;
67
68 /** @brief Converting constructor.
69 *
70 * Allows conversion from a deleter for objects of another type, `_Up`,
71 * only if `_Up*` is convertible to `_Tp*`.
72 */
73 template<typename _Up,
74 typename = _Require<is_convertible<_Up*, _Tp*>>>
75 default_delete(const default_delete<_Up>&) noexcept { }
76
77 /// Calls `delete __ptr`
78 void
79 operator()(_Tp* __ptr) const
80 {
81 static_assert(!is_void<_Tp>::value,
82 "can't delete pointer to incomplete type");
83 static_assert(sizeof(_Tp)>0,
84 "can't delete pointer to incomplete type");
85 delete __ptr;
86 }
87 };
88
89 // _GLIBCXX_RESOLVE_LIB_DEFECTS
90 // DR 740 - omit specialization for array objects with a compile time length
91
92 /// Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
93 template<typename _Tp>
94 struct default_delete<_Tp[]>
95 {
96 public:
97 /// Default constructor
98 constexpr default_delete() noexcept = default;
99
100 /** @brief Converting constructor.
101 *
102 * Allows conversion from a deleter for arrays of another type, such as
103 * a const-qualified version of `_Tp`.
104 *
105 * Conversions from types derived from `_Tp` are not allowed because
106 * it is undefined to `delete[]` an array of derived types through a
107 * pointer to the base type.
108 */
109 template<typename _Up,
110 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
111 default_delete(const default_delete<_Up[]>&) noexcept { }
112
113 /// Calls `delete[] __ptr`
114 template<typename _Up>
115 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
116 operator()(_Up* __ptr) const
117 {
118 static_assert(sizeof(_Tp)>0,
119 "can't delete pointer to incomplete type");
120 delete [] __ptr;
121 }
122 };
123
124 /// @cond undocumented
125
126 // Manages the pointer and deleter of a unique_ptr
127 template <typename _Tp, typename _Dp>
128 class __uniq_ptr_impl
129 {
130 template <typename _Up, typename _Ep, typename = void>
131 struct _Ptr
132 {
133 using type = _Up*;
134 };
135
136 template <typename _Up, typename _Ep>
137 struct
138 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
139 {
140 using type = typename remove_reference<_Ep>::type::pointer;
141 };
142
143 public:
144 using _DeleterConstraint = enable_if<
145 __and_<__not_<is_pointer<_Dp>>,
146 is_default_constructible<_Dp>>::value>;
147
148 using pointer = typename _Ptr<_Tp, _Dp>::type;
149
150 static_assert( !is_rvalue_reference<_Dp>::value,
151 "unique_ptr's deleter type must be a function object type"
152 " or an lvalue reference type" );
153
154 __uniq_ptr_impl() = default;
155 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
156
157 template<typename _Del>
158 __uniq_ptr_impl(pointer __p, _Del&& __d)
159 : _M_t(__p, std::forward<_Del>(__d)) { }
160
161 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
162 : _M_t(std::move(__u._M_t))
163 { __u._M_ptr() = nullptr; }
164
165 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
166 {
167 reset(__u.release());
168 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
169 return *this;
170 }
171
172 pointer& _M_ptr() { return std::get<0>(_M_t); }
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
174 _Dp& _M_deleter() { return std::get<1>(_M_t); }
175 const _Dp& _M_deleter() const { return std::get<1>(_M_t); }
176
177 void reset(pointer __p) noexcept
178 {
179 const pointer __old_p = _M_ptr();
180 _M_ptr() = __p;
181 if (__old_p)
182 _M_deleter()(__old_p);
183 }
184
185 pointer release() noexcept
186 {
187 pointer __p = _M_ptr();
188 _M_ptr() = nullptr;
189 return __p;
190 }
191
192 void
193 swap(__uniq_ptr_impl& __rhs) noexcept
194 {
195 using std::swap;
196 swap(this->_M_ptr(), __rhs._M_ptr());
197 swap(this->_M_deleter(), __rhs._M_deleter());
198 }
199
200 private:
201 tuple<pointer, _Dp> _M_t;
202 };
203
204 // Defines move construction + assignment as either defaulted or deleted.
205 template <typename _Tp, typename _Dp,
206 bool = is_move_constructible<_Dp>::value,
207 bool = is_move_assignable<_Dp>::value>
208 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
209 {
210 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
211 __uniq_ptr_data(__uniq_ptr_data&&) = default;
212 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
213 };
214
215 template <typename _Tp, typename _Dp>
216 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
217 {
218 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
219 __uniq_ptr_data(__uniq_ptr_data&&) = default;
220 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
221 };
222
223 template <typename _Tp, typename _Dp>
224 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
225 {
226 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
227 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
228 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
229 };
230
231 template <typename _Tp, typename _Dp>
232 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
237 };
238 /// @endcond
239
240 /// 20.7.1.2 unique_ptr for single objects.
241 template <typename _Tp, typename _Dp = default_delete<_Tp>>
242 class unique_ptr
243 {
244 template <typename _Up>
245 using _DeleterConstraint =
246 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
247
248 __uniq_ptr_data<_Tp, _Dp> _M_t;
249
250 public:
251 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
252 using element_type = _Tp;
253 using deleter_type = _Dp;
254
255 private:
256 // helper template for detecting a safe conversion from another
257 // unique_ptr
258 template<typename _Up, typename _Ep>
259 using __safe_conversion_up = __and_<
260 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
261 __not_<is_array<_Up>>
262 >;
263
264 public:
265 // Constructors.
266
267 /// Default constructor, creates a unique_ptr that owns nothing.
268 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
269 constexpr unique_ptr() noexcept
270 : _M_t()
271 { }
272
273 /** Takes ownership of a pointer.
274 *
275 * @param __p A pointer to an object of @c element_type
276 *
277 * The deleter will be value-initialized.
278 */
279 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
280 explicit
281 unique_ptr(pointer __p) noexcept
282 : _M_t(__p)
283 { }
284
285 /** Takes ownership of a pointer.
286 *
287 * @param __p A pointer to an object of @c element_type
288 * @param __d A reference to a deleter.
289 *
290 * The deleter will be initialized with @p __d
291 */
292 template<typename _Del = deleter_type,
293 typename = _Require<is_copy_constructible<_Del>>>
294 unique_ptr(pointer __p, const deleter_type& __d) noexcept
295 : _M_t(__p, __d) { }
296
297 /** Takes ownership of a pointer.
298 *
299 * @param __p A pointer to an object of @c element_type
300 * @param __d An rvalue reference to a (non-reference) deleter.
301 *
302 * The deleter will be initialized with @p std::move(__d)
303 */
304 template<typename _Del = deleter_type,
305 typename = _Require<is_move_constructible<_Del>>>
306 unique_ptr(pointer __p,
307 __enable_if_t<!is_lvalue_reference<_Del>::value,
308 _Del&&> __d) noexcept
309 : _M_t(__p, std::move(__d))
310 { }
311
312 template<typename _Del = deleter_type,
313 typename _DelUnref = typename remove_reference<_Del>::type>
314 unique_ptr(pointer,
315 __enable_if_t<is_lvalue_reference<_Del>::value,
316 _DelUnref&&>) = delete;
317
318 /// Creates a unique_ptr that owns nothing.
319 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
320 constexpr unique_ptr(nullptr_t) noexcept
321 : _M_t()
322 { }
323
324 // Move constructors.
325
326 /// Move constructor.
327 unique_ptr(unique_ptr&&) = default;
328
329 /** @brief Converting constructor from another type
330 *
331 * Requires that the pointer owned by @p __u is convertible to the
332 * type of pointer owned by this object, @p __u does not own an array,
333 * and @p __u has a compatible deleter type.
334 */
335 template<typename _Up, typename _Ep, typename = _Require<
336 __safe_conversion_up<_Up, _Ep>,
337 typename conditional<is_reference<_Dp>::value,
338 is_same<_Ep, _Dp>,
339 is_convertible<_Ep, _Dp>>::type>>
340 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
341 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
342 { }
343
344#if _GLIBCXX_USE_DEPRECATED1
345#pragma GCC diagnostic push
346#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
347 /// Converting constructor from @c auto_ptr
348 template<typename _Up, typename = _Require<
349 is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>>
350 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
351#pragma GCC diagnostic pop
352#endif
353
354 /// Destructor, invokes the deleter if the stored pointer is not null.
355 ~unique_ptr() noexcept
356 {
357 static_assert(__is_invocable<deleter_type&, pointer>::value,
358 "unique_ptr's deleter must be invocable with a pointer");
359 auto& __ptr = _M_t._M_ptr();
360 if (__ptr != nullptr)
361 get_deleter()(std::move(__ptr));
362 __ptr = pointer();
363 }
364
365 // Assignment.
366
367 /** @brief Move assignment operator.
368 *
369 * Invokes the deleter if this object owns a pointer.
370 */
371 unique_ptr& operator=(unique_ptr&&) = default;
372
373 /** @brief Assignment from another type.
374 *
375 * @param __u The object to transfer ownership from, which owns a
376 * convertible pointer to a non-array object.
377 *
378 * Invokes the deleter if this object owns a pointer.
379 */
380 template<typename _Up, typename _Ep>
381 typename enable_if< __and_<
382 __safe_conversion_up<_Up, _Ep>,
383 is_assignable<deleter_type&, _Ep&&>
384 >::value,
385 unique_ptr&>::type
386 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
387 {
388 reset(__u.release());
389 get_deleter() = std::forward<_Ep>(__u.get_deleter());
390 return *this;
391 }
392
393 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
394 unique_ptr&
395 operator=(nullptr_t) noexcept
396 {
397 reset();
398 return *this;
399 }
400
401 // Observers.
402
403 /// Dereference the stored pointer.
404 typename add_lvalue_reference<element_type>::type
405 operator*() const
406 {
407 __glibcxx_assert(get() != pointer());
408 return *get();
409 }
410
411 /// Return the stored pointer.
412 pointer
413 operator->() const noexcept
414 {
415 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
416 return get();
417 }
418
419 /// Return the stored pointer.
420 pointer
421 get() const noexcept
422 { return _M_t._M_ptr(); }
423
424 /// Return a reference to the stored deleter.
425 deleter_type&
426 get_deleter() noexcept
427 { return _M_t._M_deleter(); }
428
429 /// Return a reference to the stored deleter.
430 const deleter_type&
431 get_deleter() const noexcept
432 { return _M_t._M_deleter(); }
433
434 /// Return @c true if the stored pointer is not null.
435 explicit operator bool() const noexcept
436 { return get() == pointer() ? false : true; }
437
438 // Modifiers.
439
440 /// Release ownership of any stored pointer.
441 pointer
442 release() noexcept
443 { return _M_t.release(); }
444
445 /** @brief Replace the stored pointer.
446 *
447 * @param __p The new pointer to store.
448 *
449 * The deleter will be invoked if a pointer is already owned.
450 */
451 void
452 reset(pointer __p = pointer()) noexcept
453 {
454 static_assert(__is_invocable<deleter_type&, pointer>::value,
455 "unique_ptr's deleter must be invocable with a pointer");
456 _M_t.reset(std::move(__p));
457 }
458
459 /// Exchange the pointer and deleter with another object.
460 void
461 swap(unique_ptr& __u) noexcept
462 {
463 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
464 _M_t.swap(__u._M_t);
465 }
466
467 // Disable copy from lvalue.
468 unique_ptr(const unique_ptr&) = delete;
469 unique_ptr& operator=(const unique_ptr&) = delete;
470 };
471
472 /// 20.7.1.3 unique_ptr for array objects with a runtime length
473 // [unique.ptr.runtime]
474 // _GLIBCXX_RESOLVE_LIB_DEFECTS
475 // DR 740 - omit specialization for array objects with a compile time length
476 template<typename _Tp, typename _Dp>
477 class unique_ptr<_Tp[], _Dp>
478 {
479 template <typename _Up>
480 using _DeleterConstraint =
481 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
482
483 __uniq_ptr_data<_Tp, _Dp> _M_t;
484
485 template<typename _Up>
486 using __remove_cv = typename remove_cv<_Up>::type;
487
488 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
489 template<typename _Up>
490 using __is_derived_Tp
491 = __and_< is_base_of<_Tp, _Up>,
492 __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >;
493
494 public:
495 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
496 using element_type = _Tp;
497 using deleter_type = _Dp;
498
499 // helper template for detecting a safe conversion from another
500 // unique_ptr
501 template<typename _Up, typename _Ep,
502 typename _UPtr = unique_ptr<_Up, _Ep>,
503 typename _UP_pointer = typename _UPtr::pointer,
504 typename _UP_element_type = typename _UPtr::element_type>
505 using __safe_conversion_up = __and_<
506 is_array<_Up>,
507 is_same<pointer, element_type*>,
508 is_same<_UP_pointer, _UP_element_type*>,
509 is_convertible<_UP_element_type(*)[], element_type(*)[]>
510 >;
511
512 // helper template for detecting a safe conversion from a raw pointer
513 template<typename _Up>
514 using __safe_conversion_raw = __and_<
515 __or_<__or_<is_same<_Up, pointer>,
516 is_same<_Up, nullptr_t>>,
517 __and_<is_pointer<_Up>,
518 is_same<pointer, element_type*>,
519 is_convertible<
520 typename remove_pointer<_Up>::type(*)[],
521 element_type(*)[]>
522 >
523 >
524 >;
525
526 // Constructors.
527
528 /// Default constructor, creates a unique_ptr that owns nothing.
529 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
530 constexpr unique_ptr() noexcept
531 : _M_t()
532 { }
533
534 /** Takes ownership of a pointer.
535 *
536 * @param __p A pointer to an array of a type safely convertible
537 * to an array of @c element_type
538 *
539 * The deleter will be value-initialized.
540 */
541 template<typename _Up,
542 typename _Vp = _Dp,
543 typename = _DeleterConstraint<_Vp>,
544 typename = typename enable_if<
545 __safe_conversion_raw<_Up>::value, bool>::type>
546 explicit
547 unique_ptr(_Up __p) noexcept
548 : _M_t(__p)
549 { }
550
551 /** Takes ownership of a pointer.
552 *
553 * @param __p A pointer to an array of a type safely convertible
554 * to an array of @c element_type
555 * @param __d A reference to a deleter.
556 *
557 * The deleter will be initialized with @p __d
558 */
559 template<typename _Up, typename _Del = deleter_type,
560 typename = _Require<__safe_conversion_raw<_Up>,
561 is_copy_constructible<_Del>>>
562 unique_ptr(_Up __p, const deleter_type& __d) noexcept
563 : _M_t(__p, __d) { }
564
565 /** Takes ownership of a pointer.
566 *
567 * @param __p A pointer to an array of a type safely convertible
568 * to an array of @c element_type
569 * @param __d A reference to a deleter.
570 *
571 * The deleter will be initialized with @p std::move(__d)
572 */
573 template<typename _Up, typename _Del = deleter_type,
574 typename = _Require<__safe_conversion_raw<_Up>,
575 is_move_constructible<_Del>>>
576 unique_ptr(_Up __p,
577 __enable_if_t<!is_lvalue_reference<_Del>::value,
578 _Del&&> __d) noexcept
579 : _M_t(std::move(__p), std::move(__d))
580 { }
581
582 template<typename _Up, typename _Del = deleter_type,
583 typename _DelUnref = typename remove_reference<_Del>::type,
584 typename = _Require<__safe_conversion_raw<_Up>>>
585 unique_ptr(_Up,
586 __enable_if_t<is_lvalue_reference<_Del>::value,
587 _DelUnref&&>) = delete;
588
589 /// Move constructor.
590 unique_ptr(unique_ptr&&) = default;
591
592 /// Creates a unique_ptr that owns nothing.
593 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
594 constexpr unique_ptr(nullptr_t) noexcept
595 : _M_t()
596 { }
597
598 template<typename _Up, typename _Ep, typename = _Require<
599 __safe_conversion_up<_Up, _Ep>,
600 typename conditional<is_reference<_Dp>::value,
601 is_same<_Ep, _Dp>,
602 is_convertible<_Ep, _Dp>>::type>>
603 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
604 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
605 { }
606
607 /// Destructor, invokes the deleter if the stored pointer is not null.
608 ~unique_ptr()
609 {
610 auto& __ptr = _M_t._M_ptr();
611 if (__ptr != nullptr)
612 get_deleter()(__ptr);
613 __ptr = pointer();
614 }
615
616 // Assignment.
617
618 /** @brief Move assignment operator.
619 *
620 * Invokes the deleter if this object owns a pointer.
621 */
622 unique_ptr&
623 operator=(unique_ptr&&) = default;
624
625 /** @brief Assignment from another type.
626 *
627 * @param __u The object to transfer ownership from, which owns a
628 * convertible pointer to an array object.
629 *
630 * Invokes the deleter if this object owns a pointer.
631 */
632 template<typename _Up, typename _Ep>
633 typename
634 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
635 is_assignable<deleter_type&, _Ep&&>
636 >::value,
637 unique_ptr&>::type
638 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
639 {
640 reset(__u.release());
641 get_deleter() = std::forward<_Ep>(__u.get_deleter());
642 return *this;
643 }
644
645 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
646 unique_ptr&
647 operator=(nullptr_t) noexcept
648 {
649 reset();
650 return *this;
651 }
652
653 // Observers.
654
655 /// Access an element of owned array.
656 typename std::add_lvalue_reference<element_type>::type
657 operator[](size_t __i) const
658 {
659 __glibcxx_assert(get() != pointer());
660 return get()[__i];
661 }
662
663 /// Return the stored pointer.
664 pointer
665 get() const noexcept
666 { return _M_t._M_ptr(); }
667
668 /// Return a reference to the stored deleter.
669 deleter_type&
670 get_deleter() noexcept
671 { return _M_t._M_deleter(); }
672
673 /// Return a reference to the stored deleter.
674 const deleter_type&
675 get_deleter() const noexcept
676 { return _M_t._M_deleter(); }
677
678 /// Return @c true if the stored pointer is not null.
679 explicit operator bool() const noexcept
680 { return get() == pointer() ? false : true; }
681
682 // Modifiers.
683
684 /// Release ownership of any stored pointer.
685 pointer
686 release() noexcept
687 { return _M_t.release(); }
688
689 /** @brief Replace the stored pointer.
690 *
691 * @param __p The new pointer to store.
692 *
693 * The deleter will be invoked if a pointer is already owned.
694 */
695 template <typename _Up,
696 typename = _Require<
697 __or_<is_same<_Up, pointer>,
698 __and_<is_same<pointer, element_type*>,
699 is_pointer<_Up>,
700 is_convertible<
701 typename remove_pointer<_Up>::type(*)[],
702 element_type(*)[]
703 >
704 >
705 >
706 >>
707 void
708 reset(_Up __p) noexcept
709 { _M_t.reset(std::move(__p)); }
710
711 void reset(nullptr_t = nullptr) noexcept
712 { reset(pointer()); }
713
714 /// Exchange the pointer and deleter with another object.
715 void
716 swap(unique_ptr& __u) noexcept
717 {
718 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
719 _M_t.swap(__u._M_t);
720 }
721
722 // Disable copy from lvalue.
723 unique_ptr(const unique_ptr&) = delete;
724 unique_ptr& operator=(const unique_ptr&) = delete;
725 };
726
727 /// @relates unique_ptr @{
728
729 /// Swap overload for unique_ptr
730 template<typename _Tp, typename _Dp>
731 inline
732#if __cplusplus201402L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
733 // Constrained free swap overload, see p0185r1
734 typename enable_if<__is_swappable<_Dp>::value>::type
735#else
736 void
737#endif
738 swap(unique_ptr<_Tp, _Dp>& __x,
739 unique_ptr<_Tp, _Dp>& __y) noexcept
740 { __x.swap(__y); }
741
742#if __cplusplus201402L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11
743 template<typename _Tp, typename _Dp>
744 typename enable_if<!__is_swappable<_Dp>::value>::type
745 swap(unique_ptr<_Tp, _Dp>&,
746 unique_ptr<_Tp, _Dp>&) = delete;
747#endif
748
749 /// Equality operator for unique_ptr objects, compares the owned pointers
750 template<typename _Tp, typename _Dp,
751 typename _Up, typename _Ep>
752 _GLIBCXX_NODISCARD inline bool
753 operator==(const unique_ptr<_Tp, _Dp>& __x,
754 const unique_ptr<_Up, _Ep>& __y)
755 { return __x.get() == __y.get(); }
756
757 /// unique_ptr comparison with nullptr
758 template<typename _Tp, typename _Dp>
759 _GLIBCXX_NODISCARD inline bool
760 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
761 { return !__x; }
762
763#ifndef __cpp_lib_three_way_comparison
764 /// unique_ptr comparison with nullptr
765 template<typename _Tp, typename _Dp>
766 _GLIBCXX_NODISCARD inline bool
767 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
768 { return !__x; }
769
770 /// Inequality operator for unique_ptr objects, compares the owned pointers
771 template<typename _Tp, typename _Dp,
772 typename _Up, typename _Ep>
773 _GLIBCXX_NODISCARD inline bool
774 operator!=(const unique_ptr<_Tp, _Dp>& __x,
775 const unique_ptr<_Up, _Ep>& __y)
776 { return __x.get() != __y.get(); }
777
778 /// unique_ptr comparison with nullptr
779 template<typename _Tp, typename _Dp>
780 _GLIBCXX_NODISCARD inline bool
781 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
782 { return (bool)__x; }
783
784 /// unique_ptr comparison with nullptr
785 template<typename _Tp, typename _Dp>
786 _GLIBCXX_NODISCARD inline bool
787 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
788 { return (bool)__x; }
789#endif // three way comparison
790
791 /// Relational operator for unique_ptr objects, compares the owned pointers
792 template<typename _Tp, typename _Dp,
793 typename _Up, typename _Ep>
794 _GLIBCXX_NODISCARD inline bool
795 operator<(const unique_ptr<_Tp, _Dp>& __x,
796 const unique_ptr<_Up, _Ep>& __y)
797 {
798 typedef typename
799 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
800 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
801 return std::less<_CT>()(__x.get(), __y.get());
802 }
803
804 /// unique_ptr comparison with nullptr
805 template<typename _Tp, typename _Dp>
806 _GLIBCXX_NODISCARD inline bool
807 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
808 {
809 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
810 nullptr);
811 }
812
813 /// unique_ptr comparison with nullptr
814 template<typename _Tp, typename _Dp>
815 _GLIBCXX_NODISCARD inline bool
816 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
817 {
818 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
819 __x.get());
820 }
821
822 /// Relational operator for unique_ptr objects, compares the owned pointers
823 template<typename _Tp, typename _Dp,
824 typename _Up, typename _Ep>
825 _GLIBCXX_NODISCARD inline bool
826 operator<=(const unique_ptr<_Tp, _Dp>& __x,
827 const unique_ptr<_Up, _Ep>& __y)
828 { return !(__y < __x); }
829
830 /// unique_ptr comparison with nullptr
831 template<typename _Tp, typename _Dp>
832 _GLIBCXX_NODISCARD inline bool
833 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
834 { return !(nullptr < __x); }
835
836 /// unique_ptr comparison with nullptr
837 template<typename _Tp, typename _Dp>
838 _GLIBCXX_NODISCARD inline bool
839 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
840 { return !(__x < nullptr); }
841
842 /// Relational operator for unique_ptr objects, compares the owned pointers
843 template<typename _Tp, typename _Dp,
844 typename _Up, typename _Ep>
845 _GLIBCXX_NODISCARD inline bool
846 operator>(const unique_ptr<_Tp, _Dp>& __x,
847 const unique_ptr<_Up, _Ep>& __y)
848 { return (__y < __x); }
849
850 /// unique_ptr comparison with nullptr
851 template<typename _Tp, typename _Dp>
852 _GLIBCXX_NODISCARD inline bool
853 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
854 {
855 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
856 __x.get());
857 }
858
859 /// unique_ptr comparison with nullptr
860 template<typename _Tp, typename _Dp>
861 _GLIBCXX_NODISCARD inline bool
862 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
863 {
864 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
865 nullptr);
866 }
867
868 /// Relational operator for unique_ptr objects, compares the owned pointers
869 template<typename _Tp, typename _Dp,
870 typename _Up, typename _Ep>
871 _GLIBCXX_NODISCARD inline bool
872 operator>=(const unique_ptr<_Tp, _Dp>& __x,
873 const unique_ptr<_Up, _Ep>& __y)
874 { return !(__x < __y); }
875
876 /// unique_ptr comparison with nullptr
877 template<typename _Tp, typename _Dp>
878 _GLIBCXX_NODISCARD inline bool
879 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
880 { return !(__x < nullptr); }
881
882 /// unique_ptr comparison with nullptr
883 template<typename _Tp, typename _Dp>
884 _GLIBCXX_NODISCARD inline bool
885 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
886 { return !(nullptr < __x); }
887
888#ifdef __cpp_lib_three_way_comparison
889 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
890 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
891 typename unique_ptr<_Up, _Ep>::pointer>
892 inline
893 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
894 typename unique_ptr<_Up, _Ep>::pointer>
895 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
896 const unique_ptr<_Up, _Ep>& __y)
897 { return compare_three_way()(__x.get(), __y.get()); }
898
899 template<typename _Tp, typename _Dp>
900 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
901 inline
902 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
903 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
904 {
905 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
906 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
907 }
908#endif
909 // @} relates unique_ptr
910
911 /// @cond undocumented
912 template<typename _Up, typename _Ptr = typename _Up::pointer,
913 bool = __poison_hash<_Ptr>::__enable_hash_call>
914 struct __uniq_ptr_hash
915#if ! _GLIBCXX_INLINE_VERSION0
916 : private __poison_hash<_Ptr>
917#endif
918 {
919 size_t
920 operator()(const _Up& __u) const
921 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
922 { return hash<_Ptr>()(__u.get()); }
923 };
924
925 template<typename _Up, typename _Ptr>
926 struct __uniq_ptr_hash<_Up, _Ptr, false>
927 : private __poison_hash<_Ptr>
928 { };
929 /// @endcond
930
931 /// std::hash specialization for unique_ptr.
932 template<typename _Tp, typename _Dp>
933 struct hash<unique_ptr<_Tp, _Dp>>
934 : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>,
935 public __uniq_ptr_hash<unique_ptr<_Tp, _Dp>>
936 { };
937
938#if __cplusplus201402L >= 201402L
939 /// @relates unique_ptr @{
940#define __cpp_lib_make_unique201304 201304
941
942 /// @cond undocumented
943
944 template<typename _Tp>
945 struct _MakeUniq
946 { typedef unique_ptr<_Tp> __single_object; };
947
948 template<typename _Tp>
949 struct _MakeUniq<_Tp[]>
950 { typedef unique_ptr<_Tp[]> __array; };
951
952 template<typename _Tp, size_t _Bound>
953 struct _MakeUniq<_Tp[_Bound]>
954 { struct __invalid_type { }; };
955
956 /// @endcond
957
958 /// std::make_unique for single objects
959 template<typename _Tp, typename... _Args>
960 inline typename _MakeUniq<_Tp>::__single_object
961 make_unique(_Args&&... __args)
962 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
17
Calling constructor for 'AttrsValueIterator'
963
964 /// std::make_unique for arrays of unknown bound
965 template<typename _Tp>
966 inline typename _MakeUniq<_Tp>::__array
967 make_unique(size_t __num)
968 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
969
970 /// Disable std::make_unique for arrays of known bound
971 template<typename _Tp, typename... _Args>
972 inline typename _MakeUniq<_Tp>::__invalid_type
973 make_unique(_Args&&...) = delete;
974 // @} relates unique_ptr
975#endif // C++14
976
977#if __cplusplus201402L > 201703L && __cpp_concepts
978 // _GLIBCXX_RESOLVE_LIB_DEFECTS
979 // 2948. unique_ptr does not define operator<< for stream output
980 /// Stream output operator for unique_ptr
981 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
982 inline basic_ostream<_CharT, _Traits>&
983 operator<<(basic_ostream<_CharT, _Traits>& __os,
984 const unique_ptr<_Tp, _Dp>& __p)
985 requires requires { __os << __p.get(); }
986 {
987 __os << __p.get();
988 return __os;
989 }
990#endif // C++20
991
992 // @} group pointer_abstractions
993
994#if __cplusplus201402L >= 201703L
995 namespace __detail::__variant
996 {
997 template<typename> struct _Never_valueless_alt; // see <variant>
998
999 // Provide the strong exception-safety guarantee when emplacing a
1000 // unique_ptr into a variant.
1001 template<typename _Tp, typename _Del>
1002 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1003 : std::true_type
1004 { };
1005 } // namespace __detail::__variant
1006#endif // C++17
1007
1008_GLIBCXX_END_NAMESPACE_VERSION
1009} // namespace
1010
1011#endif /* _UNIQUE_PTR_H */

/opt/pyrefcon/lib/pyrefcon/models/models/PyObject_GetAttrString.model

1#ifndef PyObject_GetAttrString
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name) {
6 return clang_analyzer_PyObject_New_Reference();
21
Setting reference count to 1
7}
8#else
9#warning "API PyObject_GetAttrString is defined as a macro."
10#endif