diff --git a/src/command/argument_parser.cpp b/src/command/argument_parser.cpp index 55543b9f..c7bd2a51 100644 --- a/src/command/argument_parser.cpp +++ b/src/command/argument_parser.cpp @@ -7,9 +7,9 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/Options.h" #include "clang/Driver/Types.h" +#include "clang/Options/OptionUtils.h" +#include "clang/Options/Options.h" namespace clice { @@ -35,7 +35,7 @@ struct Thief { template struct Thief<&opt::OptTable::DashDashParsing, &opt::OptTable::GroupedShortOptions>; -auto& option_table = driver::getDriverOptTable(); +auto& option_table = clang::getDriverOptTable(); } // namespace @@ -45,7 +45,7 @@ std::unique_ptr ArgumentParser::parse_one(unsigned& index) { return option_table.ParseOneArg(*this, index, opt::Visibility(visibility_mask)); } -using ID = clang::driver::options::ID; +using ID = clang::options::ID; bool is_discarded_option(unsigned id) { switch(id) { @@ -165,7 +165,7 @@ llvm::StringRef resource_dir() { if(exe.empty()) { return std::string{}; } - return clang::driver::Driver::GetResourcesPath(exe); + return clang::GetResourcesPath(exe); }(); return dir; } @@ -246,7 +246,7 @@ std::string print_argv(llvm::ArrayRef args) { } unsigned default_visibility(llvm::StringRef driver) { - namespace options = clang::driver::options; + namespace options = clang::options; auto name = llvm::sys::path::filename(driver); name.consume_back(".exe"); diff --git a/src/command/search_config.cpp b/src/command/search_config.cpp index 34ea2140..c326d4ea 100644 --- a/src/command/search_config.cpp +++ b/src/command/search_config.cpp @@ -6,11 +6,11 @@ #include "llvm/ADT/StringSet.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "clang/Driver/Options.h" +#include "clang/Options/Options.h" namespace clice { -using ID = clang::driver::options::ID; +using ID = clang::options::ID; SearchConfig extract_search_config(llvm::ArrayRef arguments, llvm::StringRef directory) { @@ -24,9 +24,12 @@ SearchConfig extract_search_config(llvm::ArrayRef arguments, std::vector after; auto make_absolute = [&](llvm::StringRef path) -> std::string { - llvm::SmallString<256> abs_path(path); - if(!llvm::sys::path::is_absolute(abs_path)) { - llvm::sys::fs::make_absolute(directory, abs_path); + llvm::SmallString<256> abs_path; + if(llvm::sys::path::is_absolute(path)) { + abs_path = path; + } else { + abs_path = directory; + llvm::sys::path::append(abs_path, path); } llvm::sys::path::remove_dots(abs_path, true); return abs_path.str().str(); diff --git a/src/compile/compilation.cpp b/src/compile/compilation.cpp index bce235f3..1da56ef5 100644 --- a/src/compile/compilation.cpp +++ b/src/compile/compilation.cpp @@ -7,6 +7,7 @@ #include "support/logging.h" #include "llvm/Support/Error.h" +#include "clang/Driver/CreateInvocationFromArgs.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Lex/PreprocessorOptions.h" @@ -246,13 +247,14 @@ CompilationStatus CompilationUnitRef::Self::run_clang( self.instance = std::make_unique(std::move(invocation)); auto& instance = *self.instance; - instance.createDiagnostics(*params.vfs, diagnostic_consumer.release(), true); + instance.createDiagnostics(diagnostic_consumer.release(), true); if(auto remapping = clang::createVFSFromCompilerInvocation(instance.getInvocation(), instance.getDiagnostics(), params.vfs)) { - instance.createFileManager(std::move(remapping)); + instance.setVirtualFileSystem(std::move(remapping)); } + instance.createFileManager(); if(!instance.createTarget()) { return CompilationStatus::SetupFail; diff --git a/src/compile/diagnostic.cpp b/src/compile/diagnostic.cpp index 73ad23a6..344c048f 100644 --- a/src/compile/diagnostic.cpp +++ b/src/compile/diagnostic.cpp @@ -26,7 +26,9 @@ llvm::StringRef DiagnosticID::diagnostic_code() const { SHOWINSYSHEADER, \ SHOWINSYSMACRO, \ DEFERRABLE, \ - CATEGORY) \ + CATEGORY, \ + DIAGID, \ + FLAGS) \ case clang::diag::ENUM: return #ENUM; #include "clang/Basic/DiagnosticASTKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" diff --git a/src/compile/implement.h b/src/compile/implement.h index 72b346a3..c0268d5e 100644 --- a/src/compile/implement.h +++ b/src/compile/implement.h @@ -6,7 +6,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang-tidy/ClangTidyCheck.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidyModule.h" #include "clang-tidy/ClangTidyOptions.h" namespace clice::tidy { diff --git a/src/compile/tidy.cpp b/src/compile/tidy.cpp index 1b516e38..f32dca2b 100644 --- a/src/compile/tidy.cpp +++ b/src/compile/tidy.cpp @@ -10,7 +10,7 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang-tidy/ClangTidyCheck.h" #include "clang-tidy/ClangTidyDiagnosticConsumer.h" -#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidyModule.h" #include "clang-tidy/ClangTidyOptions.h" namespace clice::tidy { diff --git a/src/feature/document_symbols.cpp b/src/feature/document_symbols.cpp index a9ca933b..bb88832b 100644 --- a/src/feature/document_symbols.cpp +++ b/src/feature/document_symbols.cpp @@ -63,7 +63,8 @@ auto symbol_detail(clang::ASTContext& context, const clang::NamedDecl& decl) -> clang::PrintingPolicy policy(context.getPrintingPolicy()); policy.SuppressScope = true; policy.SuppressUnwrittenScope = true; - policy.AnonymousTagLocations = false; + policy.AnonymousTagNameStyle = + llvm::to_underlying(clang::PrintingPolicy::AnonymousTagMode::Plain); policy.PolishForDeclaration = true; std::string detail; diff --git a/src/feature/inlay_hints.cpp b/src/feature/inlay_hints.cpp index a0eebd50..9b221080 100644 --- a/src/feature/inlay_hints.cpp +++ b/src/feature/inlay_hints.cpp @@ -131,8 +131,9 @@ public: policy(unit.context().getPrintingPolicy()) { // The sugared type is more useful in some cases, and the canonical // type in other cases. - policy.SuppressScope = true; // keep type names short - policy.AnonymousTagLocations = false; // do not print lambda locations + policy.SuppressScope = true; // keep type names short + policy.AnonymousTagNameStyle = + llvm::to_underlying(clang::PrintingPolicy::AnonymousTagMode::Plain); // Not setting PrintCanonicalTypes for "auto" allows // SuppressDefaultTemplateArgs (set by default) to have an effect. } diff --git a/src/feature/signature_help.cpp b/src/feature/signature_help.cpp index 16a57268..a139fd33 100644 --- a/src/feature/signature_help.cpp +++ b/src/feature/signature_help.cpp @@ -25,7 +25,8 @@ public: auto range = llvm::make_range(candidates, candidates + candidate_count); auto policy = sema.getPrintingPolicy(); - policy.AnonymousTagLocations = false; + policy.AnonymousTagNameStyle = + llvm::to_underlying(clang::PrintingPolicy::AnonymousTagMode::Plain); policy.SuppressStrongLifetime = true; policy.SuppressUnwrittenScope = true; policy.SuppressScope = true; diff --git a/src/index/usr_generation.cpp b/src/index/usr_generation.cpp index 2812c237..dba2ad50 100644 --- a/src/index/usr_generation.cpp +++ b/src/index/usr_generation.cpp @@ -504,14 +504,14 @@ bool USRGenerator::GenLoc(const Decl* D, bool IncludeOffset) { static void printQualifier(llvm::raw_ostream& Out, const LangOptions& LangOpts, - NestedNameSpecifier* NNS) { + NestedNameSpecifier NNS) { // FIXME: Encode the qualifier, don't just print it. PrintingPolicy PO(LangOpts); PO.SuppressTagKeyword = true; PO.SuppressUnwrittenScope = true; PO.ConstantArraySizeAsWritten = false; - PO.AnonymousTagLocations = false; - NNS->print(Out, PO); + PO.AnonymousTagNameStyle = llvm::to_underlying(PrintingPolicy::AnonymousTagMode::Plain); + NNS.print(Out, PO); } void USRGenerator::VisitType(QualType T) { @@ -740,7 +740,7 @@ void USRGenerator::VisitType(QualType T) { return; } if(const InjectedClassNameType* InjT = T->getAs()) { - T = InjT->getInjectedSpecializationType(); + T = InjT->desugar(); continue; } if(const auto* VT = T->getAs()) { diff --git a/src/semantic/ast_utility.cpp b/src/semantic/ast_utility.cpp index 0be1b7d4..cb9ef620 100644 --- a/src/semantic/ast_utility.cpp +++ b/src/semantic/ast_utility.cpp @@ -200,10 +200,6 @@ llvm::StringRef identifier_of(const clang::NamedDecl& D) { } llvm::StringRef identifier_of(clang::QualType type) { - if(const auto* ET = llvm::dyn_cast(type)) { - return identifier_of(ET->getNamedType()); - } - if(const auto* BT = llvm::dyn_cast(type)) { clang::PrintingPolicy PP(clang::LangOptions{}); PP.adjustForCPlusPlus(); @@ -308,12 +304,6 @@ const clang::NamedDecl* decl_of_impl(const void* T) { } auto decl_of(clang::QualType type) -> const clang::NamedDecl* { - // Strip type-sugar that wraps the underlying type without adding a decl - // (e.g. ElaboratedType for "struct Foo" vs plain "Foo"). - if(auto ET = type->getAs()) { - type = ET->getNamedType(); - } - if(auto TST = type->getAs()) { auto decl = TST->getTemplateName().getAsTemplateDecl(); if(type->isDependentType()) { @@ -405,8 +395,8 @@ std::string display_name_of(const clang::NamedDecl* decl) { // Handle 'using namespace'. They all have the same name - . if(auto* UD = llvm::dyn_cast(decl)) { out << "using namespace "; - if(auto* Qual = UD->getQualifier()) - Qual->print(out, policy); + if(auto Qual = UD->getQualifier()) + Qual.print(out, policy); UD->getNominatedNamespaceAsWritten()->printName(out); return out.str(); } @@ -433,8 +423,8 @@ std::string display_name_of(const clang::NamedDecl* decl) { } // Print nested name qualifier if it was written in the source code. - if(auto* qualifier = get_qualifier_loc(decl).getNestedNameSpecifier()) { - qualifier->print(out, policy); + if(auto qualifier = get_qualifier_loc(decl).getNestedNameSpecifier()) { + qualifier.print(out, policy); } // Print the name itself. diff --git a/src/semantic/filtered_ast_visitor.h b/src/semantic/filtered_ast_visitor.h index 2f09035a..dfa8ab59 100644 --- a/src/semantic/filtered_ast_visitor.h +++ b/src/semantic/filtered_ast_visitor.h @@ -107,7 +107,7 @@ public: return true; } - bool TraverseTypeLoc(clang::TypeLoc loc) { + bool TraverseTypeLoc(clang::TypeLoc loc, bool TraverseQualifier = true) { CHECK_DERIVED_IMPL(TraverseTypeLoc); if(!loc) { @@ -116,10 +116,10 @@ public: /// FIXME: Workaround for `QualifiedTypeLoc`. if(auto QL = loc.getAs()) { - return Base::TraverseTypeLoc(QL.getUnqualifiedLoc()); + return Base::TraverseTypeLoc(QL.getUnqualifiedLoc(), TraverseQualifier); } - return Base::TraverseTypeLoc(loc); + return Base::TraverseTypeLoc(loc, TraverseQualifier); } bool TraverseAttr(clang::Attr* attr) { @@ -132,9 +132,8 @@ public: return Base::TraverseAttr(attr); } - /// We don't want to node withou location information. - constexpr bool TraverseNestedNameSpecifier - [[gnu::always_inline]] (clang::NestedNameSpecifier*) { + /// We don't want to node without location information. + constexpr bool TraverseNestedNameSpecifier [[gnu::always_inline]] (clang::NestedNameSpecifier) { CHECK_DERIVED_IMPL(TraverseNestedNameSpecifier); return true; } diff --git a/src/semantic/resolver.cpp b/src/semantic/resolver.cpp index 49875212..78c9f667 100644 --- a/src/semantic/resolver.cpp +++ b/src/semantic/resolver.cpp @@ -167,7 +167,10 @@ static clang::QualType get_decl_type(clang::Decl* decl) { if(auto* TND = llvm::dyn_cast(decl)) return TND->getUnderlyingType(); if(auto* RD = llvm::dyn_cast(decl)) - return clang::QualType(RD->getTypeForDecl(), 0); + return decl->getASTContext().getTagType(clang::ElaboratedTypeKeyword::None, + std::nullopt, + RD, + false); return clang::QualType(); } @@ -205,14 +208,11 @@ public: /// Desugar dependent typedefs to expose template parameters for substitution. clang::QualType TransformTypedefType(clang::TypeLocBuilder& TLB, clang::TypedefTypeLoc TL) { - if(auto* TND = TL.getTypedefNameDecl()) { + if(auto* TND = TL.getDecl()) { auto underlying = TND->getUnderlyingType(); if(underlying->isDependentType()) { auto type = TransformType(underlying); if(!type.isNull()) { - if(auto ET = llvm::dyn_cast(type)) { - type = ET->getNamedType(); - } TLB.pushTrivial(context, type, {}); return type; } @@ -221,20 +221,10 @@ public: return Base::TransformTypedefType(TLB, TL); } - clang::QualType TransformElaboratedType(clang::TypeLocBuilder& TLB, - clang::ElaboratedTypeLoc TL) { - clang::QualType type = TransformType(TL.getNamedTypeLoc().getType()); - if(type.isNull()) { - return Base::TransformElaboratedType(TLB, TL); - } - TLB.pushTrivial(context, type, {}); - return type; - } - clang::QualType TransformInjectedClassNameType(clang::TypeLocBuilder& TLB, clang::InjectedClassNameTypeLoc TL) { auto ICT = TL.getTypePtr(); - clang::QualType type = TransformType(ICT->getInjectedSpecializationType()); + clang::QualType type = TransformType(ICT->desugar()); if(type.isNull()) { return Base::TransformInjectedClassNameType(TLB, TL); } @@ -496,24 +486,25 @@ public: } if(auto TST = type->getAs()) { - TD = TST->getTemplateName().getAsTemplateDecl(); - args = TST->template_arguments(); - } else if(auto DTST = type->getAs()) { - // If this DTST was already resolved (possibly to itself when unresolvable), - // skip the redundant lookup. - if(resolved.count(DTST)) { - return lookup_result(); - } + if(auto* DTN = TST->getTemplateName().getAsDependentTemplateName()) { + // If this dependent TST was already resolved (possibly to itself when + // unresolvable), skip the redundant lookup. + if(resolved.count(TST)) { + return lookup_result(); + } - auto& template_name = DTST->getDependentTemplateName(); - auto name = template_name.getName().getIdentifier(); - if(!name) { - return {}; - } + auto name = DTN->getName().getIdentifier(); + if(!name) { + return {}; + } - if(auto decl = preferred(lookup(template_name.getQualifier(), name))) { - TD = decl; - args = DTST->template_arguments(); + if(auto decl = preferred(lookup(DTN->getQualifier(), name))) { + TD = decl; + args = TST->template_arguments(); + } + } else { + TD = TST->getTemplateName().getAsTemplateDecl(); + args = TST->template_arguments(); } } @@ -536,45 +527,23 @@ public: return lookup_result(); } - lookup_result lookup(const clang::NestedNameSpecifier* NNS, clang::DeclarationName name) { + lookup_result lookup(clang::NestedNameSpecifier NNS, clang::DeclarationName name) { if(!NNS) { return lookup_result(); } - if(auto iter = resolved.find(NNS); iter != resolved.end()) { - return lookup(iter->second, name); - } - - // Handle each NestedNameSpecifier kind: - // - Identifier: dependent name in NNS chain (e.g. `base::type::inner`), resolve recursively - // - TypeSpec: concrete or dependent type used as qualifier (e.g. `vector::`) - // - Global/Namespace/NamespaceAlias/Super: not dependent, cannot resolve further - switch(NNS->getKind()) { - case clang::NestedNameSpecifier::Identifier: { - auto stack_size = stack.data.size(); - auto* decl = preferred(lookup(NNS->getPrefix(), NNS->getAsIdentifier())); - auto type = get_decl_type(decl); - if(!type.isNull()) { - type = substitute(type); - } - while(stack.data.size() > stack_size) { - stack.pop(); - } - if(!type.isNull()) { - resolved.try_emplace(NNS, type); - return lookup(type, name); - } - return {}; + // In LLVM 22+, the old Identifier NNS kind is represented as a Type + // (DependentNameType), so the Type case handles both old TypeSpec and + // Identifier cases via lookup(QualType, name) → TransformDependentNameType. + switch(NNS.getKind()) { + case clang::NestedNameSpecifier::Kind::Type: { + return lookup(clang::QualType(NNS.getAsType(), 0), name); } - case clang::NestedNameSpecifier::TypeSpec: { - return lookup(clang::QualType(NNS->getAsType(), 0), name); - } - - case clang::NestedNameSpecifier::Global: - case clang::NestedNameSpecifier::Namespace: - case clang::NestedNameSpecifier::NamespaceAlias: - case clang::NestedNameSpecifier::Super: { + case clang::NestedNameSpecifier::Kind::Global: + case clang::NestedNameSpecifier::Kind::Namespace: + case clang::NestedNameSpecifier::Kind::MicrosoftSuper: + case clang::NestedNameSpecifier::Kind::Null: { return {}; } } @@ -708,14 +677,14 @@ public: /// /// TODO: Replace with a general mechanism for resolving well-known standard /// library patterns, or improve the resolver to handle these chains naturally. - clang::QualType hole(clang::NestedNameSpecifier* NNS, + clang::QualType hole(clang::NestedNameSpecifier NNS, const clang::IdentifierInfo* member, TemplateArguments arguments) { - if(NNS->getKind() != clang::NestedNameSpecifier::TypeSpec) { + if(NNS.getKind() != clang::NestedNameSpecifier::Kind::Type) { return clang::QualType(); } - auto TST = NNS->getAsType()->getAs(); + auto TST = NNS.getAsType()->getAs(); if(!TST) { return clang::QualType(); } @@ -738,17 +707,18 @@ public: return clang::QualType(); auto T = arguments[0].getAsType(); - auto prefix = - clang::NestedNameSpecifier::Create(context, nullptr, Alloc.getTypePtr()); + clang::NestedNameSpecifier prefix(Alloc.getTypePtr()); auto rebind = sema.getPreprocessor().getIdentifierInfo("rebind"); - auto DTST = context.getDependentTemplateSpecializationType( - clang::ElaboratedTypeKeyword::None, - clang::DependentTemplateStorage(prefix, rebind, false), - arguments); + auto DTN = context.getDependentTemplateName( + clang::DependentTemplateStorage(prefix, rebind, false)); + auto TST = context.getTemplateSpecializationType(clang::ElaboratedTypeKeyword::None, + DTN, + arguments, + {}); - prefix = clang::NestedNameSpecifier::Create(context, prefix, DTST.getTypePtr()); + prefix = clang::NestedNameSpecifier(TST.getTypePtr()); auto other = sema.getPreprocessor().getIdentifierInfo("other"); auto DNT = context.getDependentNameType(clang::ElaboratedTypeKeyword::Typename, @@ -770,9 +740,11 @@ public: for(auto& arg: replaceArguments) { canonicalArguments.emplace_back(context.getCanonicalTemplateArgument(arg)); } - auto result = context.getTemplateSpecializationType(TST->getTemplateName(), - replaceArguments, - canonicalArguments); + auto result = + context.getTemplateSpecializationType(clang::ElaboratedTypeKeyword::None, + TST->getTemplateName(), + replaceArguments, + canonicalArguments); LOG_DEBUG( "{}" "hole: 'allocator_traits::rebind_alloc' → '{}'", pad(), @@ -859,7 +831,9 @@ public: clang::QualType TransformDependentNameType(clang::TypeLocBuilder& TLB, clang::DependentNameTypeLoc TL, - bool DeducedTSTContext = false) { + bool DeducedTSTContext = false, + clang::QualType ObjectType = {}, + clang::NamedDecl* UnqualLookup = nullptr) { auto* DNT = TL.getTypePtr(); LOG_DEBUG("{}" "resolve '{}'", pad(), clang::QualType(DNT, 0).getAsString()); ++indent; @@ -897,7 +871,7 @@ public: return original; } - auto* NNS = NNSLoc.getNestedNameSpecifier(); + auto NNS = NNSLoc.getNestedNameSpecifier(); auto stack_size = stack.data.size(); auto* decl = preferred(lookup(NNS, DNT->getIdentifier())); auto type = get_decl_type(decl); @@ -963,23 +937,32 @@ public: return original; } - using Base::TransformDependentTemplateSpecializationType; - - clang::QualType rebuild_dtst(clang::TypeLocBuilder& TLB, - clang::DependentTemplateSpecializationTypeLoc TL) { - auto* DTST = TL.getTypePtr(); - return TLB.push(clang::QualType(DTST, 0)) - .getType(); + clang::QualType rebuild_tst(clang::TypeLocBuilder& TLB, + clang::TemplateSpecializationTypeLoc TL) { + auto* TST = TL.getTypePtr(); + return TLB.push(clang::QualType(TST, 0)).getType(); } - clang::QualType TransformDependentTemplateSpecializationType( - clang::TypeLocBuilder& TLB, - clang::DependentTemplateSpecializationTypeLoc TL) { - auto* DTST = TL.getTypePtr(); - LOG_DEBUG("{}" "resolve DTST '{}'", pad(), clang::QualType(DTST, 0).getAsString()); + clang::QualType + TransformTemplateSpecializationType(clang::TypeLocBuilder& TLB, + clang::TemplateSpecializationTypeLoc TL, + clang::QualType ObjectType = {}, + clang::NamedDecl* FirstQualifierInScope = nullptr, + bool AllowInjectedClassName = false) { + auto* TST = TL.getTypePtr(); + auto* DTN = TST->getTemplateName().getAsDependentTemplateName(); + if(!DTN) { + return Base::TransformTemplateSpecializationType(TLB, + TL, + ObjectType, + FirstQualifierInScope, + AllowInjectedClassName); + } + + LOG_DEBUG("{}" "resolve dependent TST '{}'", pad(), clang::QualType(TST, 0).getAsString()); ++indent; - if(auto iter = resolved.find(DTST); iter != resolved.end()) { + if(auto iter = resolved.find(TST); iter != resolved.end()) { --indent; TLB.pushTrivial(context, iter->second, {}); return iter->second; @@ -987,19 +970,19 @@ public: auto NNSLoc = TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); if(!NNSLoc) { - LOG_DEBUG("{}→ ", pad()); + LOG_DEBUG("{}→ ", pad()); --indent; - return rebuild_dtst(TLB, TL); + return rebuild_tst(TLB, TL); } - auto* NNS = NNSLoc.getNestedNameSpecifier(); + auto NNS = NNSLoc.getNestedNameSpecifier(); clang::TemplateArgumentListInfo info; - using iterator = clang::TemplateArgumentLocContainerIterator< - clang::DependentTemplateSpecializationTypeLoc>; + using iterator = + clang::TemplateArgumentLocContainerIterator; if(TransformTemplateArguments(iterator(TL, 0), iterator(TL, TL.getNumArgs()), info)) { - LOG_DEBUG("{}→ ", pad()); + LOG_DEBUG("{}→ ", pad()); --indent; - return rebuild_dtst(TLB, TL); + return rebuild_tst(TLB, TL); } llvm::SmallVector arguments; @@ -1007,17 +990,17 @@ public: arguments.push_back(arg.getArgument()); } - auto* name = DTST->getDependentTemplateName().getName().getIdentifier(); + auto* name = DTN->getName().getIdentifier(); if(!name) { - LOG_DEBUG("{}→ ", pad()); + LOG_DEBUG("{}→ ", pad()); --indent; - return rebuild_dtst(TLB, TL); + return rebuild_tst(TLB, TL); } if(auto result = hole(NNS, name, arguments); !result.isNull()) { LOG_DEBUG("{}" "hole: '{}' → '{}'", pad(), name->getName().str(), result.getAsString()); --indent; - resolved.try_emplace(DTST, result); + resolved.try_emplace(TST, result); TLB.pushTrivial(context, result, {}); return result; } @@ -1037,26 +1020,25 @@ public: if(!type.isNull()) { LOG_DEBUG("{}" "→ '{}' (alias)", pad(), type.getAsString()); --indent; - resolved.try_emplace(DTST, type); + resolved.try_emplace(TST, type); TLB.pushTrivial(context, type, {}); return type; } } } else if(auto* CTD = llvm::dyn_cast(decl)) { - // Resolve DTST to a concrete TemplateSpecializationType. - // e.g. __alloc_traits>::rebind → rebind (a TST) - // This allows subsequent lookup of members (like "other") to work. - // Keep lookup frames on stack — the caller (e.g. TransformNestedNameSpecifierLoc - // processing A::B::C) needs them for parameter substitution. clang::TemplateName TN(CTD); llvm::SmallVector canonArgs; for(auto& arg: arguments) { canonArgs.push_back(context.getCanonicalTemplateArgument(arg)); } - auto result = context.getTemplateSpecializationType(TN, arguments, canonArgs); + auto result = + context.getTemplateSpecializationType(clang::ElaboratedTypeKeyword::None, + TN, + arguments, + canonArgs); LOG_DEBUG("{}" "→ TST '{}' (class)", pad(), result.getAsString()); --indent; - resolved.try_emplace(DTST, result); + resolved.try_emplace(TST, result); TLB.pushTrivial(context, result, {}); return result; } @@ -1065,10 +1047,10 @@ public: stack.pop(); } - LOG_DEBUG("{}→ ", pad()); + LOG_DEBUG("{}→ ", pad()); --indent; - auto fallback = rebuild_dtst(TLB, TL); - resolved.try_emplace(DTST, fallback); + auto fallback = rebuild_tst(TLB, TL); + resolved.try_emplace(TST, fallback); return fallback; } @@ -1077,14 +1059,11 @@ public: /// its own TransformTypedefType). Using substitute() here ensures that typedef /// expansion does NOT trigger heuristic lookup, preventing the typedef ↔ lookup cycle. clang::QualType TransformTypedefType(clang::TypeLocBuilder& TLB, clang::TypedefTypeLoc TL) { - if(auto* TND = TL.getTypedefNameDecl()) { + if(auto* TND = TL.getDecl()) { auto underlying = TND->getUnderlyingType(); if(underlying->isDependentType()) { auto type = substitute(underlying); if(!type.isNull()) { - if(auto ET = llvm::dyn_cast(type)) { - type = ET->getNamedType(); - } TLB.pushTrivial(context, type, {}); return type; } @@ -1140,7 +1119,7 @@ clang::QualType TemplateResolver::resugar(clang::QualType type, clang::Decl* dec return resugar.TransformType(type); } -TemplateResolver::lookup_result TemplateResolver::lookup(const clang::NestedNameSpecifier* NNS, +TemplateResolver::lookup_result TemplateResolver::lookup(clang::NestedNameSpecifier NNS, clang::DeclarationName name) { PseudoInstantiator instantiator(sema, resolved); return instantiator.lookup(NNS, name); diff --git a/src/semantic/resolver.h b/src/semantic/resolver.h index 15557eab..aee72ce0 100644 --- a/src/semantic/resolver.h +++ b/src/semantic/resolver.h @@ -41,17 +41,17 @@ public: using lookup_result = clang::DeclContext::lookup_result; /// Look up the name in the given nested name specifier. - lookup_result lookup(const clang::NestedNameSpecifier* NNS, clang::DeclarationName name); + lookup_result lookup(clang::NestedNameSpecifier NNS, clang::DeclarationName name); lookup_result lookup(const clang::DependentNameType* type) { return lookup(type->getQualifier(), type->getIdentifier()); } - lookup_result lookup(const clang::DependentTemplateSpecializationType* type) { - auto& template_name = type->getDependentTemplateName(); - auto identifier = template_name.getName().getIdentifier(); + lookup_result lookup(const clang::TemplateSpecializationType* type, + const clang::DependentTemplateName* DTN) { + auto identifier = DTN->getName().getIdentifier(); if(identifier) { - return lookup(template_name.getQualifier(), identifier); + return lookup(DTN->getQualifier(), identifier); } else { /// TODO: Operators don't have an IdentifierInfo; need DeclarationName-based lookup. return {}; diff --git a/src/semantic/selection.cpp b/src/semantic/selection.cpp index f30970af..0697ca00 100644 --- a/src/semantic/selection.cpp +++ b/src/semantic/selection.cpp @@ -756,8 +756,8 @@ public: return traverse_node(X, [&] { return Base::TraverseDecl(X); }); } - bool TraverseTypeLoc(clang::TypeLoc X) { - return traverse_node(&X, [&] { return Base::TraverseTypeLoc(X); }); + bool TraverseTypeLoc(clang::TypeLoc X, bool TraverseQualifier = true) { + return traverse_node(&X, [&] { return Base::TraverseTypeLoc(X, TraverseQualifier); }); } bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& X) { @@ -814,9 +814,9 @@ public: // This means we'd never see 'int' in 'const int'! Work around that here. // (The reason for the behavior is to avoid traversing the nested Type twice, // but we ignore TraverseType anyway). - bool TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc QX) { + bool TraverseQualifiedTypeLoc(clang::QualifiedTypeLoc QX, bool TraverseQualifier = true) { return traverse_node(&QX, [&] { - return TraverseTypeLoc(QX.getUnqualifiedLoc()); + return TraverseTypeLoc(QX.getUnqualifiedLoc(), TraverseQualifier); }); } @@ -825,7 +825,7 @@ public: } // Uninteresting parts of the AST that don't have locations within them. - bool TraverseNestedNameSpecifier(clang::NestedNameSpecifier*) { + bool TraverseNestedNameSpecifier(clang::NestedNameSpecifier) { return true; } diff --git a/src/semantic/semantic_visitor.h b/src/semantic/semantic_visitor.h index 74729195..06df783a 100644 --- a/src/semantic/semantic_visitor.h +++ b/src/semantic/semantic_visitor.h @@ -515,7 +515,7 @@ public: /// using Foo = int; Foo foo; /// ^~~~ reference VISIT_TYPELOC(TypedefTypeLoc) { - auto decl = loc.getTypedefNameDecl(); + auto decl = loc.getDecl(); auto location = loc.getNameLoc(); handleDeclOccurrence(decl, RelationKind::Reference, location); handleRelation(decl, RelationKind::Reference, decl, location); @@ -561,14 +561,9 @@ public: /// std::allocator::rebind /// ^~~~ reference - VISIT_TYPELOC(DependentTemplateSpecializationTypeLoc) { - auto location = loc.getTemplateNameLoc(); - // for(auto decl: resolver.lookup(loc.getTypePtr())) { - // handleDeclOccurrence(decl, RelationKind::WeakReference, location); - // handleRelation(decl, RelationKind::WeakReference, decl, location); - // } - return true; - } + /// Note: In LLVM 22+, DependentTemplateSpecializationTypeLoc was merged + /// into TemplateSpecializationTypeLoc. Dependent template cases are now + /// handled by the TemplateSpecializationTypeLoc visitor above. /// ============================================================================ /// Specifier @@ -576,32 +571,19 @@ public: bool VisitNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc) { auto NNS = loc.getNestedNameSpecifier(); - switch(NNS->getKind()) { - case clang::NestedNameSpecifier::Namespace: { - auto decl = NNS->getAsNamespace(); + switch(NNS.getKind()) { + case clang::NestedNameSpecifier::Kind::Namespace: { + auto [ns, prefix] = NNS.getAsNamespaceAndPrefix(); auto location = loc.getLocalBeginLoc(); - handleDeclOccurrence(decl, RelationKind::Reference, location); - handleRelation(decl, RelationKind::Reference, decl, location); + handleDeclOccurrence(ns, RelationKind::Reference, location); + handleRelation(ns, RelationKind::Reference, ns, location); break; } - case clang::NestedNameSpecifier::NamespaceAlias: { - auto decl = NNS->getAsNamespaceAlias(); - auto location = loc.getLocalBeginLoc(); - handleDeclOccurrence(decl, RelationKind::Reference, location); - handleRelation(decl, RelationKind::Reference, decl, location); - break; - } - - case clang::NestedNameSpecifier::Identifier: { - assert(NNS->isDependent() && "Identifier NNS should be dependent"); - // FIXME: use TemplateResolver here. - break; - } - - case clang::NestedNameSpecifier::TypeSpec: - case clang::NestedNameSpecifier::Global: - case clang::NestedNameSpecifier::Super: { + case clang::NestedNameSpecifier::Kind::Type: + case clang::NestedNameSpecifier::Kind::Global: + case clang::NestedNameSpecifier::Kind::MicrosoftSuper: + case clang::NestedNameSpecifier::Kind::Null: { break; }; } diff --git a/src/syntax/scan.cpp b/src/syntax/scan.cpp index 34603b82..43438603 100644 --- a/src/syntax/scan.cpp +++ b/src/syntax/scan.cpp @@ -10,6 +10,7 @@ #include "clang/Basic/FileEntry.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#include "clang/Driver/CreateInvocationFromArgs.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/PPCallbacks.h" @@ -319,9 +320,10 @@ std::unique_ptr } auto instance = std::make_unique(std::move(invocation)); - instance->createDiagnostics(*vfs, new clang::IgnoringDiagConsumer(), true); + instance->createDiagnostics(new clang::IgnoringDiagConsumer(), true); instance->getDiagnostics().setSuppressAllDiagnostics(true); - instance->createFileManager(vfs); + instance->setVirtualFileSystem(vfs); + instance->createFileManager(); return instance; }