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