Bug Summary

File:tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
Warning:line 273, column 7
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name GoUserExpression.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -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 -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D HAVE_ROUND -D LLDB_CONFIGURATION_RELEASE -D LLDB_USE_BUILTIN_DEMANGLER -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn326551/tools/lldb/source/Plugins/ExpressionParser/Go -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326551/tools/lldb/include -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn326551/include -I /usr/include/python2.7 -I /build/llvm-toolchain-snapshot-7~svn326551/tools/clang/include -I /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-7~svn326551/tools/lldb/source/. -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn326551/build-llvm/tools/lldb/source/Plugins/ExpressionParser/Go -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-03-02-155150-1477-1 -x c++ /build/llvm-toolchain-snapshot-7~svn326551/tools/lldb/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
1//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13#include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <memory>
19#include <string>
20#include <vector>
21
22// Other libraries and framework includes
23#include "llvm/ADT/StringMap.h"
24#include "llvm/ADT/StringRef.h"
25
26// Project includes
27#include "GoUserExpression.h"
28
29#include "lldb/Core/Module.h"
30#include "lldb/Core/StreamFile.h"
31#include "lldb/Core/ValueObjectConstResult.h"
32#include "lldb/Core/ValueObjectRegister.h"
33#include "lldb/Expression/DiagnosticManager.h"
34#include "lldb/Expression/ExpressionVariable.h"
35#include "lldb/Symbol/GoASTContext.h"
36#include "lldb/Symbol/SymbolFile.h"
37#include "lldb/Symbol/TypeList.h"
38#include "lldb/Symbol/VariableList.h"
39#include "lldb/Target/ExecutionContext.h"
40#include "lldb/Target/Process.h"
41#include "lldb/Target/RegisterContext.h"
42#include "lldb/Target/StackFrame.h"
43#include "lldb/Target/Target.h"
44#include "lldb/Target/ThreadPlan.h"
45#include "lldb/Target/ThreadPlanCallUserExpression.h"
46#include "lldb/Utility/ConstString.h"
47#include "lldb/Utility/DataBufferHeap.h"
48#include "lldb/Utility/DataEncoder.h"
49#include "lldb/Utility/DataExtractor.h"
50#include "lldb/Utility/Log.h"
51#include "lldb/Utility/StreamString.h"
52#include "lldb/lldb-private.h"
53
54#include "Plugins/ExpressionParser/Go/GoAST.h"
55#include "Plugins/ExpressionParser/Go/GoParser.h"
56
57using namespace lldb_private;
58using namespace lldb;
59
60class GoUserExpression::GoInterpreter {
61public:
62 GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
63 : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) {
64 if (m_frame) {
65 const SymbolContext &ctx =
66 m_frame->GetSymbolContext(eSymbolContextFunction);
67 ConstString fname = ctx.GetFunctionName();
68 if (fname.GetLength() > 0) {
69 size_t dot = fname.GetStringRef().find('.');
70 if (dot != llvm::StringRef::npos)
71 m_package = llvm::StringRef(fname.AsCString(), dot);
72 }
73 }
74 }
75
76 void set_use_dynamic(DynamicValueType use_dynamic) {
77 m_use_dynamic = use_dynamic;
78 }
79
80 bool Parse();
81 lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
82 lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
83 lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);
84
85 ValueObjectSP VisitBadExpr(const GoASTBadExpr *e) {
86 m_parser.GetError(m_error);
87 return nullptr;
88 }
89
90 ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
91 ValueObjectSP VisitIdent(const GoASTIdent *e);
92 ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
93 ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
94 ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
95 ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
96 ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
97 ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);
98
99 ValueObjectSP VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) {
100 return NotImplemented(e);
101 }
102
103 ValueObjectSP VisitBinaryExpr(const GoASTBinaryExpr *e) {
104 return NotImplemented(e);
105 }
106
107 ValueObjectSP VisitArrayType(const GoASTArrayType *e) {
108 return NotImplemented(e);
109 }
110
111 ValueObjectSP VisitChanType(const GoASTChanType *e) {
112 return NotImplemented(e);
113 }
114
115 ValueObjectSP VisitCompositeLit(const GoASTCompositeLit *e) {
116 return NotImplemented(e);
117 }
118
119 ValueObjectSP VisitEllipsis(const GoASTEllipsis *e) {
120 return NotImplemented(e);
121 }
122
123 ValueObjectSP VisitFuncType(const GoASTFuncType *e) {
124 return NotImplemented(e);
125 }
126
127 ValueObjectSP VisitFuncLit(const GoASTFuncLit *e) {
128 return NotImplemented(e);
129 }
130
131 ValueObjectSP VisitInterfaceType(const GoASTInterfaceType *e) {
132 return NotImplemented(e);
133 }
134
135 ValueObjectSP VisitKeyValueExpr(const GoASTKeyValueExpr *e) {
136 return NotImplemented(e);
137 }
138
139 ValueObjectSP VisitMapType(const GoASTMapType *e) {
140 return NotImplemented(e);
141 }
142
143 ValueObjectSP VisitSliceExpr(const GoASTSliceExpr *e) {
144 return NotImplemented(e);
145 }
146
147 ValueObjectSP VisitStructType(const GoASTStructType *e) {
148 return NotImplemented(e);
149 }
150
151 CompilerType EvaluateType(const GoASTExpr *e);
152
153 Status &error() { return m_error; }
154
155private:
156 std::nullptr_t NotImplemented(const GoASTExpr *e) {
157 m_error.SetErrorStringWithFormat("%s node not implemented",
158 e->GetKindName());
159 return nullptr;
160 }
161
162 ExecutionContext m_exe_ctx;
163 lldb::StackFrameSP m_frame;
164 GoParser m_parser;
165 DynamicValueType m_use_dynamic;
166 Status m_error;
167 llvm::StringRef m_package;
168 std::vector<std::unique_ptr<GoASTStmt>> m_statements;
169};
170
171VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) {
172 ConstString fullname(name.str());
173 VariableList variable_list;
174 const bool append = true;
175 if (!target) {
176 return nullptr;
177 }
178 const uint32_t match_count = target->GetImages().FindGlobalVariables(
179 fullname, append, 1, variable_list);
180 if (match_count == 1) {
181 return variable_list.GetVariableAtIndex(0);
182 }
183 return nullptr;
184}
185
186CompilerType LookupType(TargetSP target, ConstString name) {
187 if (!target)
188 return CompilerType();
189 SymbolContext sc;
190 TypeList type_list;
191 llvm::DenseSet<SymbolFile *> searched_symbol_files;
192 uint32_t num_matches = target->GetImages().FindTypes(
193 sc, name, false, 2, searched_symbol_files, type_list);
194 if (num_matches > 0) {
195 return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
196 }
197 return CompilerType();
198}
199
200GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope,
201 llvm::StringRef expr, llvm::StringRef prefix,
202 lldb::LanguageType language,
203 ResultType desired_type,
204 const EvaluateExpressionOptions &options)
205 : UserExpression(exe_scope, expr, prefix, language, desired_type, options) {
206}
207
208bool GoUserExpression::Parse(DiagnosticManager &diagnostic_manager,
209 ExecutionContext &exe_ctx,
210 lldb_private::ExecutionPolicy execution_policy,
211 bool keep_result_in_memory,
212 bool generate_debug_info) {
213 InstallContext(exe_ctx);
214 m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
215 if (m_interpreter->Parse())
216 return true;
217 const char *error_cstr = m_interpreter->error().AsCString();
218 if (error_cstr && error_cstr[0])
219 diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
220 else
221 diagnostic_manager.Printf(eDiagnosticSeverityError,
222 "expression can't be interpreted or run");
223 return false;
224}
225
226lldb::ExpressionResults
227GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
228 ExecutionContext &exe_ctx,
229 const EvaluateExpressionOptions &options,
230 lldb::UserExpressionSP &shared_ptr_to_me,
231 lldb::ExpressionVariableSP &result) {
232 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8) |
233 LIBLLDB_LOG_STEP(1u << 7)));
234
235 lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
236 lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
237
238 Process *process = exe_ctx.GetProcessPtr();
239 Target *target = exe_ctx.GetTargetPtr();
1
'target' initialized here
240
241 if (target == nullptr || process == nullptr ||
2
Assuming pointer value is null
242 process->GetState() != lldb::eStateStopped) {
243 if (execution_policy == eExecutionPolicyAlways) {
3
Assuming 'execution_policy' is not equal to eExecutionPolicyAlways
4
Taking false branch
244 if (log)
245 log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
246 "but is not constant ==");
247
248 diagnostic_manager.PutString(eDiagnosticSeverityError,
249 "expression needed to run but couldn't");
250
251 return execution_results;
252 }
253 }
254
255 m_interpreter->set_use_dynamic(options.GetUseDynamic());
256 ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
257 Status err = m_interpreter->error();
258 m_interpreter.reset();
259
260 if (!result_val_sp) {
5
Assuming the condition is false
6
Taking false branch
261 const char *error_cstr = err.AsCString();
262 if (error_cstr && error_cstr[0])
263 diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
264 else
265 diagnostic_manager.PutString(eDiagnosticSeverityError,
266 "expression can't be interpreted or run");
267 return lldb::eExpressionDiscarded;
268 }
269 result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
270 result->m_live_sp = result->m_frozen_sp = result_val_sp;
271 result->m_flags |= ExpressionVariable::EVIsProgramReference;
272 PersistentExpressionState *pv =
273 target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
7
Called C++ object pointer is null
274 if (pv != nullptr) {
275 result->SetName(pv->GetNextPersistentVariableName());
276 pv->AddVariable(result);
277 }
278 return lldb::eExpressionCompleted;
279}
280
281bool GoUserExpression::GoInterpreter::Parse() {
282 for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt;
283 stmt.reset(m_parser.Statement())) {
284 if (m_parser.Failed())
285 break;
286 m_statements.emplace_back(std::move(stmt));
287 }
288 if (m_parser.Failed() || !m_parser.AtEOF())
289 m_parser.GetError(m_error);
290
291 return m_error.Success();
292}
293
294ValueObjectSP
295GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) {
296 m_exe_ctx = exe_ctx;
297 ValueObjectSP result;
298 for (const std::unique_ptr<GoASTStmt> &stmt : m_statements) {
299 result = EvaluateStatement(stmt.get());
300 if (m_error.Fail())
301 return nullptr;
302 }
303 return result;
304}
305
306ValueObjectSP GoUserExpression::GoInterpreter::EvaluateStatement(
307 const lldb_private::GoASTStmt *stmt) {
308 ValueObjectSP result;
309 switch (stmt->GetKind()) {
310 case GoASTNode::eBlockStmt: {
311 const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
312 for (size_t i = 0; i < block->NumList(); ++i)
313 result = EvaluateStatement(block->GetList(i));
314 break;
315 }
316 case GoASTNode::eBadStmt:
317 m_parser.GetError(m_error);
318 break;
319 case GoASTNode::eExprStmt: {
320 const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
321 return EvaluateExpr(expr->GetX());
322 }
323 default:
324 m_error.SetErrorStringWithFormat("%s node not supported",
325 stmt->GetKindName());
326 }
327 return result;
328}
329
330ValueObjectSP GoUserExpression::GoInterpreter::EvaluateExpr(
331 const lldb_private::GoASTExpr *e) {
332 if (e)
333 return e->Visit<ValueObjectSP>(this);
334 return ValueObjectSP();
335}
336
337ValueObjectSP GoUserExpression::GoInterpreter::VisitParenExpr(
338 const lldb_private::GoASTParenExpr *e) {
339 return EvaluateExpr(e->GetX());
340}
341
342ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) {
343 ValueObjectSP val;
344 if (m_frame) {
345 VariableSP var_sp;
346 std::string varname = e->GetName().m_value.str();
347 if (varname.size() > 1 && varname[0] == '$') {
348 RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
349 const RegisterInfo *reg =
350 reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
351 if (reg) {
352 std::string type;
353 switch (reg->encoding) {
354 case lldb::eEncodingSint:
355 type.append("int");
356 break;
357 case lldb::eEncodingUint:
358 type.append("uint");
359 break;
360 case lldb::eEncodingIEEE754:
361 type.append("float");
362 break;
363 default:
364 m_error.SetErrorString("Invalid register encoding");
365 return nullptr;
366 }
367 switch (reg->byte_size) {
368 case 8:
369 type.append("64");
370 break;
371 case 4:
372 type.append("32");
373 break;
374 case 2:
375 type.append("16");
376 break;
377 case 1:
378 type.append("8");
379 break;
380 default:
381 m_error.SetErrorString("Invalid register size");
382 return nullptr;
383 }
384 ValueObjectSP regVal = ValueObjectRegister::Create(
385 m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
386 CompilerType goType =
387 LookupType(m_frame->CalculateTarget(), ConstString(type));
388 if (regVal) {
389 regVal = regVal->Cast(goType);
390 return regVal;
391 }
392 }
393 m_error.SetErrorString("Invalid register name");
394 return nullptr;
395 }
396 VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
397 if (var_list_sp) {
398 var_sp = var_list_sp->FindVariable(ConstString(varname));
399 if (var_sp)
400 val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
401 else {
402 // When a variable is on the heap instead of the stack, go records a
403 // variable
404 // '&x' instead of 'x'.
405 var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
406 if (var_sp) {
407 val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
408 if (val)
409 val = val->Dereference(m_error);
410 if (m_error.Fail())
411 return nullptr;
412 }
413 }
414 }
415 if (!val) {
416 m_error.Clear();
417 TargetSP target = m_frame->CalculateTarget();
418 if (!target) {
419 m_error.SetErrorString("No target");
420 return nullptr;
421 }
422 var_sp =
423 FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
424 if (var_sp)
425 return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
426 }
427 }
428 if (!val)
429 m_error.SetErrorStringWithFormat("Unknown variable %s",
430 e->GetName().m_value.str().c_str());
431 return val;
432}
433
434ValueObjectSP
435GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) {
436 ValueObjectSP target = EvaluateExpr(e->GetX());
437 if (!target)
438 return nullptr;
439 return target->Dereference(m_error);
440}
441
442ValueObjectSP GoUserExpression::GoInterpreter::VisitSelectorExpr(
443 const lldb_private::GoASTSelectorExpr *e) {
444 ValueObjectSP target = EvaluateExpr(e->GetX());
445 if (target) {
446 if (target->GetCompilerType().IsPointerType()) {
447 target = target->Dereference(m_error);
448 if (m_error.Fail())
449 return nullptr;
450 }
451 ConstString field(e->GetSel()->GetName().m_value);
452 ValueObjectSP result = target->GetChildMemberWithName(field, true);
453 if (!result)
454 m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
455 return result;
456 }
457 if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) {
458 if (VariableSP global = FindGlobalVariable(
459 m_exe_ctx.GetTargetSP(), package->GetName().m_value + "." +
460 e->GetSel()->GetName().m_value)) {
461 if (m_frame) {
462 m_error.Clear();
463 return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
464 }
465 }
466 }
467 if (const GoASTBasicLit *packageLit =
468 llvm::dyn_cast<GoASTBasicLit>(e->GetX())) {
469 if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) {
470 std::string value = packageLit->GetValue().m_value.str();
471 value = value.substr(1, value.size() - 2);
472 if (VariableSP global = FindGlobalVariable(
473 m_exe_ctx.GetTargetSP(),
474 value + "." + e->GetSel()->GetName().m_value)) {
475 if (m_frame) {
476 m_error.Clear();
477 return m_frame->TrackGlobalVariable(global, m_use_dynamic);
478 }
479 }
480 }
481 }
482 // EvaluateExpr should have already set m_error.
483 return target;
484}
485
486ValueObjectSP GoUserExpression::GoInterpreter::VisitBasicLit(
487 const lldb_private::GoASTBasicLit *e) {
488 std::string value = e->GetValue().m_value.str();
489 if (e->GetValue().m_type != GoLexer::LIT_INTEGER) {
490 m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
491 return nullptr;
492 }
493 errno(*__errno_location ()) = 0;
494 int64_t intvalue = strtol(value.c_str(), nullptr, 0);
495 if (errno(*__errno_location ()) != 0) {
496 m_error.SetErrorToErrno();
497 return nullptr;
498 }
499 DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
500 TargetSP target = m_exe_ctx.GetTargetSP();
501 if (!target) {
502 m_error.SetErrorString("No target");
503 return nullptr;
504 }
505 ByteOrder order = target->GetArchitecture().GetByteOrder();
506 uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
507 DataEncoder enc(buf, order, addr_size);
508 enc.PutU64(0, static_cast<uint64_t>(intvalue));
509 DataExtractor data(buf, order, addr_size);
510
511 CompilerType type = LookupType(target, ConstString("int64"));
512 return ValueObject::CreateValueObjectFromData(llvm::StringRef(), data,
513 m_exe_ctx, type);
514}
515
516ValueObjectSP GoUserExpression::GoInterpreter::VisitIndexExpr(
517 const lldb_private::GoASTIndexExpr *e) {
518 ValueObjectSP target = EvaluateExpr(e->GetX());
519 if (!target)
520 return nullptr;
521 ValueObjectSP index = EvaluateExpr(e->GetIndex());
522 if (!index)
523 return nullptr;
524 bool is_signed;
525 if (!index->GetCompilerType().IsIntegerType(is_signed)) {
526 m_error.SetErrorString("Unsupported index");
527 return nullptr;
528 }
529 size_t idx;
530 if (is_signed)
531 idx = index->GetValueAsSigned(0);
532 else
533 idx = index->GetValueAsUnsigned(0);
534 if (GoASTContext::IsGoSlice(target->GetCompilerType())) {
535 target = target->GetStaticValue();
536 ValueObjectSP cap =
537 target->GetChildMemberWithName(ConstString("cap"), true);
538 if (cap) {
539 uint64_t capval = cap->GetValueAsUnsigned(0);
540 if (idx >= capval) {
541 m_error.SetErrorStringWithFormat("Invalid index %" PRIu64"l" "u"
542 " , cap = %" PRIu64"l" "u",
543 uint64_t(idx), capval);
544 return nullptr;
545 }
546 }
547 target = target->GetChildMemberWithName(ConstString("array"), true);
548 if (target && m_use_dynamic != eNoDynamicValues) {
549 ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
550 if (dynamic)
551 target = dynamic;
552 }
553 if (!target)
554 return nullptr;
555 return target->GetSyntheticArrayMember(idx, true);
556 }
557 return target->GetChildAtIndex(idx, true);
558}
559
560ValueObjectSP
561GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) {
562 ValueObjectSP x = EvaluateExpr(e->GetX());
563 if (!x)
564 return nullptr;
565 switch (e->GetOp()) {
566 case GoLexer::OP_AMP: {
567 CompilerType type = x->GetCompilerType().GetPointerType();
568 uint64_t address = x->GetAddressOf();
569 return ValueObject::CreateValueObjectFromAddress(llvm::StringRef(), address,
570 m_exe_ctx, type);
571 }
572 case GoLexer::OP_PLUS:
573 return x;
574 default:
575 m_error.SetErrorStringWithFormat(
576 "Operator %s not supported",
577 GoLexer::LookupToken(e->GetOp()).str().c_str());
578 return nullptr;
579 }
580}
581
582CompilerType GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) {
583 TargetSP target = m_exe_ctx.GetTargetSP();
584 if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) {
585 CompilerType result =
586 LookupType(target, ConstString(id->GetName().m_value));
587 if (result.IsValid())
588 return result;
589 std::string fullname = (m_package + "." + id->GetName().m_value).str();
590 result = LookupType(target, ConstString(fullname));
591 if (!result)
592 m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
593 return result;
594 }
595 if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) {
596 std::string package;
597 if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) {
598 package = pkg_node->GetName().m_value.str();
599 } else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) {
600 if (str_node->GetValue().m_type == GoLexer::LIT_STRING) {
601 package = str_node->GetValue().m_value.substr(1).str();
602 package.resize(package.length() - 1);
603 }
604 }
605 if (package.empty()) {
606 m_error.SetErrorStringWithFormat("Invalid %s in type expression",
607 sel->GetX()->GetKindName());
608 return CompilerType();
609 }
610 std::string fullname =
611 (package + "." + sel->GetSel()->GetName().m_value).str();
612 CompilerType result = LookupType(target, ConstString(fullname));
613 if (!result)
614 m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
615 return result;
616 }
617 if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) {
618 CompilerType elem = EvaluateType(star->GetX());
619 return elem.GetPointerType();
620 }
621 if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
622 return EvaluateType(paren->GetX());
623 if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) {
624 CompilerType elem = EvaluateType(array->GetElt());
625 }
626
627 m_error.SetErrorStringWithFormat("Invalid %s in type expression",
628 e->GetKindName());
629 return CompilerType();
630}
631
632ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr(
633 const lldb_private::GoASTCallExpr *e) {
634 ValueObjectSP x = EvaluateExpr(e->GetFun());
635 if (x || e->NumArgs() != 1) {
636 m_error.SetErrorStringWithFormat("Code execution not supported");
637 return nullptr;
638 }
639 m_error.Clear();
640 CompilerType type = EvaluateType(e->GetFun());
641 if (!type) {
642 return nullptr;
643 }
644 ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
645 if (!value)
646 return nullptr;
647 // TODO: Handle special conversions
648 return value->Cast(type);
649}
650
651GoPersistentExpressionState::GoPersistentExpressionState()
652 : PersistentExpressionState(eKindGo) {}
653
654ConstString GoPersistentExpressionState::GetNextPersistentVariableName() {
655 char name_cstr[256];
656 // We can't use the same variable format as clang.
657 ::snprintf(name_cstr, sizeof(name_cstr), "$go%u",
658 m_next_persistent_variable_id++);
659 ConstString name(name_cstr);
660 return name;
661}
662
663void GoPersistentExpressionState::RemovePersistentVariable(
664 lldb::ExpressionVariableSP variable) {
665 RemoveVariable(variable);
666
667 const char *name = variable->GetName().AsCString();
668
669 if (*(name++) != '$')
670 return;
671 if (*(name++) != 'g')
672 return;
673 if (*(name++) != 'o')
674 return;
675
676 if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1)
677 m_next_persistent_variable_id--;
678}