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