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