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