Summary:
Currently our expression evaluators only prints very basic errors that are not very useful when writing complex expressions.
For example, in the expression below the user made a type error, but it's not clear from the diagnostic what went wrong:
```
(lldb) expr printf("Modulos are:", foobar%mo1, foobar%mo2, foobar%mo3)
error: invalid operands to binary expression ('int' and 'double')
```
This patch enables full Clang diagnostics in our expression evaluator. After this patch the diagnostics for the expression look like this:
```
(lldb) expr printf("Modulos are:", foobar%mo1, foobar%mo2, foobar%mo3)
error: <user expression 1>:1:54: invalid operands to binary expression ('int' and 'float')
printf("Modulos are:", foobar%mo1, foobar%mo2, foobar%mo3)
~~~~~~^~~~
```
To make this possible, we now emulate a user expression file within our diagnostics. This prevents that the user is exposed to
our internal wrapper code we inject.
Note that the diagnostics that refer to declarations from the debug information (e.g. 'note' diagnostics pointing to a called function)
will not be improved by this as they don't have any source locations associated with them, so caret or line printing isn't possible.
We instead just suppress these diagnostics as we already do with warnings as they would otherwise just be a context message
without any context (and the original diagnostic in the user expression should be enough to explain the issue).
Fixes rdar://24306342
Reviewers: JDevlieghere, aprantl, shafik, #lldb
Reviewed By: JDevlieghere, #lldb
Subscribers: usaxena95, davide, jingham, aprantl, arphaman, kadircet, lldb-commits
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D65646
llvm-svn: 372203
96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
//===-- ClangPersistentVariables.h ------------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef liblldb_ClangPersistentVariables_h_
|
|
#define liblldb_ClangPersistentVariables_h_
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
|
|
#include "ClangExpressionVariable.h"
|
|
#include "ClangModulesDeclVendor.h"
|
|
|
|
#include "lldb/Expression/ExpressionVariable.h"
|
|
|
|
namespace lldb_private {
|
|
|
|
/// \class ClangPersistentVariables ClangPersistentVariables.h
|
|
/// "lldb/Expression/ClangPersistentVariables.h" Manages persistent values
|
|
/// that need to be preserved between expression invocations.
|
|
///
|
|
/// A list of variables that can be accessed and updated by any expression. See
|
|
/// ClangPersistentVariable for more discussion. Also provides an increasing,
|
|
/// 0-based counter for naming result variables.
|
|
class ClangPersistentVariables : public PersistentExpressionState {
|
|
public:
|
|
ClangPersistentVariables();
|
|
|
|
~ClangPersistentVariables() override = default;
|
|
|
|
// llvm casting support
|
|
static bool classof(const PersistentExpressionState *pv) {
|
|
return pv->getKind() == PersistentExpressionState::eKindClang;
|
|
}
|
|
|
|
lldb::ExpressionVariableSP
|
|
CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) override;
|
|
|
|
lldb::ExpressionVariableSP CreatePersistentVariable(
|
|
ExecutionContextScope *exe_scope, ConstString name,
|
|
const CompilerType &compiler_type, lldb::ByteOrder byte_order,
|
|
uint32_t addr_byte_size) override;
|
|
|
|
void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
|
|
|
|
llvm::StringRef GetPersistentVariablePrefix(bool is_error) const override {
|
|
return "$";
|
|
}
|
|
|
|
/// Returns the next file name that should be used for user expressions.
|
|
std::string GetNextExprFileName() {
|
|
std::string name;
|
|
name.append("<user expression ");
|
|
name.append(std::to_string(m_next_user_file_id++));
|
|
name.append(">");
|
|
return name;
|
|
}
|
|
|
|
llvm::Optional<CompilerType>
|
|
GetCompilerTypeFromPersistentDecl(ConstString type_name) override;
|
|
|
|
void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl);
|
|
|
|
clang::NamedDecl *GetPersistentDecl(ConstString name);
|
|
|
|
void AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) {
|
|
m_hand_loaded_clang_modules.push_back(module);
|
|
}
|
|
|
|
const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() {
|
|
return m_hand_loaded_clang_modules;
|
|
}
|
|
|
|
private:
|
|
/// The counter used by GetNextExprFileName.
|
|
uint32_t m_next_user_file_id = 0;
|
|
// The counter used by GetNextPersistentVariableName
|
|
uint32_t m_next_persistent_variable_id = 0;
|
|
|
|
typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap;
|
|
PersistentDeclMap
|
|
m_persistent_decls; ///< Persistent entities declared by the user.
|
|
|
|
ClangModulesDeclVendor::ModuleVector
|
|
m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded;
|
|
///these are the highest-
|
|
///< priority source for macros.
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // liblldb_ClangPersistentVariables_h_
|