15ffd83dbSDimitry Andric //===-- CxxModuleHandler.cpp ----------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/CxxModuleHandler.h" 105ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 115ffd83dbSDimitry Andric 125ffd83dbSDimitry Andric #include "lldb/Utility/Log.h" 135ffd83dbSDimitry Andric #include "clang/Sema/Lookup.h" 145ffd83dbSDimitry Andric #include "llvm/Support/Error.h" 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric using namespace lldb_private; 175ffd83dbSDimitry Andric using namespace clang; 185ffd83dbSDimitry Andric 195ffd83dbSDimitry Andric CxxModuleHandler::CxxModuleHandler(ASTImporter &importer, ASTContext *target) 205ffd83dbSDimitry Andric : m_importer(&importer), 215ffd83dbSDimitry Andric m_sema(TypeSystemClang::GetASTContext(target)->getSema()) { 225ffd83dbSDimitry Andric 235ffd83dbSDimitry Andric std::initializer_list<const char *> supported_names = { 245ffd83dbSDimitry Andric // containers 25e8d8bef9SDimitry Andric "array", 265ffd83dbSDimitry Andric "deque", 275ffd83dbSDimitry Andric "forward_list", 285ffd83dbSDimitry Andric "list", 295ffd83dbSDimitry Andric "queue", 305ffd83dbSDimitry Andric "stack", 315ffd83dbSDimitry Andric "vector", 325ffd83dbSDimitry Andric // pointers 335ffd83dbSDimitry Andric "shared_ptr", 345ffd83dbSDimitry Andric "unique_ptr", 355ffd83dbSDimitry Andric "weak_ptr", 36*fe6060f1SDimitry Andric // iterator 37*fe6060f1SDimitry Andric "move_iterator", 38*fe6060f1SDimitry Andric "__wrap_iter", 395ffd83dbSDimitry Andric // utility 405ffd83dbSDimitry Andric "allocator", 41e8d8bef9SDimitry Andric "pair", 425ffd83dbSDimitry Andric }; 435ffd83dbSDimitry Andric m_supported_templates.insert(supported_names.begin(), supported_names.end()); 445ffd83dbSDimitry Andric } 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric /// Builds a list of scopes that point into the given context. 475ffd83dbSDimitry Andric /// 485ffd83dbSDimitry Andric /// \param sema The sema that will be using the scopes. 495ffd83dbSDimitry Andric /// \param ctxt The context that the scope should look into. 505ffd83dbSDimitry Andric /// \param result A list of scopes. The scopes need to be freed by the caller 515ffd83dbSDimitry Andric /// (except the TUScope which is owned by the sema). 525ffd83dbSDimitry Andric static void makeScopes(Sema &sema, DeclContext *ctxt, 535ffd83dbSDimitry Andric std::vector<Scope *> &result) { 545ffd83dbSDimitry Andric // FIXME: The result should be a list of unique_ptrs, but the TUScope makes 555ffd83dbSDimitry Andric // this currently impossible as it's owned by the Sema. 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric if (auto parent = ctxt->getParent()) { 585ffd83dbSDimitry Andric makeScopes(sema, parent, result); 595ffd83dbSDimitry Andric 605ffd83dbSDimitry Andric Scope *scope = 615ffd83dbSDimitry Andric new Scope(result.back(), Scope::DeclScope, sema.getDiagnostics()); 625ffd83dbSDimitry Andric scope->setEntity(ctxt); 635ffd83dbSDimitry Andric result.push_back(scope); 645ffd83dbSDimitry Andric } else 655ffd83dbSDimitry Andric result.push_back(sema.TUScope); 665ffd83dbSDimitry Andric } 675ffd83dbSDimitry Andric 685ffd83dbSDimitry Andric /// Uses the Sema to look up the given name in the given DeclContext. 695ffd83dbSDimitry Andric static std::unique_ptr<LookupResult> 705ffd83dbSDimitry Andric emulateLookupInCtxt(Sema &sema, llvm::StringRef name, DeclContext *ctxt) { 715ffd83dbSDimitry Andric IdentifierInfo &ident = sema.getASTContext().Idents.get(name); 725ffd83dbSDimitry Andric 735ffd83dbSDimitry Andric std::unique_ptr<LookupResult> lookup_result; 745ffd83dbSDimitry Andric lookup_result = std::make_unique<LookupResult>(sema, DeclarationName(&ident), 755ffd83dbSDimitry Andric SourceLocation(), 765ffd83dbSDimitry Andric Sema::LookupOrdinaryName); 775ffd83dbSDimitry Andric 785ffd83dbSDimitry Andric // Usually during parsing we already encountered the scopes we would use. But 795ffd83dbSDimitry Andric // here don't have these scopes so we have to emulate the behavior of the 805ffd83dbSDimitry Andric // Sema during parsing. 815ffd83dbSDimitry Andric std::vector<Scope *> scopes; 825ffd83dbSDimitry Andric makeScopes(sema, ctxt, scopes); 835ffd83dbSDimitry Andric 845ffd83dbSDimitry Andric // Now actually perform the lookup with the sema. 855ffd83dbSDimitry Andric sema.LookupName(*lookup_result, scopes.back()); 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric // Delete all the allocated scopes beside the translation unit scope (which 885ffd83dbSDimitry Andric // has depth 0). 895ffd83dbSDimitry Andric for (Scope *s : scopes) 905ffd83dbSDimitry Andric if (s->getDepth() != 0) 915ffd83dbSDimitry Andric delete s; 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric return lookup_result; 945ffd83dbSDimitry Andric } 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric /// Error class for handling problems when finding a certain DeclContext. 975ffd83dbSDimitry Andric struct MissingDeclContext : public llvm::ErrorInfo<MissingDeclContext> { 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric static char ID; 1005ffd83dbSDimitry Andric 1015ffd83dbSDimitry Andric MissingDeclContext(DeclContext *context, std::string error) 1025ffd83dbSDimitry Andric : m_context(context), m_error(error) {} 1035ffd83dbSDimitry Andric 1045ffd83dbSDimitry Andric DeclContext *m_context; 1055ffd83dbSDimitry Andric std::string m_error; 1065ffd83dbSDimitry Andric 1075ffd83dbSDimitry Andric void log(llvm::raw_ostream &OS) const override { 1085ffd83dbSDimitry Andric OS << llvm::formatv("error when reconstructing context of kind {0}:{1}", 1095ffd83dbSDimitry Andric m_context->getDeclKindName(), m_error); 1105ffd83dbSDimitry Andric } 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric std::error_code convertToErrorCode() const override { 1135ffd83dbSDimitry Andric return llvm::inconvertibleErrorCode(); 1145ffd83dbSDimitry Andric } 1155ffd83dbSDimitry Andric }; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric char MissingDeclContext::ID = 0; 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric /// Given a foreign decl context, this function finds the equivalent local 1205ffd83dbSDimitry Andric /// decl context in the ASTContext of the given Sema. Potentially deserializes 1215ffd83dbSDimitry Andric /// decls from the 'std' module if necessary. 1225ffd83dbSDimitry Andric static llvm::Expected<DeclContext *> 1235ffd83dbSDimitry Andric getEqualLocalDeclContext(Sema &sema, DeclContext *foreign_ctxt) { 1245ffd83dbSDimitry Andric 1255ffd83dbSDimitry Andric // Inline namespaces don't matter for lookups, so let's skip them. 1265ffd83dbSDimitry Andric while (foreign_ctxt && foreign_ctxt->isInlineNamespace()) 1275ffd83dbSDimitry Andric foreign_ctxt = foreign_ctxt->getParent(); 1285ffd83dbSDimitry Andric 1295ffd83dbSDimitry Andric // If the foreign context is the TU, we just return the local TU. 1305ffd83dbSDimitry Andric if (foreign_ctxt->isTranslationUnit()) 1315ffd83dbSDimitry Andric return sema.getASTContext().getTranslationUnitDecl(); 1325ffd83dbSDimitry Andric 1335ffd83dbSDimitry Andric // Recursively find/build the parent DeclContext. 1345ffd83dbSDimitry Andric llvm::Expected<DeclContext *> parent = 1355ffd83dbSDimitry Andric getEqualLocalDeclContext(sema, foreign_ctxt->getParent()); 1365ffd83dbSDimitry Andric if (!parent) 1375ffd83dbSDimitry Andric return parent; 1385ffd83dbSDimitry Andric 1395ffd83dbSDimitry Andric // We currently only support building namespaces. 1405ffd83dbSDimitry Andric if (foreign_ctxt->isNamespace()) { 1415ffd83dbSDimitry Andric NamedDecl *ns = llvm::dyn_cast<NamedDecl>(foreign_ctxt); 1425ffd83dbSDimitry Andric llvm::StringRef ns_name = ns->getName(); 1435ffd83dbSDimitry Andric 1445ffd83dbSDimitry Andric auto lookup_result = emulateLookupInCtxt(sema, ns_name, *parent); 1455ffd83dbSDimitry Andric for (NamedDecl *named_decl : *lookup_result) { 1465ffd83dbSDimitry Andric if (DeclContext *DC = llvm::dyn_cast<DeclContext>(named_decl)) 1475ffd83dbSDimitry Andric return DC->getPrimaryContext(); 1485ffd83dbSDimitry Andric } 1495ffd83dbSDimitry Andric return llvm::make_error<MissingDeclContext>( 1505ffd83dbSDimitry Andric foreign_ctxt, 1515ffd83dbSDimitry Andric "Couldn't find namespace " + ns->getQualifiedNameAsString()); 1525ffd83dbSDimitry Andric } 1535ffd83dbSDimitry Andric 1545ffd83dbSDimitry Andric return llvm::make_error<MissingDeclContext>(foreign_ctxt, "Unknown context "); 1555ffd83dbSDimitry Andric } 1565ffd83dbSDimitry Andric 1575ffd83dbSDimitry Andric /// Returns true iff tryInstantiateStdTemplate supports instantiating a template 1585ffd83dbSDimitry Andric /// with the given template arguments. 1595ffd83dbSDimitry Andric static bool templateArgsAreSupported(ArrayRef<TemplateArgument> a) { 1605ffd83dbSDimitry Andric for (const TemplateArgument &arg : a) { 1615ffd83dbSDimitry Andric switch (arg.getKind()) { 1625ffd83dbSDimitry Andric case TemplateArgument::Type: 1635ffd83dbSDimitry Andric case TemplateArgument::Integral: 1645ffd83dbSDimitry Andric break; 1655ffd83dbSDimitry Andric default: 1665ffd83dbSDimitry Andric // TemplateArgument kind hasn't been handled yet. 1675ffd83dbSDimitry Andric return false; 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric } 1705ffd83dbSDimitry Andric return true; 1715ffd83dbSDimitry Andric } 1725ffd83dbSDimitry Andric 1735ffd83dbSDimitry Andric /// Constructor function for Clang declarations. Ensures that the created 1745ffd83dbSDimitry Andric /// declaration is registered with the ASTImporter. 1755ffd83dbSDimitry Andric template <typename T, typename... Args> 1765ffd83dbSDimitry Andric T *createDecl(ASTImporter &importer, Decl *from_d, Args &&... args) { 1775ffd83dbSDimitry Andric T *to_d = T::Create(std::forward<Args>(args)...); 1785ffd83dbSDimitry Andric importer.RegisterImportedDecl(from_d, to_d); 1795ffd83dbSDimitry Andric return to_d; 1805ffd83dbSDimitry Andric } 1815ffd83dbSDimitry Andric 1825ffd83dbSDimitry Andric llvm::Optional<Decl *> CxxModuleHandler::tryInstantiateStdTemplate(Decl *d) { 1835ffd83dbSDimitry Andric Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); 1845ffd83dbSDimitry Andric 1855ffd83dbSDimitry Andric // If we don't have a template to instiantiate, then there is nothing to do. 1865ffd83dbSDimitry Andric auto td = dyn_cast<ClassTemplateSpecializationDecl>(d); 1875ffd83dbSDimitry Andric if (!td) 188e8d8bef9SDimitry Andric return llvm::None; 1895ffd83dbSDimitry Andric 1905ffd83dbSDimitry Andric // We only care about templates in the std namespace. 1915ffd83dbSDimitry Andric if (!td->getDeclContext()->isStdNamespace()) 192e8d8bef9SDimitry Andric return llvm::None; 1935ffd83dbSDimitry Andric 1945ffd83dbSDimitry Andric // We have a list of supported template names. 195e8d8bef9SDimitry Andric if (!m_supported_templates.contains(td->getName())) 196e8d8bef9SDimitry Andric return llvm::None; 1975ffd83dbSDimitry Andric 1985ffd83dbSDimitry Andric // Early check if we even support instantiating this template. We do this 1995ffd83dbSDimitry Andric // before we import anything into the target AST. 2005ffd83dbSDimitry Andric auto &foreign_args = td->getTemplateInstantiationArgs(); 2015ffd83dbSDimitry Andric if (!templateArgsAreSupported(foreign_args.asArray())) 202e8d8bef9SDimitry Andric return llvm::None; 2035ffd83dbSDimitry Andric 2045ffd83dbSDimitry Andric // Find the local DeclContext that corresponds to the DeclContext of our 2055ffd83dbSDimitry Andric // decl we want to import. 2065ffd83dbSDimitry Andric llvm::Expected<DeclContext *> to_context = 2075ffd83dbSDimitry Andric getEqualLocalDeclContext(*m_sema, td->getDeclContext()); 2085ffd83dbSDimitry Andric if (!to_context) { 2095ffd83dbSDimitry Andric LLDB_LOG_ERROR(log, to_context.takeError(), 2105ffd83dbSDimitry Andric "Got error while searching equal local DeclContext for decl " 2115ffd83dbSDimitry Andric "'{1}':\n{0}", 2125ffd83dbSDimitry Andric td->getName()); 213e8d8bef9SDimitry Andric return llvm::None; 2145ffd83dbSDimitry Andric } 2155ffd83dbSDimitry Andric 2165ffd83dbSDimitry Andric // Look up the template in our local context. 2175ffd83dbSDimitry Andric std::unique_ptr<LookupResult> lookup = 2185ffd83dbSDimitry Andric emulateLookupInCtxt(*m_sema, td->getName(), *to_context); 2195ffd83dbSDimitry Andric 2205ffd83dbSDimitry Andric ClassTemplateDecl *new_class_template = nullptr; 2215ffd83dbSDimitry Andric for (auto LD : *lookup) { 2225ffd83dbSDimitry Andric if ((new_class_template = dyn_cast<ClassTemplateDecl>(LD))) 2235ffd83dbSDimitry Andric break; 2245ffd83dbSDimitry Andric } 2255ffd83dbSDimitry Andric if (!new_class_template) 226e8d8bef9SDimitry Andric return llvm::None; 2275ffd83dbSDimitry Andric 2285ffd83dbSDimitry Andric // Import the foreign template arguments. 2295ffd83dbSDimitry Andric llvm::SmallVector<TemplateArgument, 4> imported_args; 2305ffd83dbSDimitry Andric 2315ffd83dbSDimitry Andric // If this logic is changed, also update templateArgsAreSupported. 2325ffd83dbSDimitry Andric for (const TemplateArgument &arg : foreign_args.asArray()) { 2335ffd83dbSDimitry Andric switch (arg.getKind()) { 2345ffd83dbSDimitry Andric case TemplateArgument::Type: { 2355ffd83dbSDimitry Andric llvm::Expected<QualType> type = m_importer->Import(arg.getAsType()); 2365ffd83dbSDimitry Andric if (!type) { 2375ffd83dbSDimitry Andric LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); 238e8d8bef9SDimitry Andric return llvm::None; 2395ffd83dbSDimitry Andric } 2405ffd83dbSDimitry Andric imported_args.push_back(TemplateArgument(*type)); 2415ffd83dbSDimitry Andric break; 2425ffd83dbSDimitry Andric } 2435ffd83dbSDimitry Andric case TemplateArgument::Integral: { 2445ffd83dbSDimitry Andric llvm::APSInt integral = arg.getAsIntegral(); 2455ffd83dbSDimitry Andric llvm::Expected<QualType> type = 2465ffd83dbSDimitry Andric m_importer->Import(arg.getIntegralType()); 2475ffd83dbSDimitry Andric if (!type) { 2485ffd83dbSDimitry Andric LLDB_LOG_ERROR(log, type.takeError(), "Couldn't import type: {0}"); 249e8d8bef9SDimitry Andric return llvm::None; 2505ffd83dbSDimitry Andric } 2515ffd83dbSDimitry Andric imported_args.push_back( 2525ffd83dbSDimitry Andric TemplateArgument(d->getASTContext(), integral, *type)); 2535ffd83dbSDimitry Andric break; 2545ffd83dbSDimitry Andric } 2555ffd83dbSDimitry Andric default: 2565ffd83dbSDimitry Andric assert(false && "templateArgsAreSupported not updated?"); 2575ffd83dbSDimitry Andric } 2585ffd83dbSDimitry Andric } 2595ffd83dbSDimitry Andric 2605ffd83dbSDimitry Andric // Find the class template specialization declaration that 2615ffd83dbSDimitry Andric // corresponds to these arguments. 2625ffd83dbSDimitry Andric void *InsertPos = nullptr; 2635ffd83dbSDimitry Andric ClassTemplateSpecializationDecl *result = 2645ffd83dbSDimitry Andric new_class_template->findSpecialization(imported_args, InsertPos); 2655ffd83dbSDimitry Andric 2665ffd83dbSDimitry Andric if (result) { 2675ffd83dbSDimitry Andric // We found an existing specialization in the module that fits our arguments 2685ffd83dbSDimitry Andric // so we can treat it as the result and register it with the ASTImporter. 2695ffd83dbSDimitry Andric m_importer->RegisterImportedDecl(d, result); 2705ffd83dbSDimitry Andric return result; 2715ffd83dbSDimitry Andric } 2725ffd83dbSDimitry Andric 2735ffd83dbSDimitry Andric // Instantiate the template. 2745ffd83dbSDimitry Andric result = createDecl<ClassTemplateSpecializationDecl>( 2755ffd83dbSDimitry Andric *m_importer, d, m_sema->getASTContext(), 2765ffd83dbSDimitry Andric new_class_template->getTemplatedDecl()->getTagKind(), 2775ffd83dbSDimitry Andric new_class_template->getDeclContext(), 2785ffd83dbSDimitry Andric new_class_template->getTemplatedDecl()->getLocation(), 2795ffd83dbSDimitry Andric new_class_template->getLocation(), new_class_template, imported_args, 2805ffd83dbSDimitry Andric nullptr); 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric new_class_template->AddSpecialization(result, InsertPos); 2835ffd83dbSDimitry Andric if (new_class_template->isOutOfLine()) 2845ffd83dbSDimitry Andric result->setLexicalDeclContext( 2855ffd83dbSDimitry Andric new_class_template->getLexicalDeclContext()); 2865ffd83dbSDimitry Andric return result; 2875ffd83dbSDimitry Andric } 2885ffd83dbSDimitry Andric 2895ffd83dbSDimitry Andric llvm::Optional<Decl *> CxxModuleHandler::Import(Decl *d) { 2905ffd83dbSDimitry Andric if (!isValid()) 2915ffd83dbSDimitry Andric return {}; 2925ffd83dbSDimitry Andric 2935ffd83dbSDimitry Andric return tryInstantiateStdTemplate(d); 2945ffd83dbSDimitry Andric } 295