xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp (revision 5e801ac66d24704442eba426ed13c3effb8a34e7)
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 
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 
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     // FIXME: The LinkageSpecDecl here should be added to m_decl_context.
70   }
71 
72   // Pass the identifier info for functions the decl_name is needed for
73   // operators
74   clang::DeclarationName decl_name =
75       m_decl_name.getNameKind() == DeclarationName::Identifier
76           ? m_decl_name.getAsIdentifierInfo()
77           : m_decl_name;
78 
79   clang::FunctionDecl *func_decl = FunctionDecl::Create(
80       ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
81       nullptr, SC_Extern, /*UsesFPIntrin=*/false, isInlineSpecified, hasWrittenPrototype,
82       isConstexprSpecified ? ConstexprSpecKind::Constexpr
83                            : ConstexprSpecKind::Unspecified);
84 
85   // We have to do more than just synthesize the FunctionDecl.  We have to
86   // synthesize ParmVarDecls for all of the FunctionDecl's arguments.  To do
87   // this, we raid the function's FunctionProtoType for types.
88 
89   const FunctionProtoType *func_proto_type =
90       qual_type.getTypePtr()->getAs<FunctionProtoType>();
91 
92   if (func_proto_type) {
93     unsigned NumArgs = func_proto_type->getNumParams();
94     unsigned ArgIndex;
95 
96     SmallVector<ParmVarDecl *, 5> parm_var_decls;
97 
98     for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) {
99       QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
100 
101       parm_var_decls.push_back(
102           ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
103                               SourceLocation(), SourceLocation(), nullptr,
104                               arg_qual_type, nullptr, SC_Static, nullptr));
105     }
106 
107     func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls));
108   } else {
109     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
110 
111     LLDB_LOG(log, "Function type wasn't a FunctionProtoType");
112   }
113 
114   // If this is an operator (e.g. operator new or operator==), only insert the
115   // declaration we inferred from the symbol if we can provide the correct
116   // number of arguments. We shouldn't really inject random decl(s) for
117   // functions that are analyzed semantically in a special way, otherwise we
118   // will crash in clang.
119   clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
120   if (func_proto_type &&
121       TypeSystemClang::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
122     if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
123             false, op_kind, func_proto_type->getNumParams()))
124       return nullptr;
125   }
126   m_decls.push_back(func_decl);
127 
128   return func_decl;
129 }
130 
131 clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
132   FunctionProtoType::ExtProtoInfo proto_info;
133 
134   proto_info.Variadic = true;
135 
136   QualType generic_function_type(
137       GetASTContext().getFunctionType(GetASTContext().UnknownAnyTy, // result
138                                       ArrayRef<QualType>(), // argument types
139                                       proto_info));
140 
141   return AddFunDecl(m_clang_ts.GetType(generic_function_type), true);
142 }
143 
144 clang::NamedDecl *
145 NameSearchContext::AddTypeDecl(const CompilerType &clang_type) {
146   if (ClangUtil::IsClangType(clang_type)) {
147     QualType qual_type = ClangUtil::GetQualType(clang_type);
148 
149     if (const TypedefType *typedef_type =
150             llvm::dyn_cast<TypedefType>(qual_type)) {
151       TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
152 
153       m_decls.push_back(typedef_name_decl);
154 
155       return (NamedDecl *)typedef_name_decl;
156     } else if (const TagType *tag_type = qual_type->getAs<TagType>()) {
157       TagDecl *tag_decl = tag_type->getDecl();
158 
159       m_decls.push_back(tag_decl);
160 
161       return tag_decl;
162     } else if (const ObjCObjectType *objc_object_type =
163                    qual_type->getAs<ObjCObjectType>()) {
164       ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
165 
166       m_decls.push_back((NamedDecl *)interface_decl);
167 
168       return (NamedDecl *)interface_decl;
169     }
170   }
171   return nullptr;
172 }
173 
174 void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) {
175   for (clang::NamedDecl *decl : result)
176     m_decls.push_back(decl);
177 }
178 
179 void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) {
180   m_decls.push_back(decl);
181 }
182