diff options
Diffstat (limited to 'source/Plugins/ExpressionParser')
26 files changed, 652 insertions, 524 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 9e6a2f3acafe..fa49a51f32a6 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -226,8 +226,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, return true; // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off - // if that's the - // case. + // if that's the case. do { ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr); @@ -242,8 +241,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, } while (0); // is_lvalue is used to record whether the expression returns an assignable - // Lvalue or an - // Rvalue. This is relevant because they are handled differently. + // Lvalue or an Rvalue. This is relevant because they are handled + // differently. // // For Lvalues // @@ -293,9 +292,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, // // - During dematerialization, $0 is ignored. - bool is_lvalue = (last_expr->getValueKind() == VK_LValue || - last_expr->getValueKind() == VK_XValue) && - (last_expr->getObjectKind() == OK_Ordinary); + bool is_lvalue = last_expr->getValueKind() == VK_LValue && + last_expr->getObjectKind() == OK_Ordinary; QualType expr_qual_type = last_expr->getType(); const clang::Type *expr_type = expr_qual_type.getTypePtr(); diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h index c0e6c0358a23..859a1dfa5f73 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -18,18 +18,17 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ASTResultSynthesizer ASTResultSynthesizer.h -/// "lldb/Expression/ASTResultSynthesizer.h" -/// @brief Adds a result variable declaration to the ASTs for an expression. +/// "lldb/Expression/ASTResultSynthesizer.h" Adds a result variable +/// declaration to the ASTs for an expression. /// /// Users expect the expression "i + 3" to return a result, even if a result /// variable wasn't specifically declared. To fulfil this requirement, LLDB -/// adds -/// a result variable to the expression, transforming it to -/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the +/// adds a result variable to the expression, transforming it to "int +/// $__lldb_expr_result = i + 3." The IR transformers ensure that the /// resulting variable is mapped to the right piece of memory. -/// ASTResultSynthesizer's job is to add the variable and its initialization to -/// the ASTs for the expression, and it does so by acting as a SemaConsumer for -/// Clang. +/// ASTResultSynthesizer's job is to add the variable and its initialization +/// to the ASTs for the expression, and it does so by acting as a SemaConsumer +/// for Clang. //---------------------------------------------------------------------- class ASTResultSynthesizer : public clang::SemaConsumer { public: @@ -68,8 +67,8 @@ public: void Initialize(clang::ASTContext &Context) override; //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code + /// Examine a list of Decls to find the function $__lldb_expr and transform + /// its code /// /// @param[in] D /// The list of Decls to search. These may contain LinkageSpecDecls, @@ -124,8 +123,8 @@ public: private: //---------------------------------------------------------------------- - /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing - /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on + /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing as + /// necessary through LinkageSpecDecls, and calling SynthesizeResult on /// anything that was found /// /// @param[in] D @@ -164,8 +163,8 @@ private: bool SynthesizeBodyResult(clang::CompoundStmt *Body, clang::DeclContext *DC); //---------------------------------------------------------------------- - /// Given a DeclContext for a function or method, find all types - /// declared in the context and record any persistent types found. + /// Given a DeclContext for a function or method, find all types declared in + /// the context and record any persistent types found. /// /// @param[in] FunDeclCtx /// The context for the function to process. @@ -173,8 +172,8 @@ private: void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); //---------------------------------------------------------------------- - /// Given a TypeDecl, if it declares a type whose name starts with a - /// dollar sign, register it as a pointer type in the target's scratch + /// Given a TypeDecl, if it declares a type whose name starts with a dollar + /// sign, register it as a pointer type in the target's scratch /// AST context. /// /// @param[in] Body diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h index 63e3161cae85..65f4b00a8651 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -20,20 +20,19 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ASTStructExtractor ASTStructExtractor.h -/// "lldb/Expression/ASTStructExtractor.h" -/// @brief Extracts and describes the argument structure for a wrapped function. +/// "lldb/Expression/ASTStructExtractor.h" Extracts and describes the argument +/// structure for a wrapped function. /// /// This pass integrates with ClangFunctionCaller, which calls functions with -/// custom -/// sets of arguments. To avoid having to implement the full calling convention -/// for the target's architecture, ClangFunctionCaller writes a simple wrapper -/// function that takes a pointer to an argument structure that contains room -/// for the address of the function to be called, the values of all its -/// arguments, and room for the function's return value. +/// custom sets of arguments. To avoid having to implement the full calling +/// convention for the target's architecture, ClangFunctionCaller writes a +/// simple wrapper function that takes a pointer to an argument structure that +/// contains room for the address of the function to be called, the values of +/// all its arguments, and room for the function's return value. /// -/// The definition of this struct is itself in the body of the wrapper function, -/// so Clang does the structure layout itself. ASTStructExtractor reads through -/// the AST for the wrapper function and finds the struct. +/// The definition of this struct is itself in the body of the wrapper +/// function, so Clang does the structure layout itself. ASTStructExtractor +/// reads through the AST for the wrapper function and finds the struct. //---------------------------------------------------------------------- class ASTStructExtractor : public clang::SemaConsumer { public: @@ -73,8 +72,8 @@ public: void Initialize(clang::ASTContext &Context) override; //---------------------------------------------------------------------- - /// Examine a list of Decls to find the function $__lldb_expr and - /// transform its code + /// Examine a list of Decls to find the function $__lldb_expr and transform + /// its code /// /// @param[in] D /// The list of Decls to search. These may contain LinkageSpecDecls, diff --git a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/source/Plugins/ExpressionParser/Clang/CMakeLists.txt index a780e7d597b1..ec4f6d5674e1 100644 --- a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ b/source/Plugins/ExpressionParser/Clang/CMakeLists.txt @@ -11,6 +11,7 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN ClangExpressionParser.cpp ClangExpressionVariable.cpp ClangFunctionCaller.cpp + ClangHost.cpp ClangModulesDeclVendor.cpp ClangPersistentVariables.cpp ClangUserExpression.cpp @@ -23,6 +24,7 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN LINK_LIBS clangAST clangCodeGen + clangDriver clangEdit clangFrontend clangLex diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 7f031356b3c3..d98a2b25fbb7 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -33,8 +33,8 @@ using namespace clang; using namespace lldb_private; //------------------------------------------------------------------ -// Scoped class that will remove an active lexical decl from the set -// when it goes out of scope. +// Scoped class that will remove an active lexical decl from the set when it +// goes out of scope. //------------------------------------------------------------------ namespace { class ScopedLexicalDeclEraser { @@ -141,8 +141,8 @@ ClangASTSource::~ClangASTSource() { m_ast_importer_sp->ForgetDestination(m_ast_context); // We are in the process of destruction, don't create clang ast context on - // demand - // by passing false to Target::GetScratchClangASTContext(create_on_demand). + // demand by passing false to + // Target::GetScratchClangASTContext(create_on_demand). ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); @@ -231,8 +231,8 @@ bool ClangASTSource::FindExternalVisibleDeclsByName( } if (!GetLookupsEnabled()) { - // Wait until we see a '$' at the start of a name before we start doing - // any lookups so we can avoid lookup up all of the builtin types. + // Wait until we see a '$' at the start of a name before we start doing any + // lookups so we can avoid lookup up all of the builtin types. if (!decl_name.empty() && decl_name[0] == '$') { SetLookupsEnabled(true); } else { @@ -297,8 +297,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { } if (!m_ast_importer_sp->CompleteTagDecl(tag_decl)) { - // We couldn't complete the type. Maybe there's a definition - // somewhere else that can be completed. + // We couldn't complete the type. Maybe there's a definition somewhere + // else that can be completed. if (log) log->Printf(" CTD[%u] Type could not be completed in the module in " @@ -398,8 +398,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) { const_cast<TagDecl *>(tag_type->getDecl()); // We have found a type by basename and we need to make sure the decl - // contexts - // are the same before we can try to complete this type with another + // contexts are the same before we can try to complete this type with + // another if (!ClangASTContext::DeclsAreEquivalent(tag_decl, candidate_tag_decl)) continue; @@ -861,13 +861,16 @@ void ClangASTSource::FindExternalVisibleDecls( TypeList types; SymbolContext null_sc; - const bool exact_match = false; + const bool exact_match = true; llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; if (module_sp && namespace_decl) module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); - else - m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, + else { + SymbolContext sc; + sc.module_sp = module_sp; + m_target->GetImages().FindTypes(sc, name, exact_match, 1, searched_symbol_files, types); + } if (size_t num_types = types.GetSize()) { for (size_t ti = 0; ti < num_types; ++ti) { @@ -1243,8 +1246,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) { break; // Fall back and check for methods in categories. If we find methods this - // way, we need to check that they're actually in - // categories on the desired class. + // way, we need to check that they're actually in categories on the desired + // class. SymbolContextList candidate_sc_list; @@ -1591,8 +1594,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) { do { // Check the runtime only if the debug information didn't have a complete - // interface - // and nothing was in the modules. + // interface and nothing was in the modules. lldb::ProcessSP process(m_target->GetProcessSP()); @@ -1645,12 +1647,9 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, ClangASTSource &source) { // When importing fields into a new record, clang has a hard requirement that // fields be imported in field offset order. Since they are stored in a - // DenseMap - // with a pointer as the key type, this means we cannot simply iterate over - // the - // map, as the order will be non-deterministic. Instead we have to sort by - // the offset - // and then insert in sorted order. + // DenseMap with a pointer as the key type, this means we cannot simply + // iterate over the map, as the order will be non-deterministic. Instead we + // have to sort by the offset and then insert in sorted order. typedef llvm::DenseMap<const D *, O> MapType; typedef typename MapType::value_type PairType; std::vector<PairType> sorted_items; @@ -2051,9 +2050,8 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) { if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) - // this shouldn't happen, but we're hardening because the AST importer seems - // to be generating bad types - // on occasion. + // this shouldn't happen, but we're hardening because the AST importer + // seems to be generating bad types on occasion. return CompilerType(); return CompilerType(m_ast_context, copied_qual_type); @@ -2156,6 +2154,18 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, log->Printf("Function type wasn't a FunctionProtoType"); } + // If this is an operator (e.g. operator new or operator==), only insert the + // declaration we inferred from the symbol if we can provide the correct + // number of arguments. We shouldn't really inject random decl(s) for + // functions that are analyzed semantically in a special way, otherwise we + // will crash in clang. + clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS; + if (func_proto_type && + ClangASTContext::IsOperator(decl_name.getAsString().c_str(), op_kind)) { + if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount( + false, op_kind, func_proto_type->getNumParams())) + return NULL; + } m_decls.push_back(func_decl); return func_decl; diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index 6f72ad92dc8c..a42422b0f97f 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -25,14 +25,13 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" -/// @brief Provider for named objects defined in the debug info for Clang +/// Provider for named objects defined in the debug info for Clang /// -/// As Clang parses an expression, it may encounter names that are not -/// defined inside the expression, including variables, functions, and -/// types. Clang knows the name it is looking for, but nothing else. -/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) -/// to Clang for these names, consulting the ClangExpressionDeclMap to do -/// the actual lookups. +/// As Clang parses an expression, it may encounter names that are not defined +/// inside the expression, including variables, functions, and types. Clang +/// knows the name it is looking for, but nothing else. The ExternalSemaSource +/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these +/// names, consulting the ClangExpressionDeclMap to do the actual lookups. //---------------------------------------------------------------------- class ClangASTSource : public ClangExternalASTSourceCommon, public ClangASTImporter::MapCompleter { @@ -78,8 +77,8 @@ public: //------------------------------------------------------------------ /// Look up all Decls that match a particular name. Only handles /// Identifiers and DeclContexts that are either NamespaceDecls or - /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with - /// the result. + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with the + /// result. /// /// The work for this function is done by /// void FindExternalVisibleDecls (NameSearchContext &); @@ -173,8 +172,8 @@ public: //------------------------------------------------------------------ /// Called on entering a translation unit. Tells Clang by calling - /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() - /// that this object has something to say about undefined names. + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that + /// this object has something to say about undefined names. /// /// @param[in] ASTConsumer /// Unused. @@ -186,8 +185,8 @@ public: // //------------------------------------------------------------------ - /// Look up the modules containing a given namespace and put the - /// appropriate entries in the namespace map. + /// Look up the modules containing a given namespace and put the appropriate + /// entries in the namespace map. /// /// @param[in] namespace_map /// The map to be completed. @@ -231,11 +230,10 @@ public: //---------------------------------------------------------------------- /// @class ClangASTSourceProxy ClangASTSource.h - /// "lldb/Expression/ClangASTSource.h" - /// @brief Proxy for ClangASTSource + /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource /// - /// Clang AST contexts like to own their AST sources, so this is a - /// state-free proxy object. + /// Clang AST contexts like to own their AST sources, so this is a state- + /// free proxy object. //---------------------------------------------------------------------- class ClangASTSourceProxy : public ClangExternalASTSourceCommon { public: @@ -298,8 +296,8 @@ public: protected: //------------------------------------------------------------------ - /// Look for the complete version of an Objective-C interface, and - /// return it if found. + /// Look for the complete version of an Objective-C interface, and return it + /// if found. /// /// @param[in] interface_decl /// An ObjCInterfaceDecl that may not be the complete one. @@ -312,8 +310,8 @@ protected: GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl); //------------------------------------------------------------------ - /// Find all entities matching a given name in a given module, - /// using a NameSearchContext to make Decls for them. + /// Find all entities matching a given name in a given module, using a + /// NameSearchContext to make Decls for them. /// /// @param[in] context /// The NameSearchContext that can construct Decls for this name. @@ -474,8 +472,9 @@ protected: }; //---------------------------------------------------------------------- -/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" -/// @brief Container for all objects relevant to a single name lookup +/// @class NameSearchContext ClangASTSource.h +/// "lldb/Expression/ClangASTSource.h" Container for all objects relevant to a +/// single name lookup /// /// LLDB needs to create Decls for entities it finds. This class communicates /// what name is being searched for and provides helper functions to construct @@ -532,8 +531,8 @@ struct NameSearchContext { } //------------------------------------------------------------------ - /// Create a VarDecl with the name being searched for and the provided - /// type and register it in the right places. + /// Create a VarDecl with the name being searched for and the provided type + /// and register it in the right places. /// /// @param[in] type /// The opaque QualType for the VarDecl being registered. @@ -541,8 +540,8 @@ struct NameSearchContext { clang::NamedDecl *AddVarDecl(const CompilerType &type); //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and the provided - /// type and register it in the right places. + /// Create a FunDecl with the name being searched for and the provided type + /// and register it in the right places. /// /// @param[in] type /// The opaque QualType for the FunDecl being registered. @@ -553,15 +552,14 @@ struct NameSearchContext { clang::NamedDecl *AddFunDecl(const CompilerType &type, bool extern_c = false); //------------------------------------------------------------------ - /// Create a FunDecl with the name being searched for and generic - /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the - /// right places. + /// Create a FunDecl with the name being searched for and generic type (i.e. + /// intptr_t NAME_GOES_HERE(...)) and register it in the right places. //------------------------------------------------------------------ clang::NamedDecl *AddGenericFunDecl(); //------------------------------------------------------------------ - /// Create a TypeDecl with the name being searched for and the provided - /// type and register it in the right places. + /// Create a TypeDecl with the name being searched for and the provided type + /// and register it in the right places. /// /// @param[in] compiler_type /// The opaque QualType for the TypeDecl being registered. @@ -569,8 +567,8 @@ struct NameSearchContext { clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); //------------------------------------------------------------------ - /// Add Decls from the provided DeclContextLookupResult to the list - /// of results. + /// Add Decls from the provided DeclContextLookupResult to the list of + /// results. /// /// @param[in] result /// The DeclContextLookupResult, usually returned as the result diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 07ff2e97aac7..0811a7999920 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -213,8 +213,8 @@ private: m_exporter.getFromContext().getSourceManager().getFileID(loc); if (file != m_file) return false; - // We are assuming the Decl was parsed in this very expression, so it should - // not have external storage. + // We are assuming the Decl was parsed in this very expression, so it + // should not have external storage. lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage()); return true; } @@ -591,8 +591,8 @@ bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl, if (!entity) return false; - // We know m_parser_vars is valid since we searched for the variable by - // its NamedDecl + // We know m_parser_vars is valid since we searched for the variable by its + // NamedDecl ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); @@ -720,9 +720,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable( VariableList vars; if (module && namespace_decl) - module->FindGlobalVariables(name, namespace_decl, true, -1, vars); + module->FindGlobalVariables(name, namespace_decl, -1, vars); else - target.GetImages().FindGlobalVariables(name, true, -1, vars); + target.GetImages().FindGlobalVariables(name, -1, vars); if (vars.GetSize()) { if (type) { @@ -867,8 +867,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( if (IgnoreName(name, false)) return; - // Only look for functions by name out in our symbols if the function - // doesn't start with our phony prefix of '$' + // Only look for functions by name out in our symbols if the function doesn't + // start with our phony prefix of '$' Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); SymbolContext sym_ctx; @@ -977,13 +977,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( m_struct_vars->m_object_pointer_type = self_user_type; } } else { - // This branch will get hit if we are executing code in the context of a - // function that - // claims to have an object pointer (through DW_AT_object_pointer?) but - // is not formally a - // method of the class. In that case, just look up the "this" variable - // in the current - // scope and use its type. + // This branch will get hit if we are executing code in the context of + // a function that claims to have an object pointer (through + // DW_AT_object_pointer?) but is not formally a method of the class. + // In that case, just look up the "this" variable in the current scope + // and use its type. // FIXME: This code is formally correct, but clang doesn't currently // emit DW_AT_object_pointer // for C++ so it hasn't actually been tested. @@ -1093,13 +1091,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( return; } else { - // This branch will get hit if we are executing code in the context of a - // function that - // claims to have an object pointer (through DW_AT_object_pointer?) but - // is not formally a - // method of the class. In that case, just look up the "self" variable - // in the current - // scope and use its type. + // This branch will get hit if we are executing code in the context of + // a function that claims to have an object pointer (through + // DW_AT_object_pointer?) but is not formally a method of the class. + // In that case, just look up the "self" variable in the current scope + // and use its type. VariableList *vars = frame->GetVariableList(false); @@ -1217,9 +1213,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( vars->GetVariableAtIndex(i)->GetDecl(); // Search for declarations matching the name. Do not include imported - // decls - // in the search if we are looking for decls in the artificial namespace - // $__lldb_local_vars. + // decls in the search if we are looking for decls in the artificial + // namespace $__lldb_local_vars. std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name, namespace_decl.IsValid()); @@ -1285,15 +1280,15 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( append, sc_list); } - // If we found more than one function, see if we can use the - // frame's decl context to remove functions that are shadowed - // by other functions which match in type but are nearer in scope. + // If we found more than one function, see if we can use the frame's decl + // context to remove functions that are shadowed by other functions which + // match in type but are nearer in scope. // // AddOneFunction will not add a function whose type has already been - // added, so if there's another function in the list with a matching - // type, check to see if their decl context is a parent of the current - // frame's or was imported via a and using statement, and pick the - // best match according to lookup rules. + // added, so if there's another function in the list with a matching type, + // check to see if their decl context is a parent of the current frame's or + // was imported via a and using statement, and pick the best match + // according to lookup rules. if (sc_list.GetSize() > 1) { // Collect some info about our frame's context. StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); @@ -1321,11 +1316,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( SymbolContext m_sym_ctx; }; - // First, symplify things by looping through the symbol contexts - // to remove unwanted functions and separate out the functions we - // want to compare and prune into a separate list. - // Cache the info needed about the function declarations in a - // vector for efficiency. + // First, symplify things by looping through the symbol contexts to + // remove unwanted functions and separate out the functions we want to + // compare and prune into a separate list. Cache the info needed about + // the function declarations in a vector for efficiency. SymbolContextList sc_sym_list; uint32_t num_indices = sc_list.GetSize(); std::vector<FuncDeclInfo> fdi_cache; @@ -1335,16 +1329,16 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( SymbolContext sym_ctx; sc_list.GetContextAtIndex(index, sym_ctx); - // We don't know enough about symbols to compare them, - // but we should keep them in the list. + // We don't know enough about symbols to compare them, but we should + // keep them in the list. Function *function = sym_ctx.function; if (!function) { sc_sym_list.Append(sym_ctx); continue; } // Filter out functions without declaration contexts, as well as - // class/instance methods, since they'll be skipped in the - // code that follows anyway. + // class/instance methods, since they'll be skipped in the code that + // follows anyway. CompilerDeclContext func_decl_context = function->GetDeclContext(); if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) @@ -1363,11 +1357,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( fdi.m_copied_type = copied_func_type; fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; if (fdi.m_copied_type && func_decl_context) { - // Call CountDeclLevels to get the number of parent scopes we - // have to look through before we find the function declaration. - // When comparing functions of the same type, the one with a - // lower count will be closer to us in the lookup scope and - // shadows the other. + // Call CountDeclLevels to get the number of parent scopes we have + // to look through before we find the function declaration. When + // comparing functions of the same type, the one with a lower count + // will be closer to us in the lookup scope and shadows the other. clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); fdi.m_decl_lvl = ast->CountDeclLevels( @@ -1536,9 +1529,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls( } if (target && !context.m_found.variable && !namespace_decl) { - // We couldn't find a non-symbol variable for this. Now we'll hunt for - // a generic - // data symbol, and -- if it is found -- treat it as a variable. + // We couldn't find a non-symbol variable for this. Now we'll hunt for a + // generic data symbol, and -- if it is found -- treat it as a variable. Status error; const Symbol *data_symbol = @@ -2116,7 +2108,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, parser_vars->m_llvm_value = NULL; if (log) { - ASTDumper ast_dumper(function_decl); + std::string function_str = + function_decl ? ASTDumper(function_decl).GetCString() : "nullptr"; StreamString ss; @@ -2127,7 +2120,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context, log->Printf( " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", current_id, (function ? "specific" : "generic"), decl_name.c_str(), - ss.GetData(), ast_dumper.GetCString()); + ss.GetData(), function_str.c_str()); } } @@ -2165,7 +2158,7 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context, CXXMethodDecl *method_decl = ClangASTContext::GetASTContext(m_ast_context) ->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", NULL, method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index d163ad4f7e29..b67387930190 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -36,29 +36,28 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ClangExpressionDeclMap ClangExpressionDeclMap.h -/// "lldb/Expression/ClangExpressionDeclMap.h" -/// @brief Manages named entities that are defined in LLDB's debug information. +/// "lldb/Expression/ClangExpressionDeclMap.h" Manages named entities that are +/// defined in LLDB's debug information. /// /// The Clang parser uses the ClangASTSource as an interface to request named /// entities from outside an expression. The ClangASTSource reports back, -/// listing -/// all possible objects corresponding to a particular name. But it in turn -/// relies on ClangExpressionDeclMap, which performs several important +/// listing all possible objects corresponding to a particular name. But it +/// in turn relies on ClangExpressionDeclMap, which performs several important /// functions. /// -/// First, it records what variables and functions were looked up and what Decls -/// were returned for them. +/// First, it records what variables and functions were looked up and what +/// Decls were returned for them. /// /// Second, it constructs a struct on behalf of IRForTarget, recording which -/// variables should be placed where and relaying this information back so that -/// IRForTarget can generate context-independent code. +/// variables should be placed where and relaying this information back so +/// that IRForTarget can generate context-independent code. /// /// Third, it "materializes" this struct on behalf of the expression command, /// finding the current values of each variable and placing them into the /// struct so that it can be passed to the JITted version of the IR. /// -/// Fourth and finally, it "dematerializes" the struct after the JITted code has -/// has executed, placing the new values back where it found the old ones. +/// Fourth and finally, it "dematerializes" the struct after the JITted code +/// has has executed, placing the new values back where it found the old ones. //---------------------------------------------------------------------- class ClangExpressionDeclMap : public ClangASTSource { public: @@ -169,8 +168,8 @@ public: lldb::offset_t alignment); //------------------------------------------------------------------ - /// [Used by IRForTarget] Finalize the struct, laying out the position - /// of each object in it. + /// [Used by IRForTarget] Finalize the struct, laying out the position of + /// each object in it. /// /// @return /// True on success; false otherwise. @@ -178,8 +177,8 @@ public: bool DoStructLayout(); //------------------------------------------------------------------ - /// [Used by IRForTarget] Get general information about the laid-out - /// struct after DoStructLayout() has been called. + /// [Used by IRForTarget] Get general information about the laid-out struct + /// after DoStructLayout() has been called. /// /// @param[out] num_elements /// The number of elements in the struct. @@ -197,8 +196,8 @@ public: lldb::offset_t &alignment); //------------------------------------------------------------------ - /// [Used by IRForTarget] Get specific information about one field - /// of the laid-out struct after DoStructLayout() has been called. + /// [Used by IRForTarget] Get specific information about one field of the + /// laid-out struct after DoStructLayout() has been called. /// /// @param[out] decl /// The parsed Decl for the field, as generated by ClangASTSource @@ -232,8 +231,7 @@ public: uint32_t index); //------------------------------------------------------------------ - /// [Used by IRForTarget] Get information about a function given its - /// Decl. + /// [Used by IRForTarget] Get information about a function given its Decl. /// /// @param[in] decl /// The parsed Decl for the Function, as generated by ClangASTSource @@ -248,8 +246,8 @@ public: bool GetFunctionInfo(const clang::NamedDecl *decl, uint64_t &ptr); //------------------------------------------------------------------ - /// [Used by IRForTarget] Get the address of a symbol given nothing - /// but its name. + /// [Used by IRForTarget] Get the address of a symbol given nothing but its + /// name. /// /// @param[in] target /// The target to find the symbol in. If not provided, @@ -303,8 +301,8 @@ public: TargetInfo GetTargetInfo(); //------------------------------------------------------------------ - /// [Used by ClangASTSource] Find all entities matching a given name, - /// using a NameSearchContext to make Decls for them. + /// [Used by ClangASTSource] Find all entities matching a given name, using + /// a NameSearchContext to make Decls for them. /// /// @param[in] context /// The NameSearchContext that can construct Decls for this name. @@ -442,14 +440,13 @@ private: void DisableStructVars() { m_struct_vars.reset(); } //---------------------------------------------------------------------- - /// Get this parser's ID for use in extracting parser- and JIT-specific - /// data from persistent variables. + /// Get this parser's ID for use in extracting parser- and JIT-specific data + /// from persistent variables. //---------------------------------------------------------------------- uint64_t GetParserID() { return (uint64_t) this; } //------------------------------------------------------------------ - /// Given a target, find a variable that matches the given name and - /// type. + /// Given a target, find a variable that matches the given name and type. /// /// @param[in] target /// The target to use as a basis for finding the variable. @@ -477,8 +474,8 @@ private: TypeFromUser *type = NULL); //------------------------------------------------------------------ - /// Get the value of a variable in a given execution context and return - /// the associated Types if needed. + /// Get the value of a variable in a given execution context and return the + /// associated Types if needed. /// /// @param[in] var /// The variable to evaluate. @@ -524,8 +521,8 @@ private: lldb::ValueObjectSP valobj, unsigned int current_id); //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// persistent variable, and put it in the list of found entities. + /// Use the NameSearchContext to generate a Decl for the given persistent + /// variable, and put it in the list of found entities. /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. @@ -542,9 +539,8 @@ private: unsigned int current_id); //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given LLDB - /// symbol (treated as a variable), and put it in the list of found - /// entities. + /// Use the NameSearchContext to generate a Decl for the given LLDB symbol + /// (treated as a variable), and put it in the list of found entities. /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. @@ -556,9 +552,9 @@ private: unsigned int current_id); //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// function. (Functions are not placed in the Tuple list.) Can - /// handle both fully typed functions and generic functions. + /// Use the NameSearchContext to generate a Decl for the given function. + /// (Functions are not placed in the Tuple list.) Can handle both fully + /// typed functions and generic functions. /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. @@ -575,8 +571,7 @@ private: unsigned int current_id); //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// register. + /// Use the NameSearchContext to generate a Decl for the given register. /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. @@ -588,8 +583,8 @@ private: unsigned int current_id); //------------------------------------------------------------------ - /// Use the NameSearchContext to generate a Decl for the given - /// type. (Types are not placed in the Tuple list.) + /// Use the NameSearchContext to generate a Decl for the given type. (Types + /// are not placed in the Tuple list.) /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. @@ -601,8 +596,8 @@ private: unsigned int current_id); //------------------------------------------------------------------ - /// Generate a Decl for "*this" and add a member function declaration - /// to it for the expression, then report it. + /// Generate a Decl for "*this" and add a member function declaration to it + /// for the expression, then report it. /// /// @param[in] context /// The NameSearchContext to use when constructing the Decl. diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index d9e53074b3fb..c5406fcc3340 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -182,8 +182,7 @@ public: m_manager->AddDiagnostic(new_diagnostic); // Don't store away warning fixits, since the compiler doesn't have - // enough - // context in an expression for the warning to be useful. + // enough context in an expression for the warning to be useful. // FIXME: Should we try to filter out FixIts that apply to our generated // code, and not the user's expression? if (severity == eDiagnosticSeverityError) { @@ -226,10 +225,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, m_code_generator(), m_pp_callbacks(nullptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - // We can't compile expressions without a target. So if the exe_scope is null - // or doesn't have a target, - // then we just need to get out of here. I'll lldb_assert and not make any of - // the compiler objects since + // We can't compile expressions without a target. So if the exe_scope is + // null or doesn't have a target, then we just need to get out of here. I'll + // lldb_assert and not make any of the compiler objects since // I can't return errors directly from the constructor. Further calls will // check if the compiler was made and // bag out if it wasn't. @@ -262,14 +260,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, const auto target_machine = target_arch.GetMachine(); - // If the expression is being evaluated in the context of an existing - // stack frame, we introspect to see if the language runtime is available. + // If the expression is being evaluated in the context of an existing stack + // frame, we introspect to see if the language runtime is available. lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame(); lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); - // Make sure the user hasn't provided a preferred execution language - // with `expression --language X -- ...` + // Make sure the user hasn't provided a preferred execution language with + // `expression --language X -- ...` if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) frame_lang = frame_sp->GetLanguage(); @@ -281,8 +279,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, } // 2. Configure the compiler with a set of default options that are - // appropriate - // for most situations. + // appropriate for most situations. if (target_arch.IsValid()) { std::string triple = target_arch.GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; @@ -292,19 +289,17 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, } else { // If we get here we don't have a valid target and just have to guess. // Sometimes this will be ok to just use the host target triple (when we - // evaluate say "2+3", but other - // expressions like breakpoint conditions and other things that _are_ target - // specific really shouldn't just be - // using the host triple. In such a case the language runtime should expose - // an overridden options set (3), - // below. + // evaluate say "2+3", but other expressions like breakpoint conditions and + // other things that _are_ target specific really shouldn't just be using + // the host triple. In such a case the language runtime should expose an + // overridden options set (3), below. m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); if (log) log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str()); } - // Now add some special fixes for known architectures: - // Any arm32 iOS environment, but not on arm64 + // Now add some special fixes for known architectures: Any arm32 iOS + // environment, but not on arm64 if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) { @@ -317,8 +312,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, m_compiler->getTargetOpts().Features.push_back("+sse2"); } - // Set the target CPU to generate code for. - // This will be empty for any CPU that doesn't really need to make a special + // Set the target CPU to generate code for. This will be empty for any CPU + // that doesn't really need to make a special // CPU string. m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU(); @@ -328,11 +323,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, m_compiler->getTargetOpts().ABI = abi; // 3. Now allow the runtime to provide custom configuration options for the - // target. - // In this case, a specialized language runtime is available and we can query - // it for extra options. - // For 99% of use cases, this will not be needed and should be provided when - // basic platform detection is not enough. + // target. In this case, a specialized language runtime is available and we + // can query it for extra options. For 99% of use cases, this will not be + // needed and should be provided when basic platform detection is not enough. if (lang_rt) overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts()); @@ -378,9 +371,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, case lldb::eLanguageTypeC11: // FIXME: the following language option is a temporary workaround, // to "ask for C, get C++." - // For now, the expression parser must use C++ anytime the - // language is a C family language, because the expression parser - // uses features of C++ to capture values. + // For now, the expression parser must use C++ anytime the language is a C + // family language, because the expression parser uses features of C++ to + // capture values. m_compiler->getLangOpts().CPlusPlus = true; break; case lldb::eLanguageTypeObjC: @@ -392,10 +385,10 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, // Clang now sets as default C++14 as the default standard (with // GNU extensions), so we do the same here to avoid mismatches that - // cause compiler error when evaluating expressions (e.g. nullptr - // not found as it's a C++11 feature). Currently lldb evaluates - // C++14 as C++11 (see two lines below) so we decide to be consistent - // with that, but this could be re-evaluated in the future. + // cause compiler error when evaluating expressions (e.g. nullptr not found + // as it's a C++11 feature). Currently lldb evaluates C++14 as C++11 (see + // two lines below) so we decide to be consistent with that, but this could + // be re-evaluated in the future. m_compiler->getLangOpts().CPlusPlus11 = true; break; case lldb::eLanguageTypeC_plus_plus: @@ -407,8 +400,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, case lldb::eLanguageTypeC_plus_plus_03: m_compiler->getLangOpts().CPlusPlus = true; // FIXME: the following language option is a temporary workaround, - // to "ask for C++, get ObjC++". Apple hopes to remove this requirement - // on non-Apple platforms, but for now it is needed. + // to "ask for C++, get ObjC++". Apple hopes to remove this requirement on + // non-Apple platforms, but for now it is needed. m_compiler->getLangOpts().ObjC1 = true; break; case lldb::eLanguageTypeObjC_plus_plus: @@ -434,10 +427,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, ArchSpec(m_compiler->getTargetOpts().Triple.c_str()) .CharIsSignedByDefault(); - // Spell checking is a nice feature, but it ends up completing a - // lot of types that we didn't strictly speaking need to complete. - // As a result, we spend a long time parsing and importing debug - // information. + // Spell checking is a nice feature, but it ends up completing a lot of types + // that we didn't strictly speaking need to complete. As a result, we spend a + // long time parsing and importing debug information. m_compiler->getLangOpts().SpellChecking = false; if (process_sp && m_compiler->getLangOpts().ObjC1) { @@ -513,8 +505,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope, m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); } - // 8. Most of this we get from the CompilerInstance, but we - // also want to give the context an ExternalASTSource. + // 8. Most of this we get from the CompilerInstance, but we also want to give + // the context an ExternalASTSource. m_selector_table.reset(new SelectorTable()); m_builtin_context.reset(new Builtin::Context()); @@ -569,9 +561,7 @@ unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { codegenoptions::FullDebugInfo) { int temp_fd = -1; llvm::SmallString<PATH_MAX> result_path; - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, - tmpdir_file_spec)) { + if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) { tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); std::string temp_source_path = tmpdir_file_spec.GetPath(); llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); @@ -811,7 +801,7 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution( { auto lang = m_expr.Language(); if (log) - log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, + log->Printf("%s - Current expression language is %s\n", __FUNCTION__, Language::GetNameForLanguageType(lang)); lldb::ProcessSP process_sp = exe_ctx.GetProcessSP(); if (process_sp && lang != lldb::eLanguageTypeUnknown) { diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 41f290f2e127..4058ec1270b3 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -26,14 +26,14 @@ class IRExecutionUnit; //---------------------------------------------------------------------- /// @class ClangExpressionParser ClangExpressionParser.h -/// "lldb/Expression/ClangExpressionParser.h" -/// @brief Encapsulates an instance of Clang that can parse expressions. +/// "lldb/Expression/ClangExpressionParser.h" Encapsulates an instance of +/// Clang that can parse expressions. /// /// ClangExpressionParser is responsible for preparing an instance of /// ClangExpression for execution. ClangExpressionParser uses ClangExpression /// as a glorified parameter list, performing the required parsing and -/// conversion to formats (DWARF bytecode, or JIT compiled machine code) -/// that can be executed. +/// conversion to formats (DWARF bytecode, or JIT compiled machine code) that +/// can be executed. //---------------------------------------------------------------------- class ClangExpressionParser : public ExpressionParser { public: @@ -59,8 +59,8 @@ public: ~ClangExpressionParser() override; //------------------------------------------------------------------ - /// Parse a single expression and convert it to IR using Clang. Don't - /// wrap the expression in anything at all. + /// Parse a single expression and convert it to IR using Clang. Don't wrap + /// the expression in anything at all. /// /// @param[in] diagnostic_manager /// The diagnostic manager to report errors to. @@ -74,8 +74,8 @@ public: bool RewriteExpression(DiagnosticManager &diagnostic_manager) override; //------------------------------------------------------------------ - /// Ready an already-parsed expression for execution, possibly - /// evaluating it statically. + /// Ready an already-parsed expression for execution, possibly evaluating it + /// statically. /// /// @param[out] func_addr /// The address to which the function has been written. diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index baa80d7ba0d4..7d5ced5b4705 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -41,27 +41,25 @@ class ValueObjectConstResult; //---------------------------------------------------------------------- /// @class ClangExpressionVariable ClangExpressionVariable.h -/// "lldb/Expression/ClangExpressionVariable.h" -/// @brief Encapsulates one variable for the expression parser. +/// "lldb/Expression/ClangExpressionVariable.h" Encapsulates one variable for +/// the expression parser. /// /// The expression parser uses variables in three different contexts: /// -/// First, it stores persistent variables along with the process for use -/// in expressions. These persistent variables contain their own data -/// and are typed. +/// First, it stores persistent variables along with the process for use in +/// expressions. These persistent variables contain their own data and are +/// typed. /// -/// Second, in an interpreted expression, it stores the local variables -/// for the expression along with the expression. These variables -/// contain their own data and are typed. +/// Second, in an interpreted expression, it stores the local variables for +/// the expression along with the expression. These variables contain their +/// own data and are typed. /// -/// Third, in a JIT-compiled expression, it stores the variables that -/// the expression needs to have materialized and dematerialized at each -/// execution. These do not contain their own data but are named and -/// typed. +/// Third, in a JIT-compiled expression, it stores the variables that the +/// expression needs to have materialized and dematerialized at each +/// execution. These do not contain their own data but are named and typed. /// -/// This class supports all of these use cases using simple type -/// polymorphism, and provides necessary support methods. Its interface -/// is RTTI-neutral. +/// This class supports all of these use cases using simple type polymorphism, +/// and provides necessary support methods. Its interface is RTTI-neutral. //---------------------------------------------------------------------- class ClangExpressionVariable : public ExpressionVariable { public: @@ -79,8 +77,8 @@ public: lldb::ByteOrder byte_order, uint32_t addr_byte_size); //---------------------------------------------------------------------- - /// Utility functions for dealing with ExpressionVariableLists in - /// Clang-specific ways + /// Utility functions for dealing with ExpressionVariableLists in Clang- + /// specific ways //---------------------------------------------------------------------- //---------------------------------------------------------------------- @@ -112,9 +110,9 @@ public: } //---------------------------------------------------------------------- - /// If the variable contains its own data, make a Value point at it. - /// If \a exe_ctx in not NULL, the value will be resolved in with - /// that execution context. + /// If the variable contains its own data, make a Value point at it. If \a + /// exe_ctx in not NULL, the value will be resolved in with that execution + /// context. /// /// @param[in] value /// The value to point at the data. @@ -156,8 +154,8 @@ private: public: //---------------------------------------------------------------------- - /// Make this variable usable by the parser by allocating space for - /// parser-specific variables + /// Make this variable usable by the parser by allocating space for parser- + /// specific variables //---------------------------------------------------------------------- void EnableParserVars(uint64_t parser_id) { m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index a26ceda82d5f..e3e0ed49181e 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -101,14 +101,12 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp, m_wrapper_function_text.append(" (*fn_ptr) ("); // Get the number of arguments. If we have a function type and it is - // prototyped, - // trust that, otherwise use the values we were given. + // prototyped, trust that, otherwise use the values we were given. // FIXME: This will need to be extended to handle Variadic functions. We'll // need // to pull the defined arguments out of the function, then add the types from - // the - // arguments list for the variable arguments. + // the arguments list for the variable arguments. uint32_t num_args = UINT32_MAX; bool trust_function = false; diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 0596d8fde7b9..438cf0c713da 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -31,8 +31,8 @@ class ClangExpressionParser; //---------------------------------------------------------------------- /// @class ClangFunctionCaller ClangFunctionCaller.h -/// "lldb/Expression/ClangFunctionCaller.h" -/// @brief Encapsulates a function that can be called. +/// "lldb/Expression/ClangFunctionCaller.h" Encapsulates a function that can +/// be called. /// /// A given ClangFunctionCaller object can handle a single function signature. /// Once constructed, it can set up any number of concurrent calls to @@ -56,8 +56,8 @@ class ClangExpressionParser; /// If you need to call the function on the thread plan stack, you can also /// call InsertFunction() followed by GetThreadPlanToCallFunction(). /// -/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed -/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed a +/// pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated /// and its address returned in that variable. /// /// Any of the methods that take arg_addr_ptr can be passed NULL, and the @@ -79,8 +79,8 @@ class ClangFunctionCaller : public FunctionCaller { ClangExpressionDeclMap *DeclMap() override { return NULL; } //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. + /// Return the object that the parser should allow to access ASTs. May be + /// NULL if the ASTs do not need to be transformed. /// /// @param[in] passthrough /// The ASTConsumer that the returned transformer should send diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp new file mode 100644 index 000000000000..4251d2ee75b9 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp @@ -0,0 +1,142 @@ +//===-- ClangHost.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangHost.h" + +#include "clang/Basic/Version.h" +#include "clang/Config/config.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" + +// Project includes +#include "lldb/Host/HostInfo.h" +#if !defined(_WIN32) +#include "lldb/Host/posix/HostInfoPosix.h" +#endif +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" + +#include <string> + +using namespace lldb_private; + +#if defined(_WIN32) +static bool ComputeClangDirectory(FileSpec &file_spec) { return false; } +#else +static bool DefaultComputeClangDirectory(FileSpec &file_spec) { + return HostInfoPosix::ComputePathRelativeToLibrary( + file_spec, (llvm::Twine("/lib") + CLANG_LIBDIR_SUFFIX + "/clang/" + + CLANG_VERSION_STRING) + .str()); +} + +#if defined(__APPLE__) + +static bool VerifyClangPath(const llvm::Twine &clang_path) { + if (llvm::sys::fs::is_directory(clang_path)) + return true; + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("VerifyClangPath(): " + "failed to stat clang resource directory at \"%s\"", + clang_path.str().c_str()); + return false; +} + +bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec, + FileSpec &file_spec, bool verify) { + std::string raw_path = lldb_shlib_spec.GetPath(); + + auto rev_it = llvm::sys::path::rbegin(raw_path); + auto r_end = llvm::sys::path::rend(raw_path); + + // Check for a Posix-style build of LLDB. + while (rev_it != r_end) { + if (*rev_it == "LLDB.framework") + break; + ++rev_it; + } + + if (rev_it == r_end) + return DefaultComputeClangDirectory(file_spec); + + // Inside Xcode and in Xcode toolchains LLDB is always in lockstep + // with the Swift compiler, so it can reuse its Clang resource + // directory. This allows LLDB and the Swift compiler to share the + // same Clang module cache. + llvm::SmallString<256> clang_path; + const char *swift_clang_resource_dir = "usr/lib/swift/clang"; + auto parent = std::next(rev_it); + if (parent != r_end && *parent == "SharedFrameworks") { + // This is the top-level LLDB in the Xcode.app bundle. + // E.g., "Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A" + raw_path.resize(parent - r_end); + llvm::sys::path::append(clang_path, raw_path, + "Developer/Toolchains/XcodeDefault.xctoolchain", + swift_clang_resource_dir); + if (!verify || VerifyClangPath(clang_path)) { + file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native); + return true; + } + } else if (parent != r_end && *parent == "PrivateFrameworks" && + std::distance(parent, r_end) > 2) { + ++parent; + ++parent; + if (*parent == "System") { + // This is LLDB inside an Xcode toolchain. + // E.g., "Xcode.app/Contents/Developer/Toolchains/" \ + // "My.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework" + raw_path.resize(parent - r_end); + llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir); + if (!verify || VerifyClangPath(clang_path)) { + file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native); + return true; + } + raw_path = lldb_shlib_spec.GetPath(); + } + raw_path.resize(rev_it - r_end); + } else { + raw_path.resize(rev_it - r_end); + } + + // Fall back to the Clang resource directory inside the framework. + raw_path.append("LLDB.framework/Resources/Clang"); + file_spec.SetFile(raw_path.c_str(), true, FileSpec::Style::native); + return true; +} + +static bool ComputeClangDirectory(FileSpec &file_spec) { + if (FileSpec lldb_file_spec = HostInfo::GetShlibDir()) + return ComputeClangDirectory(lldb_file_spec, file_spec, true); + return false; +} +#else // __APPLE__ + +// All non-Apple posix systems. +static bool ComputeClangDirectory(FileSpec &file_spec) { + return DefaultComputeClangDirectory(file_spec); +} +#endif // __APPLE__ +#endif // _WIN32 + +FileSpec lldb_private::GetClangResourceDir() { + static FileSpec g_cached_resource_dir; + static llvm::once_flag g_once_flag; + llvm::call_once(g_once_flag, []() { + ::ComputeClangDirectory(g_cached_resource_dir); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) + log->Printf("GetClangResourceDir() => '%s'", + g_cached_resource_dir.GetPath().c_str()); + }); + return g_cached_resource_dir; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.h b/source/Plugins/ExpressionParser/Clang/ClangHost.h new file mode 100644 index 000000000000..4fe423adb1a5 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangHost.h @@ -0,0 +1,26 @@ +//===-- ClangHost.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H +#define LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H + +namespace lldb_private { + +class FileSpec; + +#if defined(__APPLE__) +bool ComputeClangDirectory(FileSpec &lldb_shlib_spec, FileSpec &file_spec, + bool verify); +#endif + +FileSpec GetClangResourceDir(); + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index b42ceb9afee8..665195f01774 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -25,8 +25,10 @@ #include "llvm/Support/Threading.h" // Project includes +#include "ClangHost.h" #include "ClangModulesDeclVendor.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/CompileUnit.h" @@ -39,9 +41,9 @@ using namespace lldb_private; namespace { -// Any Clang compiler requires a consumer for diagnostics. This one stores them -// as strings -// so we can provide them to the user in case a module failed to load. +// Any Clang compiler requires a consumer for diagnostics. This one stores +// them as strings so we can provide them to the user in case a module failed +// to load. class StoringDiagnosticConsumer : public clang::DiagnosticConsumer { public: StoringDiagnosticConsumer(); @@ -61,8 +63,7 @@ private: }; // The private implementation of our ClangModulesDeclVendor. Contains all the -// Clang state required -// to load modules. +// Clang state required to load modules. class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor { public: ClangModulesDeclVendorImpl( @@ -144,18 +145,6 @@ void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) { } } -static FileSpec GetResourceDir() { - static FileSpec g_cached_resource_dir; - - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - HostInfo::GetLLDBPath(lldb::ePathTypeClangDir, g_cached_resource_dir); - }); - - return g_cached_resource_dir; -} - ClangModulesDeclVendor::ClangModulesDeclVendor() {} ClangModulesDeclVendor::~ClangModulesDeclVendor() {} @@ -168,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl( : m_diagnostics_engine(std::move(diagnostics_engine)), m_compiler_invocation(std::move(compiler_invocation)), m_compiler_instance(std::move(compiler_instance)), - m_parser(std::move(parser)) {} + m_parser(std::move(parser)), m_origin_map() {} void ClangModulesDeclVendorImpl::ReportModuleExportsHelper( std::set<ClangModulesDeclVendor::ModuleID> &exports, @@ -590,14 +579,11 @@ ClangModulesDeclVendor::Create(Target &target) { // Add additional search paths with { "-I", path } or { "-F", path } here. { - llvm::SmallString<128> DefaultModuleCache; - const bool erased_on_reboot = false; - llvm::sys::path::system_temp_directory(erased_on_reboot, - DefaultModuleCache); - llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); - llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + llvm::SmallString<128> path; + auto props = ModuleList::GetGlobalModuleListProperties(); + props.GetClangModulesCachePath().GetPath(path); std::string module_cache_argument("-fmodules-cache-path="); - module_cache_argument.append(DefaultModuleCache.str().str()); + module_cache_argument.append(path.str()); compiler_invocation_arguments.push_back(module_cache_argument); } @@ -613,7 +599,7 @@ ClangModulesDeclVendor::Create(Target &target) { } { - FileSpec clang_resource_dir = GetResourceDir(); + FileSpec clang_resource_dir = GetClangResourceDir(); if (llvm::sys::fs::is_directory(clang_resource_dir.GetPath())) { compiler_invocation_arguments.push_back("-resource-dir"); diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 8ebf78409a03..bb73d55a9a41 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -10,6 +10,7 @@ #include "ClangPersistentVariables.h" #include "lldb/Core/Value.h" +#include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" @@ -52,14 +53,6 @@ void ClangPersistentVariables::RemovePersistentVariable( m_next_persistent_variable_id--; } -ConstString ClangPersistentVariables::GetNextPersistentVariableName() { - char name_cstr[256]; - ::snprintf(name_cstr, sizeof(name_cstr), "$%u", - m_next_persistent_variable_id++); - ConstString name(name_cstr); - return name; -} - void ClangPersistentVariables::RegisterPersistentDecl(const ConstString &name, clang::NamedDecl *decl) { m_persistent_decls.insert( diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index 16981a7fe14a..59126974616d 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -25,9 +25,8 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ClangPersistentVariables ClangPersistentVariables.h -/// "lldb/Expression/ClangPersistentVariables.h" -/// @brief Manages persistent values that need to be preserved between -/// expression invocations. +/// "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, @@ -54,16 +53,11 @@ public: const CompilerType &compiler_type, lldb::ByteOrder byte_order, uint32_t addr_byte_size) override; - //---------------------------------------------------------------------- - /// Return the next entry in the sequence of strings "$0", "$1", ... for - /// use naming persistent expression convenience variables. - /// - /// @return - /// A string that contains the next persistent variable name. - //---------------------------------------------------------------------- - ConstString GetNextPersistentVariableName() override; - void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; + llvm::StringRef + GetPersistentVariablePrefix(bool is_error) const override { + return "$"; + } void RegisterPersistentDecl(const ConstString &name, clang::NamedDecl *decl); diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 18fe8b49227b..2e61f704127a 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -65,7 +65,8 @@ ClangUserExpression::ClangUserExpression( options), m_type_system_helper(*m_target_wp.lock().get(), options.GetExecutionPolicy() == - eExecutionPolicyTopLevel) { + eExecutionPolicyTopLevel), + m_result_delegate(exe_scope.CalculateTarget()) { switch (m_language) { case lldb::eLanguageTypeC_plus_plus: m_allow_cxx = true; @@ -195,12 +196,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { } else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) { // We might also have a function that said in the debug information that it - // captured an - // object pointer. The best way to deal with getting to the ivars at - // present is by pretending - // that this is a method of a class in whatever runtime the debug info says - // the object pointer - // belongs to. Do that here. + // captured an object pointer. The best way to deal with getting to the + // ivars at present is by pretending that this is a method of a class in + // whatever runtime the debug info says the object pointer belongs to. Do + // that here. ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData(decl_context, function_decl); @@ -290,10 +289,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) { } } -// This is a really nasty hack, meant to fix Objective-C expressions of the form -// (int)[myArray count]. Right now, because the type information for count is -// not available, [myArray count] returns id, which can't be directly cast to -// int without causing a clang error. +// This is a really nasty hack, meant to fix Objective-C expressions of the +// form (int)[myArray count]. Right now, because the type information for +// count is not available, [myArray count] returns id, which can't be directly +// cast to int without causing a clang error. static void ApplyObjcCastHack(std::string &expr) { #define OBJC_CAST_HACK_FROM "(int)[" #define OBJC_CAST_HACK_TO "(int)(long long)[" @@ -308,17 +307,23 @@ static void ApplyObjcCastHack(std::string &expr) { #undef OBJC_CAST_HACK_FROM } -bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); +namespace { +// Utility guard that calls a callback when going out of scope. +class OnExit { +public: + typedef std::function<void(void)> Callback; - Status err; + OnExit(Callback const &callback) : m_callback(callback) {} - InstallContext(exe_ctx); + ~OnExit() { m_callback(); } + +private: + Callback m_callback; +}; +} // namespace +bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx) { if (Target *target = exe_ctx.GetTargetPtr()) { if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage( @@ -335,26 +340,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, "error: couldn't start parsing (no target)"); return false; } + return true; +} - ScanContext(exe_ctx, err); - - if (!err.Success()) { - diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString()); - } - - //////////////////////////////////// - // Generate the expression - // - - ApplyObjcCastHack(m_expr_text); - - std::string prefix = m_expr_prefix; - +static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) { if (ClangModulesDeclVendor *decl_vendor = - m_target->GetClangModulesDeclVendor()) { + target->GetClangModulesDeclVendor()) { const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>( - m_target->GetPersistentExpressionStateForLanguage( + target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) ->GetHandLoadedClangModules(); ClangModulesDeclVendor::ModuleVector modules_for_macros; @@ -363,7 +357,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, modules_for_macros.push_back(module); } - if (m_target->GetEnableAutoImportClangModules()) { + if (target->GetEnableAutoImportClangModules()) { if (StackFrame *frame = exe_ctx.GetFramePtr()) { if (Block *block = frame->GetFrameBlock()) { SymbolContext sc; @@ -380,8 +374,13 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, } } } +} - lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; +llvm::Optional<lldb::LanguageType> ClangUserExpression::GetLanguageForExpr( + DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { + lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown; + + std::string prefix = m_expr_prefix; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { m_transformed_text = m_expr_text; @@ -401,9 +400,50 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, exe_ctx)) { diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't construct expression body"); - return false; + return llvm::Optional<lldb::LanguageType>(); } } + return lang_type; +} + +bool ClangUserExpression::PrepareForParsing( + DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { + InstallContext(exe_ctx); + + if (!SetupPersistentState(diagnostic_manager, exe_ctx)) + return false; + + Status err; + ScanContext(exe_ctx, err); + + if (!err.Success()) { + diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString()); + } + + //////////////////////////////////// + // Generate the expression + // + + ApplyObjcCastHack(m_expr_text); + + SetupDeclVendor(exe_ctx, m_target); + return true; +} + +bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (!PrepareForParsing(diagnostic_manager, exe_ctx)) + return false; + + lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown; + if (auto new_lang = GetLanguageForExpr(diagnostic_manager, exe_ctx)) { + lang_type = new_lang.getValue(); + } if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); @@ -427,28 +467,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); - class OnExit { - public: - typedef std::function<void(void)> Callback; - - OnExit(Callback const &callback) : m_callback(callback) {} - - ~OnExit() { m_callback(); } - - private: - Callback m_callback; - }; - OnExit on_exit([this]() { ResetDeclMap(); }); if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); - - ResetDeclMap(); // We are being careful here in the case of breakpoint - // conditions. - return false; } @@ -463,17 +487,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, exe_scope = exe_ctx.GetTargetPtr(); // We use a shared pointer here so we can use the original parser - if it - // succeeds - // or the rewrite parser we might make if it fails. But the parser_sp will - // never be empty. + // succeeds or the rewrite parser we might make if it fails. But the + // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info); unsigned num_errors = parser.Parse(diagnostic_manager); // Check here for FixItHints. If there are any try to apply the fixits and - // set the fixed text in m_fixed_text - // before returning an error. + // set the fixed text in m_fixed_text before returning an error. if (num_errors) { if (diagnostic_manager.HasFixIts()) { if (parser.RewriteExpression(diagnostic_manager)) { @@ -487,16 +509,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, fixed_expression.substr(fixed_start, fixed_end - fixed_start); } } - - ResetDeclMap(); // We are being careful here in the case of breakpoint - // conditions. - return false; } ////////////////////////////////////////////////////////////////////////////////////////// - // Prepare the output of the parser for execution, evaluating it statically if - // possible + // Prepare the output of the parser for execution, evaluating it statically + // if possible // { @@ -539,9 +557,9 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, register_execution_unit = true; } - // If there is more than one external function in the execution - // unit, it needs to keep living even if it's not top level, because - // the result could refer to that function. + // If there is more than one external function in the execution unit, it + // needs to keep living even if it's not top level, because the result + // could refer to that function. if (m_execution_unit_sp->GetJittedFunctions().size() > 1) { register_execution_unit = true; @@ -568,10 +586,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, } } - ResetDeclMap(); // Make this go away since we don't need any of its state - // after parsing. This also gets rid of any - // ClangASTImporter::Minions. - if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; @@ -667,10 +681,10 @@ void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() { } } -ClangUserExpression::ResultDelegate::ResultDelegate() {} - ConstString ClangUserExpression::ResultDelegate::GetName() { - return m_persistent_state->GetNextPersistentVariableName(); + auto prefix = m_persistent_state->GetPersistentVariablePrefix(); + return m_persistent_state->GetNextPersistentVariableName(*m_target_sp, + prefix); } void ClangUserExpression::ResultDelegate::DidDematerialize( diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 88a78798b657..ac363bf91747 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -35,13 +35,13 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ClangUserExpression ClangUserExpression.h -/// "lldb/Expression/ClangUserExpression.h" -/// @brief Encapsulates a single expression for use with Clang +/// "lldb/Expression/ClangUserExpression.h" Encapsulates a single expression +/// for use with Clang /// /// LLDB uses expressions for various purposes, notably to call functions /// and as a backend for the expr command. ClangUserExpression encapsulates -/// the objects needed to parse and interpret or JIT an expression. It -/// uses the Clang parser to produce LLVM IR from the expression. +/// the objects needed to parse and interpret or JIT an expression. It uses +/// the Clang parser to produce LLVM IR from the expression. //---------------------------------------------------------------------- class ClangUserExpression : public LLVMUserExpression { public: @@ -69,8 +69,8 @@ public: bool keep_result_in_memory); //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. + /// Return the object that the parser should allow to access ASTs. May be + /// NULL if the ASTs do not need to be transformed. /// /// @param[in] passthrough /// The ASTConsumer that the returned transformer should send @@ -174,11 +174,18 @@ private: lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) override; + llvm::Optional<lldb::LanguageType> GetLanguageForExpr( + DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx); + bool SetupPersistentState(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx); + bool PrepareForParsing(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx); + ClangUserExpressionHelper m_type_system_helper; class ResultDelegate : public Materializer::PersistentVariableDelegate { public: - ResultDelegate(); + ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {} ConstString GetName() override; void DidDematerialize(lldb::ExpressionVariableSP &variable) override; @@ -188,6 +195,7 @@ private: private: PersistentExpressionState *m_persistent_state; lldb::ExpressionVariableSP m_variable; + lldb::TargetSP m_target_sp; }; ResultDelegate m_result_delegate; diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index 80577199b818..a897a2b17087 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -29,15 +29,15 @@ namespace lldb_private { //---------------------------------------------------------------------- /// @class ClangUtilityFunction ClangUtilityFunction.h -/// "lldb/Expression/ClangUtilityFunction.h" -/// @brief Encapsulates a single expression for use with Clang +/// "lldb/Expression/ClangUtilityFunction.h" Encapsulates a single expression +/// for use with Clang /// /// LLDB uses expressions for various purposes, notably to call functions /// and as a backend for the expr command. ClangUtilityFunction encapsulates /// a self-contained function meant to be used from other code. Utility /// functions can perform error-checking for ClangUserExpressions, or can -/// simply provide a way to push a function into the target for the debugger to -/// call later on. +/// simply provide a way to push a function into the target for the debugger +/// to call later on. //---------------------------------------------------------------------- class ClangUtilityFunction : public UtilityFunction { public: @@ -60,8 +60,8 @@ public: void ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory); //------------------------------------------------------------------ - /// Return the object that the parser should allow to access ASTs. - /// May be NULL if the ASTs do not need to be transformed. + /// Return the object that the parser should allow to access ASTs. May be + /// NULL if the ASTs do not need to be transformed. /// /// @param[in] passthrough /// The ASTConsumer that the returned transformer should send diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 13f5657eedd8..e51c9ee07b9f 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -263,8 +263,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { } // Get the next available result name from m_decl_map and create the - // persistent - // variable for it + // persistent variable for it // If the result is an Lvalue, it is emitted as a pointer; see // ASTResultSynthesizer::SynthesizeBodyResult. @@ -345,9 +344,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) { GlobalValue::ExternalLinkage, NULL, /* no initializer */ m_result_name.GetCString()); - // It's too late in compilation to create a new VarDecl for this, but we don't - // need to. We point the metadata at the old VarDecl. This creates an odd - // anomaly: a variable with a Value whose name is something like $0 and a + // It's too late in compilation to create a new VarDecl for this, but we + // don't need to. We point the metadata at the old VarDecl. This creates an + // odd anomaly: a variable with a Value whose name is something like $0 and a // Decl whose name is $__lldb_expr_result. This condition is handled in // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is // fixed up. @@ -464,9 +463,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str, // CFAllocatorRef -> i8* // UInt8 * -> i8* // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its - // pointer size for now) - // CFStringEncoding -> i32 - // Boolean -> i8 + // pointer size for now) CFStringEncoding -> i32 Boolean -> i8 Type *arg_type_array[5]; @@ -801,9 +798,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { // Unpack the message name from the selector. In LLVM IR, an objc_msgSend // gets represented as // - // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> - // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) - // ; <i8*> + // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> %call = call + // i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*> // // where %obj is the object pointer and %tmp is the selector. // @@ -870,7 +866,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) { log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); - // Build the function type: struct objc_selector *sel_registerName(uint8_t*) + // Build the function type: struct objc_selector + // *sel_registerName(uint8_t*) // The below code would be "more correct," but in actuality what's required // is uint8_t* @@ -980,11 +977,10 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) { // %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4 // // @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called - // @OBJC_CLASS_NAME_. - // @OBJC_CLASS_NAME contains the string. + // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string. - // Find the pointer's initializer (a ConstantExpr with opcode BitCast) - // and get the string from its target + // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and + // get the string from its target GlobalVariable *_objc_class_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand()); @@ -1159,8 +1155,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { GlobalValue::ExternalLinkage, NULL, /* no initializer */ alloc->getName().str()); - // What we're going to do here is make believe this was a regular old external - // variable. That means we need to make the metadata valid. + // What we're going to do here is make believe this was a regular old + // external variable. That means we need to make the metadata valid. NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); @@ -1175,8 +1171,7 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) { named_metadata->addOperand(persistent_global_md); // Now, since the variable is a pointer variable, we will drop in a load of - // that - // pointer variable. + // that pointer variable. LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc); @@ -1366,16 +1361,13 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) { if (name[0] == '$') { // The $__lldb_expr_result name indicates the return value has allocated - // as - // a static variable. Per the comment at - // ASTResultSynthesizer::SynthesizeBodyResult, - // accesses to this static variable need to be redirected to the result of - // dereferencing - // a pointer that is passed in as one of the arguments. + // as a static variable. Per the comment at + // ASTResultSynthesizer::SynthesizeBodyResult, accesses to this static + // variable need to be redirected to the result of dereferencing a + // pointer that is passed in as one of the arguments. // // Consequently, when reporting the size of the type, we report a pointer - // type pointing - // to the type of $__lldb_expr_result, not the type itself. + // type pointing to the type of $__lldb_expr_result, not the type itself. // // We also do this for any user-declared persistent variables. compiler_type = compiler_type.GetPointerType(); @@ -1965,12 +1957,11 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) { FunctionValueCache body_result_maker( [this, name, offset_type, offset, argument, value](llvm::Function *function) -> llvm::Value * { - // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in - // cases where the result - // variable is an rvalue, we have to synthesize a dereference of the - // appropriate structure - // entry in order to produce the static variable that the AST thinks - // it is accessing. + // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, + // in cases where the result variable is an rvalue, we have to + // synthesize a dereference of the appropriate structure entry in + // order to produce the static variable that the AST thinks it is + // accessing. llvm::Instruction *entry_instruction = llvm::cast<Instruction>( m_entry_instruction_finder.GetValue(function)); @@ -2194,7 +2185,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) { if (log) log->Printf("RewriteObjCSelectors() failed"); - // RewriteObjCSelectors() reports its own errors, so we don't do so here + // RewriteObjCSelectors() reports its own errors, so we don't do so + // here return false; } diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h index 93ce8aa44eb2..c6c44b46023c 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -47,12 +47,11 @@ class IRMemoryMap; //---------------------------------------------------------------------- /// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" -/// @brief Transforms the IR for a function to run in the target +/// Transforms the IR for a function to run in the target /// -/// Once an expression has been parsed and converted to IR, it can run -/// in two contexts: interpreted by LLDB as a DWARF location expression, -/// or compiled by the JIT and inserted into the target process for -/// execution. +/// Once an expression has been parsed and converted to IR, it can run in two +/// contexts: interpreted by LLDB as a DWARF location expression, or compiled +/// by the JIT and inserted into the target process for execution. /// /// IRForTarget makes the second possible, by applying a series of /// transformations to the IR which make it relocatable. These @@ -126,8 +125,7 @@ public: //------------------------------------------------------------------ /// Interface stub /// - /// Implementation of the llvm::ModulePass::assignPassManager() - /// function. + /// Implementation of the llvm::ModulePass::assignPassManager() function. //------------------------------------------------------------------ void assignPassManager(llvm::PMStack &pass_mgr_stack, llvm::PassManagerType pass_mgr_type = @@ -179,8 +177,8 @@ private: //------------------------------------------------------------------ //------------------------------------------------------------------ - /// Get the address of a function, and a location to put the complete - /// Value of the function if one is available. + /// Get the address of a function, and a location to put the complete Value + /// of the function if one is available. /// /// @param[in] function /// The function to find the location of. @@ -204,13 +202,13 @@ private: //------------------------------------------------------------------ /// A function-level pass to take the generated global value - /// $__lldb_expr_result and make it into a persistent variable. - /// Also see ASTResultSynthesizer. + /// $__lldb_expr_result and make it into a persistent variable. Also see + /// ASTResultSynthesizer. //------------------------------------------------------------------ //------------------------------------------------------------------ - /// Find the NamedDecl corresponding to a Value. This interface is - /// exposed for the IR interpreter. + /// Find the NamedDecl corresponding to a Value. This interface is exposed + /// for the IR interpreter. /// /// @param[in] module /// The module containing metadata to search @@ -230,8 +228,8 @@ private: //------------------------------------------------------------------ /// Set the constant result variable m_const_result to the provided - /// constant, assuming it can be evaluated. The result variable - /// will be reset to NULL later if the expression has side effects. + /// constant, assuming it can be evaluated. The result variable will be + /// reset to NULL later if the expression has side effects. /// /// @param[in] initializer /// The constant initializer for the variable. @@ -247,8 +245,8 @@ private: lldb_private::TypeFromParser type); //------------------------------------------------------------------ - /// If the IR represents a cast of a variable, set m_const_result - /// to the result of the cast. The result variable will be reset to + /// If the IR represents a cast of a variable, set m_const_result to the + /// result of the cast. The result variable will be reset to /// NULL latger if the expression has side effects. /// /// @param[in] type @@ -301,10 +299,9 @@ private: /// rewrite them to use sel_registerName instead of statically allocated /// selectors. The reason is that the selectors are created on the /// assumption that the Objective-C runtime will scan the appropriate - /// section and prepare them. This doesn't happen when code is copied - /// into the target, though, and there's no easy way to induce the - /// runtime to scan them. So instead we get our selectors from - /// sel_registerName. + /// section and prepare them. This doesn't happen when code is copied into + /// the target, though, and there's no easy way to induce the runtime to + /// scan them. So instead we get our selectors from sel_registerName. //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -359,13 +356,12 @@ private: //------------------------------------------------------------------ /// A basic block-level pass to find all newly-declared persistent - /// variables and register them with the ClangExprDeclMap. This - /// allows them to be materialized and dematerialized like normal - /// external variables. Before transformation, these persistent - /// variables look like normal locals, so they have an allocation. - /// This pass excises these allocations and makes references look - /// like external references where they will be resolved -- like all - /// other external references -- by ResolveExternals(). + /// variables and register them with the ClangExprDeclMap. This allows them + /// to be materialized and dematerialized like normal external variables. + /// Before transformation, these persistent variables look like normal + /// locals, so they have an allocation. This pass excises these allocations + /// and makes references look like external references where they will be + /// resolved -- like all other external references -- by ResolveExternals(). //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -389,15 +385,14 @@ private: //------------------------------------------------------------------ /// A function-level pass to find all external variables and functions - /// used in the IR. Each found external variable is added to the - /// struct, and each external function is resolved in place, its call - /// replaced with a call to a function pointer whose value is the - /// address of the function in the target process. + /// used in the IR. Each found external variable is added to the struct, + /// and each external function is resolved in place, its call replaced with + /// a call to a function pointer whose value is the address of the function + /// in the target process. //------------------------------------------------------------------ //------------------------------------------------------------------ - /// Write an initializer to a memory array of assumed sufficient - /// size. + /// Write an initializer to a memory array of assumed sufficient size. /// /// @param[in] data /// A pointer to the data to write to. @@ -504,8 +499,8 @@ private: //------------------------------------------------------------------ /// A basic block-level pass to excise guard variables from the code. /// The result for the function is passed through Clang as a static - /// variable. Static variables normally have guard variables to - /// ensure that they are only initialized once. + /// variable. Static variables normally have guard variables to ensure that + /// they are only initialized once. //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -529,9 +524,9 @@ private: //------------------------------------------------------------------ /// A function-level pass to make all external variable references - /// point at the correct offsets from the void* passed into the - /// function. ClangExpressionDeclMap::DoStructLayout() must be called - /// beforehand, so that the offsets are valid. + /// point at the correct offsets from the void* passed into the function. + /// ClangExpressionDeclMap::DoStructLayout() must be called beforehand, so + /// that the offsets are valid. //------------------------------------------------------------------ //------------------------------------------------------------------ @@ -583,7 +578,8 @@ private: llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that ///writes to the result variable. If - /// m_has_side_effects is true, this is NULL. + /// m_has_side_effects is true, this is + /// NULL. bool m_result_is_pointer; ///< True if the function's result in the AST is a ///pointer (see comments in /// ASTResultSynthesizer::SynthesizeBodyResult) @@ -594,18 +590,17 @@ private: /// location of the static allocation. //------------------------------------------------------------------ - /// UnfoldConstant operates on a constant [Old] which has just been - /// replaced with a value [New]. We assume that new_value has - /// been properly placed early in the function, in front of the - /// first instruction in the entry basic block - /// [FirstEntryInstruction]. + /// UnfoldConstant operates on a constant [Old] which has just been replaced + /// with a value [New]. We assume that new_value has been properly placed + /// early in the function, in front of the first instruction in the entry + /// basic block [FirstEntryInstruction]. /// - /// UnfoldConstant reads through the uses of Old and replaces Old - /// in those uses with New. Where those uses are constants, the - /// function generates new instructions to compute the result of the - /// new, non-constant expression and places them before - /// FirstEntryInstruction. These instructions replace the constant - /// uses, so UnfoldConstant calls itself recursively for those. + /// UnfoldConstant reads through the uses of Old and replaces Old in those + /// uses with New. Where those uses are constants, the function generates + /// new instructions to compute the result of the new, non-constant + /// expression and places them before FirstEntryInstruction. These + /// instructions replace the constant uses, so UnfoldConstant calls itself + /// recursively for those. /// /// @param[in] llvm_function /// The function currently being processed. @@ -637,8 +632,8 @@ private: lldb_private::Stream &error_stream); //------------------------------------------------------------------ - /// Construct a reference to m_reloc_placeholder with a given type - /// and offset. This typically happens after inserting data into + /// Construct a reference to m_reloc_placeholder with a given type and + /// offset. This typically happens after inserting data into /// m_data_allocator. /// /// @param[in] type @@ -653,8 +648,8 @@ private: llvm::Constant *BuildRelocation(llvm::Type *type, uint64_t offset); //------------------------------------------------------------------ - /// Commit the allocation in m_data_allocator and use its final - /// location to replace m_reloc_placeholder. + /// Commit the allocation in m_data_allocator and use its final location to + /// replace m_reloc_placeholder. /// /// @param[in] module /// The module that m_data_allocator resides in diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp index 538bd05e25f8..9c845d02bca0 100644 --- a/source/Plugins/ExpressionParser/Go/GoParser.cpp +++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp @@ -67,7 +67,9 @@ private: size_t m_pos; }; -GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) {} +GoParser::GoParser(const char *src) + : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID), + m_failed(false) {} GoASTStmt *GoParser::Statement() { Rule r("Statement", this); @@ -437,8 +439,10 @@ GoASTExpr *GoParser::CompositeLit() { if (!type) return r.error(); GoASTCompositeLit *lit = LiteralValue(); - if (!lit) + if (!lit) { + delete type; return r.error(); + } lit->SetType(type); return lit; } @@ -546,6 +550,7 @@ GoASTExpr *GoParser::Arguments(GoASTExpr *e) { GoASTExpr *GoParser::Conversion() { Rule r("Conversion", this); if (GoASTExpr *t = Type2()) { + std::unique_ptr<GoASTExpr> owner(t); if (match(GoLexer::OP_LPAREN)) { GoASTExpr *v = Expression(); if (!v) @@ -555,6 +560,7 @@ GoASTExpr *GoParser::Conversion() { return r.error(); GoASTCallExpr *call = new GoASTCallExpr(false); call->SetFun(t); + owner.release(); call->AddArgs(v); return call; } diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp index f4b8cfbe03d4..3a10a1dc767a 100644 --- a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -171,12 +171,11 @@ private: VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) { ConstString fullname(name.str()); VariableList variable_list; - const bool append = true; if (!target) { return nullptr; } - const uint32_t match_count = target->GetImages().FindGlobalVariables( - fullname, append, 1, variable_list); + const uint32_t match_count = + target->GetImages().FindGlobalVariables(fullname, 1, variable_list); if (match_count == 1) { return variable_list.GetVariableAtIndex(0); } @@ -272,7 +271,8 @@ GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); if (pv != nullptr) { - result->SetName(pv->GetNextPersistentVariableName()); + result->SetName(pv->GetNextPersistentVariableName( + *target, pv->GetPersistentVariablePrefix())); pv->AddVariable(result); } return lldb::eExpressionCompleted; @@ -400,8 +400,7 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) { val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); else { // When a variable is on the heap instead of the stack, go records a - // variable - // '&x' instead of 'x'. + // variable '&x' instead of 'x'. var_sp = var_list_sp->FindVariable(ConstString("&" + varname)); if (var_sp) { val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); @@ -651,15 +650,6 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr( GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo) {} -ConstString GoPersistentExpressionState::GetNextPersistentVariableName() { - char name_cstr[256]; - // We can't use the same variable format as clang. - ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", - m_next_persistent_variable_id++); - ConstString name(name_cstr); - return name; -} - void GoPersistentExpressionState::RemovePersistentVariable( lldb::ExpressionVariableSP variable) { RemoveVariable(variable); diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h index 03ceb76b8431..e2839da9bfdd 100644 --- a/source/Plugins/ExpressionParser/Go/GoUserExpression.h +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -29,8 +29,10 @@ class GoPersistentExpressionState : public PersistentExpressionState { public: GoPersistentExpressionState(); - ConstString GetNextPersistentVariableName() override; - + llvm::StringRef + GetPersistentVariablePrefix(bool is_error) const override { + return "$go"; + } void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; lldb::addr_t LookupSymbol(const ConstString &name) override { @@ -48,12 +50,12 @@ private: //---------------------------------------------------------------------- /// @class GoUserExpression GoUserExpression.h -/// "lldb/Expression/GoUserExpression.h" -/// @brief Encapsulates a single expression for use with Go +/// "lldb/Expression/GoUserExpression.h" Encapsulates a single expression for +/// use with Go /// /// LLDB uses expressions for various purposes, notably to call functions -/// and as a backend for the expr command. GoUserExpression encapsulates -/// the objects needed to parse and interpret an expression. +/// and as a backend for the expr command. GoUserExpression encapsulates the +/// objects needed to parse and interpret an expression. //---------------------------------------------------------------------- class GoUserExpression : public UserExpression { public: |
