1dda28197Spatrick //===-- NameSearchContext.cpp ---------------------------------------------===//
2dda28197Spatrick //
3dda28197Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4dda28197Spatrick // See https://llvm.org/LICENSE.txt for license information.
5dda28197Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dda28197Spatrick //
7dda28197Spatrick //===----------------------------------------------------------------------===//
8dda28197Spatrick
9dda28197Spatrick #include "NameSearchContext.h"
10dda28197Spatrick #include "ClangUtil.h"
11*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
12dda28197Spatrick
13dda28197Spatrick using namespace clang;
14dda28197Spatrick using namespace lldb_private;
15dda28197Spatrick
AddVarDecl(const CompilerType & type)16dda28197Spatrick clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
17dda28197Spatrick assert(type && "Type for variable must be valid!");
18dda28197Spatrick
19dda28197Spatrick if (!type.IsValid())
20dda28197Spatrick return nullptr;
21dda28197Spatrick
22*f6aab3d8Srobert auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
23dda28197Spatrick if (!lldb_ast)
24dda28197Spatrick return nullptr;
25dda28197Spatrick
26dda28197Spatrick IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
27dda28197Spatrick
28dda28197Spatrick clang::ASTContext &ast = lldb_ast->getASTContext();
29dda28197Spatrick
30dda28197Spatrick clang::NamedDecl *Decl = VarDecl::Create(
31dda28197Spatrick ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
32dda28197Spatrick SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static);
33dda28197Spatrick m_decls.push_back(Decl);
34dda28197Spatrick
35dda28197Spatrick return Decl;
36dda28197Spatrick }
37dda28197Spatrick
AddFunDecl(const CompilerType & type,bool extern_c)38dda28197Spatrick clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
39dda28197Spatrick bool extern_c) {
40dda28197Spatrick assert(type && "Type for variable must be valid!");
41dda28197Spatrick
42dda28197Spatrick if (!type.IsValid())
43dda28197Spatrick return nullptr;
44dda28197Spatrick
45dda28197Spatrick if (m_function_types.count(type))
46dda28197Spatrick return nullptr;
47dda28197Spatrick
48*f6aab3d8Srobert auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
49dda28197Spatrick if (!lldb_ast)
50dda28197Spatrick return nullptr;
51dda28197Spatrick
52dda28197Spatrick m_function_types.insert(type);
53dda28197Spatrick
54dda28197Spatrick QualType qual_type(ClangUtil::GetQualType(type));
55dda28197Spatrick
56dda28197Spatrick clang::ASTContext &ast = lldb_ast->getASTContext();
57dda28197Spatrick
58dda28197Spatrick const bool isInlineSpecified = false;
59dda28197Spatrick const bool hasWrittenPrototype = true;
60dda28197Spatrick const bool isConstexprSpecified = false;
61dda28197Spatrick
62dda28197Spatrick clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context);
63dda28197Spatrick
64dda28197Spatrick if (extern_c) {
65dda28197Spatrick context = LinkageSpecDecl::Create(
66dda28197Spatrick ast, context, SourceLocation(), SourceLocation(),
67dda28197Spatrick clang::LinkageSpecDecl::LanguageIDs::lang_c, false);
68*f6aab3d8Srobert // FIXME: The LinkageSpecDecl here should be added to m_decl_context.
69dda28197Spatrick }
70dda28197Spatrick
71dda28197Spatrick // Pass the identifier info for functions the decl_name is needed for
72dda28197Spatrick // operators
73dda28197Spatrick clang::DeclarationName decl_name =
74dda28197Spatrick m_decl_name.getNameKind() == DeclarationName::Identifier
75dda28197Spatrick ? m_decl_name.getAsIdentifierInfo()
76dda28197Spatrick : m_decl_name;
77dda28197Spatrick
78dda28197Spatrick clang::FunctionDecl *func_decl = FunctionDecl::Create(
79dda28197Spatrick ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
80*f6aab3d8Srobert nullptr, SC_Extern, /*UsesFPIntrin=*/false, isInlineSpecified, hasWrittenPrototype,
81be691f3bSpatrick isConstexprSpecified ? ConstexprSpecKind::Constexpr
82be691f3bSpatrick : ConstexprSpecKind::Unspecified);
83dda28197Spatrick
84dda28197Spatrick // We have to do more than just synthesize the FunctionDecl. We have to
85dda28197Spatrick // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
86dda28197Spatrick // this, we raid the function's FunctionProtoType for types.
87dda28197Spatrick
88dda28197Spatrick const FunctionProtoType *func_proto_type =
89dda28197Spatrick qual_type.getTypePtr()->getAs<FunctionProtoType>();
90dda28197Spatrick
91dda28197Spatrick if (func_proto_type) {
92dda28197Spatrick unsigned NumArgs = func_proto_type->getNumParams();
93dda28197Spatrick unsigned ArgIndex;
94dda28197Spatrick
95dda28197Spatrick SmallVector<ParmVarDecl *, 5> parm_var_decls;
96dda28197Spatrick
97dda28197Spatrick for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) {
98dda28197Spatrick QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
99dda28197Spatrick
100dda28197Spatrick parm_var_decls.push_back(
101dda28197Spatrick ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
102dda28197Spatrick SourceLocation(), SourceLocation(), nullptr,
103dda28197Spatrick arg_qual_type, nullptr, SC_Static, nullptr));
104dda28197Spatrick }
105dda28197Spatrick
106dda28197Spatrick func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls));
107dda28197Spatrick } else {
108*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
109dda28197Spatrick
110dda28197Spatrick LLDB_LOG(log, "Function type wasn't a FunctionProtoType");
111dda28197Spatrick }
112dda28197Spatrick
113dda28197Spatrick // If this is an operator (e.g. operator new or operator==), only insert the
114dda28197Spatrick // declaration we inferred from the symbol if we can provide the correct
115dda28197Spatrick // number of arguments. We shouldn't really inject random decl(s) for
116dda28197Spatrick // functions that are analyzed semantically in a special way, otherwise we
117dda28197Spatrick // will crash in clang.
118dda28197Spatrick clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
119dda28197Spatrick if (func_proto_type &&
120dda28197Spatrick TypeSystemClang::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
121dda28197Spatrick if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
122dda28197Spatrick false, op_kind, func_proto_type->getNumParams()))
123dda28197Spatrick return nullptr;
124dda28197Spatrick }
125dda28197Spatrick m_decls.push_back(func_decl);
126dda28197Spatrick
127dda28197Spatrick return func_decl;
128dda28197Spatrick }
129dda28197Spatrick
AddGenericFunDecl()130dda28197Spatrick clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
131dda28197Spatrick FunctionProtoType::ExtProtoInfo proto_info;
132dda28197Spatrick
133dda28197Spatrick proto_info.Variadic = true;
134dda28197Spatrick
135dda28197Spatrick QualType generic_function_type(
136dda28197Spatrick GetASTContext().getFunctionType(GetASTContext().UnknownAnyTy, // result
137dda28197Spatrick ArrayRef<QualType>(), // argument types
138dda28197Spatrick proto_info));
139dda28197Spatrick
140dda28197Spatrick return AddFunDecl(m_clang_ts.GetType(generic_function_type), true);
141dda28197Spatrick }
142dda28197Spatrick
143dda28197Spatrick clang::NamedDecl *
AddTypeDecl(const CompilerType & clang_type)144dda28197Spatrick NameSearchContext::AddTypeDecl(const CompilerType &clang_type) {
145dda28197Spatrick if (ClangUtil::IsClangType(clang_type)) {
146dda28197Spatrick QualType qual_type = ClangUtil::GetQualType(clang_type);
147dda28197Spatrick
148dda28197Spatrick if (const TypedefType *typedef_type =
149dda28197Spatrick llvm::dyn_cast<TypedefType>(qual_type)) {
150dda28197Spatrick TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
151dda28197Spatrick
152dda28197Spatrick m_decls.push_back(typedef_name_decl);
153dda28197Spatrick
154dda28197Spatrick return (NamedDecl *)typedef_name_decl;
155dda28197Spatrick } else if (const TagType *tag_type = qual_type->getAs<TagType>()) {
156dda28197Spatrick TagDecl *tag_decl = tag_type->getDecl();
157dda28197Spatrick
158dda28197Spatrick m_decls.push_back(tag_decl);
159dda28197Spatrick
160dda28197Spatrick return tag_decl;
161dda28197Spatrick } else if (const ObjCObjectType *objc_object_type =
162dda28197Spatrick qual_type->getAs<ObjCObjectType>()) {
163dda28197Spatrick ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
164dda28197Spatrick
165dda28197Spatrick m_decls.push_back((NamedDecl *)interface_decl);
166dda28197Spatrick
167dda28197Spatrick return (NamedDecl *)interface_decl;
168dda28197Spatrick }
169dda28197Spatrick }
170dda28197Spatrick return nullptr;
171dda28197Spatrick }
172dda28197Spatrick
AddLookupResult(clang::DeclContextLookupResult result)173dda28197Spatrick void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) {
174dda28197Spatrick for (clang::NamedDecl *decl : result)
175dda28197Spatrick m_decls.push_back(decl);
176dda28197Spatrick }
177dda28197Spatrick
AddNamedDecl(clang::NamedDecl * decl)178dda28197Spatrick void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) {
179dda28197Spatrick m_decls.push_back(decl);
180dda28197Spatrick }
181