14#include "clang/Sema/Lookup.h"
15#include "llvm/Support/Error.h"
22 : m_importer(&importer),
25 std::initializer_list<const char *> supported_names = {
45 m_supported_templates.insert(supported_names.begin(), supported_names.end());
55 std::vector<Scope *> &result) {
59 if (
auto parent = ctxt->getParent()) {
63 new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics());
64 scope->setEntity(ctxt);
65 result.push_back(scope);
67 result.push_back(sema.TUScope);
71static std::unique_ptr<LookupResult>
73 IdentifierInfo &ident = sema.getASTContext().Idents.get(name);
75 std::unique_ptr<LookupResult> lookup_result;
76 lookup_result = std::make_unique<LookupResult>(sema, DeclarationName(&ident),
78 Sema::LookupOrdinaryName);
83 std::vector<Scope *> scopes;
87 sema.LookupName(*lookup_result, scopes.back());
91 for (Scope *s : scopes)
92 if (s->getDepth() != 0)
109 void log(llvm::raw_ostream &
OS)
const override {
110 OS << llvm::formatv(
"error when reconstructing context of kind {0}:{1}",
115 return llvm::inconvertibleErrorCode();
124static llvm::Expected<DeclContext *>
128 while (foreign_ctxt && foreign_ctxt->isInlineNamespace())
129 foreign_ctxt = foreign_ctxt->getParent();
132 if (foreign_ctxt->isTranslationUnit())
133 return sema.getASTContext().getTranslationUnitDecl();
136 llvm::Expected<DeclContext *> parent =
142 if (foreign_ctxt->isNamespace()) {
143 NamedDecl *ns = llvm::cast<NamedDecl>(foreign_ctxt);
144 llvm::StringRef ns_name = ns->getName();
147 for (NamedDecl *named_decl : *lookup_result) {
148 if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl))
149 return DC->getPrimaryContext();
151 return llvm::make_error<MissingDeclContext>(
153 "Couldn't find namespace " + ns->getQualifiedNameAsString());
156 return llvm::make_error<MissingDeclContext>(foreign_ctxt,
"Unknown context ");
162 for (
const TemplateArgument &arg : a) {
163 switch (arg.getKind()) {
164 case TemplateArgument::Type:
165 case TemplateArgument::Integral:
177template <
typename T,
typename...
Args>
179 T *to_d = T::Create(std::forward<Args>(args)...);
180 importer.RegisterImportedDecl(from_d, to_d);
188 auto td = dyn_cast<ClassTemplateSpecializationDecl>(d);
193 if (!td->getDeclContext()->isStdNamespace())
202 auto &foreign_args = td->getTemplateInstantiationArgs();
208 llvm::Expected<DeclContext *> to_context =
212 "Got error while searching equal local DeclContext for decl "
219 std::unique_ptr<LookupResult> lookup =
222 ClassTemplateDecl *new_class_template =
nullptr;
223 for (
auto LD : *lookup) {
224 if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD)))
227 if (!new_class_template)
231 llvm::SmallVector<TemplateArgument, 4> imported_args;
234 for (
const TemplateArgument &arg : foreign_args.asArray()) {
235 switch (arg.getKind()) {
236 case TemplateArgument::Type: {
237 llvm::Expected<QualType> type =
m_importer->Import(arg.getAsType());
239 LLDB_LOG_ERROR(log, type.takeError(),
"Couldn't import type: {0}");
242 imported_args.push_back(
243 TemplateArgument(*type,
false, arg.getIsDefaulted()));
246 case TemplateArgument::Integral: {
247 llvm::APSInt integral = arg.getAsIntegral();
248 llvm::Expected<QualType> type =
251 LLDB_LOG_ERROR(log, type.takeError(),
"Couldn't import type: {0}");
254 imported_args.push_back(TemplateArgument(d->getASTContext(), integral,
255 *type, arg.getIsDefaulted()));
259 assert(
false &&
"templateArgsAreSupported not updated?");
265 void *InsertPos =
nullptr;
266 ClassTemplateSpecializationDecl *result =
267 new_class_template->findSpecialization(imported_args, InsertPos);
277 result = createDecl<ClassTemplateSpecializationDecl>(
279 new_class_template->getTemplatedDecl()->getTagKind(),
280 new_class_template->getDeclContext(),
281 new_class_template->getTemplatedDecl()->getLocation(),
282 new_class_template->getLocation(), new_class_template, imported_args,
285 new_class_template->AddSpecialization(result, InsertPos);
286 if (new_class_template->isOutOfLine())
287 result->setLexicalDeclContext(
288 new_class_template->getLexicalDeclContext());
static llvm::raw_ostream & error(Stream &strm)
static void makeScopes(Sema &sema, DeclContext *ctxt, std::vector< Scope * > &result)
Builds a list of scopes that point into the given context.
static llvm::Expected< DeclContext * > getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt)
Given a foreign decl context, this function finds the equivalent local decl context in the ASTContext...
static bool templateArgsAreSupported(ArrayRef< TemplateArgument > a)
Returns true iff tryInstantiateStdTemplate supports instantiating a template with the given template ...
static std::unique_ptr< LookupResult > emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt)
Uses the Sema to look up the given name in the given DeclContext.
T * createDecl(ASTImporter &importer, Decl *from_d, Args &&... args)
Constructor function for Clang declarations.
#define LLDB_LOG_ERROR(log, error,...)
A command line argument class.
clang::Sema * m_sema
The Sema instance of the target ASTContext.
bool isValid() const
Returns true iff this instance is capable of importing any declarations in the target ASTContext.
CxxModuleHandler()=default
std::optional< clang::Decl * > Import(clang::Decl *d)
Attempts to import the given decl into the target ASTContext by deserializing it from the 'std' modul...
clang::ASTImporter * m_importer
The ASTImporter that should be used to import any Decls which aren't directly handled by this class i...
std::optional< clang::Decl * > tryInstantiateStdTemplate(clang::Decl *d)
Tries to manually instantiate the given foreign template in the target context (designated by m_sema)...
llvm::StringSet m_supported_templates
List of template names this class currently supports.
A TypeSystem implementation based on Clang.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Error class for handling problems when finding a certain DeclContext.
MissingDeclContext(DeclContext *context, std::string error)
void log(llvm::raw_ostream &OS) const override
std::error_code convertToErrorCode() const override