| // Copyright 2018 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_CAST_H_ | |
| #define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_CAST_H_ | |
| #include "src/developer/debug/zxdb/expr/eval_callback.h" | |
| #include "src/developer/debug/zxdb/expr/expr_value.h" | |
| #include "src/lib/fxl/memory/ref_ptr.h" | |
| namespace zxdb { | |
| class Err; | |
| class EvalContext; | |
| class ExprValue; | |
| class Type; | |
| // Our casting rules are somewhat different than C++. In a debugger, we want to be as permissive as | |
| // reasonable given the rules of the requested cast. When the user is interactively assigning or | |
| // converting values, they usually don't want the warnings and errors that come with C++. | |
| enum class CastType { | |
| // Implicit casts are for expressions like "double d = (float)f"; | |
| // | |
| // Any number can be converted to any other number, even if the sign is different, it is | |
| // truncated, or there is a float/integer mismatch. Pointers can be converted back-and-forth to | |
| // integers as long as the sizes match. Composite types can be copied if the type names and sizes | |
| // match (the type objects don't necessarily need to point to the same thing because | |
| // we can easily get different definitions of the same type). | |
| kImplicit, | |
| // A C-style cast: "(int)foo;". | |
| // | |
| // This attempts a static_cast and falls back to reinterpret_cast. | |
| kC, | |
| // Converts pointer types. | |
| // | |
| // Our rules are more lax than C++, allowing any conversion that can be reasonable executed. C++ | |
| // will, for example, prohibit conversion of a 32-bit integer to a 64-bit pointer, but if the user | |
| // types "reinterpret_cast<char*>(0x12343567)" we want the debugger to be able to execute. | |
| kReinterpret, | |
| // A Rust-style cast: "foo as bar;". | |
| // | |
| // The expected behaviors of this type of cast are documented here: | |
| // | |
| // https://doc.rust-lang.org/nomicon/casts.html | |
| kRust, | |
| // Compared to C++, the debugger's implicit cast is so powerful that the only thing that | |
| // static_cast adds is conversions to derived classes for pointers and references. | |
| kStatic | |
| // We don't bother implementing const_cast and dynamic_cast yet because they're less useful in a | |
| // debugger. | |
| }; | |
| const char* CastTypeToString(CastType); | |
| // Casts to a given type using a specific set of casting rules. | |
| // | |
| // The dest_source is an optional specification of what "source location" the returned value should | |
| // have. For the default behavior, use an empty ExprValueSource(). | |
| void CastExprValue(const fxl::RefPtr<EvalContext>& eval_context, CastType cast_type, | |
| const ExprValue& source, const fxl::RefPtr<Type>& dest_type, | |
| const ExprValueSource& dest_source, EvalCallback cb); | |
| // A numeric cast handles implicit casts of numeric types. This subset of casting can be synchronous | |
| // because it does not need to follow references or virtual inheritance. | |
| ErrOrValue CastNumericExprValue(const fxl::RefPtr<EvalContext>& eval_context, | |
| const ExprValue& source, const fxl::RefPtr<Type>& dest_type, | |
| const ExprValueSource& dest_source = ExprValueSource()); | |
| // Convience function around CastNumericExprValue() to do an implicit cast to a boolean value. Like | |
| // CastNumericExprValue(), this does not follow references. | |
| ErrOr<bool> CastNumericExprValueToBool(const fxl::RefPtr<EvalContext>& eval_context, | |
| const ExprValue& source); | |
| } // namespace zxdb | |
| #endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_CAST_H_ |