diff options
Diffstat (limited to 'lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp')
-rw-r--r-- | lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp new file mode 100644 index 000000000000..c1f88889f1dc --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp @@ -0,0 +1,179 @@ +//===-- NameSearchContext.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "NameSearchContext.h" +#include "ClangUtil.h" + +using namespace clang; +using namespace lldb_private; + +clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) { + assert(type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return nullptr; + + TypeSystemClang *lldb_ast = + llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + if (!lldb_ast) + return nullptr; + + IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); + + clang::ASTContext &ast = lldb_ast->getASTContext(); + + clang::NamedDecl *Decl = VarDecl::Create( + ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(), + SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static); + m_decls.push_back(Decl); + + return Decl; +} + +clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type, + bool extern_c) { + assert(type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return nullptr; + + if (m_function_types.count(type)) + return nullptr; + + TypeSystemClang *lldb_ast = + llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem()); + if (!lldb_ast) + return nullptr; + + m_function_types.insert(type); + + QualType qual_type(ClangUtil::GetQualType(type)); + + clang::ASTContext &ast = lldb_ast->getASTContext(); + + const bool isInlineSpecified = false; + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; + + clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context); + + if (extern_c) { + context = LinkageSpecDecl::Create( + ast, context, SourceLocation(), SourceLocation(), + clang::LinkageSpecDecl::LanguageIDs::lang_c, false); + } + + // Pass the identifier info for functions the decl_name is needed for + // operators + clang::DeclarationName decl_name = + m_decl_name.getNameKind() == DeclarationName::Identifier + ? m_decl_name.getAsIdentifierInfo() + : m_decl_name; + + clang::FunctionDecl *func_decl = FunctionDecl::Create( + ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type, + nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype, + isConstexprSpecified ? CSK_constexpr : CSK_unspecified); + + // We have to do more than just synthesize the FunctionDecl. We have to + // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do + // this, we raid the function's FunctionProtoType for types. + + const FunctionProtoType *func_proto_type = + qual_type.getTypePtr()->getAs<FunctionProtoType>(); + + if (func_proto_type) { + unsigned NumArgs = func_proto_type->getNumParams(); + unsigned ArgIndex; + + SmallVector<ParmVarDecl *, 5> parm_var_decls; + + for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) { + QualType arg_qual_type(func_proto_type->getParamType(ArgIndex)); + + parm_var_decls.push_back( + ParmVarDecl::Create(ast, const_cast<DeclContext *>(context), + SourceLocation(), SourceLocation(), nullptr, + arg_qual_type, nullptr, SC_Static, nullptr)); + } + + func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls)); + } else { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + LLDB_LOG(log, "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 && + TypeSystemClang::IsOperator(decl_name.getAsString().c_str(), op_kind)) { + if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount( + false, op_kind, func_proto_type->getNumParams())) + return nullptr; + } + m_decls.push_back(func_decl); + + return func_decl; +} + +clang::NamedDecl *NameSearchContext::AddGenericFunDecl() { + FunctionProtoType::ExtProtoInfo proto_info; + + proto_info.Variadic = true; + + QualType generic_function_type( + GetASTContext().getFunctionType(GetASTContext().UnknownAnyTy, // result + ArrayRef<QualType>(), // argument types + proto_info)); + + return AddFunDecl(m_clang_ts.GetType(generic_function_type), true); +} + +clang::NamedDecl * +NameSearchContext::AddTypeDecl(const CompilerType &clang_type) { + if (ClangUtil::IsClangType(clang_type)) { + QualType qual_type = ClangUtil::GetQualType(clang_type); + + if (const TypedefType *typedef_type = + llvm::dyn_cast<TypedefType>(qual_type)) { + TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); + + m_decls.push_back(typedef_name_decl); + + return (NamedDecl *)typedef_name_decl; + } else if (const TagType *tag_type = qual_type->getAs<TagType>()) { + TagDecl *tag_decl = tag_type->getDecl(); + + m_decls.push_back(tag_decl); + + return tag_decl; + } else if (const ObjCObjectType *objc_object_type = + qual_type->getAs<ObjCObjectType>()) { + ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); + + m_decls.push_back((NamedDecl *)interface_decl); + + return (NamedDecl *)interface_decl; + } + } + return nullptr; +} + +void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) { + for (clang::NamedDecl *decl : result) + m_decls.push_back(decl); +} + +void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) { + m_decls.push_back(decl); +} |