LLDB  mainline
NameSearchContext.cpp
Go to the documentation of this file.
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  TypeSystemClang *lldb_ast =
23  llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
24  if (!lldb_ast)
25  return nullptr;
26 
27  IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
28 
29  clang::ASTContext &ast = lldb_ast->getASTContext();
30 
31  clang::NamedDecl *Decl = VarDecl::Create(
32  ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
33  SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static);
34  m_decls.push_back(Decl);
35 
36  return Decl;
37 }
38 
39 clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
40  bool extern_c) {
41  assert(type && "Type for variable must be valid!");
42 
43  if (!type.IsValid())
44  return nullptr;
45 
46  if (m_function_types.count(type))
47  return nullptr;
48 
49  TypeSystemClang *lldb_ast =
50  llvm::dyn_cast<TypeSystemClang>(type.GetTypeSystem());
51  if (!lldb_ast)
52  return nullptr;
53 
54  m_function_types.insert(type);
55 
56  QualType qual_type(ClangUtil::GetQualType(type));
57 
58  clang::ASTContext &ast = lldb_ast->getASTContext();
59 
60  const bool isInlineSpecified = false;
61  const bool hasWrittenPrototype = true;
62  const bool isConstexprSpecified = false;
63 
64  clang::DeclContext *context = const_cast<DeclContext *>(m_decl_context);
65 
66  if (extern_c) {
67  context = LinkageSpecDecl::Create(
68  ast, context, SourceLocation(), SourceLocation(),
69  clang::LinkageSpecDecl::LanguageIDs::lang_c, false);
70  // FIXME: The LinkageSpecDecl here should be added to m_decl_context.
71  }
72 
73  // Pass the identifier info for functions the decl_name is needed for
74  // operators
75  clang::DeclarationName decl_name =
76  m_decl_name.getNameKind() == DeclarationName::Identifier
77  ? m_decl_name.getAsIdentifierInfo()
78  : m_decl_name;
79 
80  clang::FunctionDecl *func_decl = FunctionDecl::Create(
81  ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
82  nullptr, SC_Extern, /*UsesFPIntrin=*/false, isInlineSpecified, hasWrittenPrototype,
83  isConstexprSpecified ? ConstexprSpecKind::Constexpr
84  : ConstexprSpecKind::Unspecified);
85 
86  // We have to do more than just synthesize the FunctionDecl. We have to
87  // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
88  // this, we raid the function's FunctionProtoType for types.
89 
90  const FunctionProtoType *func_proto_type =
91  qual_type.getTypePtr()->getAs<FunctionProtoType>();
92 
93  if (func_proto_type) {
94  unsigned NumArgs = func_proto_type->getNumParams();
95  unsigned ArgIndex;
96 
97  SmallVector<ParmVarDecl *, 5> parm_var_decls;
98 
99  for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) {
100  QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
101 
102  parm_var_decls.push_back(
103  ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
104  SourceLocation(), SourceLocation(), nullptr,
105  arg_qual_type, nullptr, SC_Static, nullptr));
106  }
107 
108  func_decl->setParams(ArrayRef<ParmVarDecl *>(parm_var_decls));
109  } else {
110  Log *log = GetLog(LLDBLog::Expressions);
111 
112  LLDB_LOG(log, "Function type wasn't a FunctionProtoType");
113  }
114 
115  // If this is an operator (e.g. operator new or operator==), only insert the
116  // declaration we inferred from the symbol if we can provide the correct
117  // number of arguments. We shouldn't really inject random decl(s) for
118  // functions that are analyzed semantically in a special way, otherwise we
119  // will crash in clang.
120  clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
121  if (func_proto_type &&
122  TypeSystemClang::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
123  if (!TypeSystemClang::CheckOverloadedOperatorKindParameterCount(
124  false, op_kind, func_proto_type->getNumParams()))
125  return nullptr;
126  }
127  m_decls.push_back(func_decl);
128 
129  return func_decl;
130 }
131 
132 clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
133  FunctionProtoType::ExtProtoInfo proto_info;
134 
135  proto_info.Variadic = true;
136 
137  QualType generic_function_type(
138  GetASTContext().getFunctionType(GetASTContext().UnknownAnyTy, // result
139  ArrayRef<QualType>(), // argument types
140  proto_info));
141 
142  return AddFunDecl(m_clang_ts.GetType(generic_function_type), true);
143 }
144 
145 clang::NamedDecl *
146 NameSearchContext::AddTypeDecl(const CompilerType &clang_type) {
147  if (ClangUtil::IsClangType(clang_type)) {
148  QualType qual_type = ClangUtil::GetQualType(clang_type);
149 
150  if (const TypedefType *typedef_type =
151  llvm::dyn_cast<TypedefType>(qual_type)) {
152  TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
153 
154  m_decls.push_back(typedef_name_decl);
155 
156  return (NamedDecl *)typedef_name_decl;
157  } else if (const TagType *tag_type = qual_type->getAs<TagType>()) {
158  TagDecl *tag_decl = tag_type->getDecl();
159 
160  m_decls.push_back(tag_decl);
161 
162  return tag_decl;
163  } else if (const ObjCObjectType *objc_object_type =
164  qual_type->getAs<ObjCObjectType>()) {
165  ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
166 
167  m_decls.push_back((NamedDecl *)interface_decl);
168 
169  return (NamedDecl *)interface_decl;
170  }
171  }
172  return nullptr;
173 }
174 
175 void NameSearchContext::AddLookupResult(clang::DeclContextLookupResult result) {
176  for (clang::NamedDecl *decl : result)
177  m_decls.push_back(decl);
178 }
179 
180 void NameSearchContext::AddNamedDecl(clang::NamedDecl *decl) {
181  m_decls.push_back(decl);
182 }
lldb_private::TypeSystemClang::getASTContext
clang::ASTContext & getASTContext()
Returns the clang::ASTContext instance managed by this TypeSystemClang.
Definition: TypeSystemClang.cpp:686
ClangUtil.h
NameSearchContext.h
lldb_private::CompilerType::IsValid
bool IsValid() const
Definition: CompilerType.h:72
lldb_private::CompilerType::GetTypeSystem
TypeSystem * GetTypeSystem() const
Accessors.
Definition: CompilerType.h:162
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:336
clang
Definition: ASTResultSynthesizer.h:15
lldb_private::CompilerType
Generic representation of a type in a programming language.
Definition: CompilerType.h:33
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::TypeSystemClang
A TypeSystem implementation based on Clang.
Definition: TypeSystemClang.h:105
lldb_private::Log
Definition: Log.h:115
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:308
LLDBLog.h