xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/NameSearchContext.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 #include "lldb/Utility/LLDBLog.h"
12 
13 using namespace clang;
14 using namespace lldb_private;
15 
16 clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
17   assert(type && "Type for variable must be valid!");
18 
19   if (!type.IsValid())
20     return nullptr;
21 
22   auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
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   auto lldb_ast = type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
49   if (!lldb_ast)
50     return nullptr;
51 
52   m_function_types.insert(type);
53 
54   QualType qual_type(ClangUtil::GetQualType(type));
55 
56   clang::ASTContext &ast = lldb_ast->getASTContext();
57 
58   const bool isInlineSpecified = false;
59   const bool hasWrittenPrototype = true;
60   const bool isConstexprSpecified = false;
61 
62   clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context);
63 
64   if (extern_c) {
65     context = LinkageSpecDecl::Create(ast, context, SourceLocation(),
66                                       SourceLocation(),
67                                       clang::LinkageSpecLanguageIDs::C, false);
68     // FIXME: The LinkageSpecDecl here should be added to m_decl_context.
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, /*UsesFPIntrin=*/false, isInlineSpecified, hasWrittenPrototype,
81       isConstexprSpecified ? ConstexprSpecKind::Constexpr
82                            : ConstexprSpecKind::Unspecified);
83 
84   // We have to do more than just synthesize the FunctionDecl.  We have to
85   // synthesize ParmVarDecls for all of the FunctionDecl's arguments.  To do
86   // this, we raid the function's FunctionProtoType for types.
87 
88   const FunctionProtoType *func_proto_type =
89       qual_type.getTypePtr()->getAs<FunctionProtoType>();
90 
91   if (func_proto_type) {
92     unsigned NumArgs = func_proto_type->getNumParams();
93     unsigned ArgIndex;
94 
95     SmallVector<ParmVarDecl *, 5> parm_var_decls;
96 
97     for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) {
98       QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
99 
100       parm_var_decls.push_back(
101           ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
102                               SourceLocation(), SourceLocation(), nullptr,
103                               arg_qual_type, nullptr, SC_Static, nullptr));
104     }
105 
106     func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls));
107   } else {
108     Log *log = GetLog(LLDBLog::Expressions);
109 
110     LLDB_LOG(log, "Function type wasn't a FunctionProtoType");
111   }
112 
113   // If this is an operator (e.g. operator new or operator==), only insert the
114   // declaration we inferred from the symbol if we can provide the correct
115   // number of arguments. We shouldn't really inject random decl(s) for
116   // functions that are analyzed semantically in a special way, otherwise we
117   // will crash in clang.
118   clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
119   if (func_proto_type &&
120       TypeSystemClang::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
121     if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
122             false, op_kind, func_proto_type->getNumParams()))
123       return nullptr;
124   }
125   m_decls.push_back(func_decl);
126 
127   return func_decl;
128 }
129 
130 clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
131   FunctionProtoType::ExtProtoInfo proto_info;
132 
133   proto_info.Variadic = true;
134 
135   QualType generic_function_type(
136       GetASTContext().getFunctionType(GetASTContext().UnknownAnyTy, // result
137                                       ArrayRef<QualType>(), // argument types
138                                       proto_info));
139 
140   return AddFunDecl(m_clang_ts.GetType(generic_function_type), true);
141 }
142 
143 clang::NamedDecl *
144 NameSearchContext::AddTypeDecl(const CompilerType &clang_type) {
145   if (ClangUtil::IsClangType(clang_type)) {
146     QualType qual_type = ClangUtil::GetQualType(clang_type);
147 
148     if (const TypedefType *typedef_type =
149             llvm::dyn_cast<TypedefType>(qual_type)) {
150       TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
151 
152       m_decls.push_back(typedef_name_decl);
153 
154       return (NamedDecl *)typedef_name_decl;
155     } else if (const TagType *tag_type = qual_type->getAs<TagType>()) {
156       TagDecl *tag_decl = tag_type->getDecl();
157 
158       m_decls.push_back(tag_decl);
159 
160       return tag_decl;
161     } else if (const ObjCObjectType *objc_object_type =
162                    qual_type->getAs<ObjCObjectType>()) {
163       ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
164 
165       m_decls.push_back((NamedDecl *)interface_decl);
166 
167       return (NamedDecl *)interface_decl;
168     }
169   }
170   return nullptr;
171 }
172 
173 void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) {
174   for (clang::NamedDecl *decl : result)
175     m_decls.push_back(decl);
176 }
177 
178 void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) {
179   m_decls.push_back(decl);
180 }
181