From 89beedc1b592689168928e09dbfe47c53eeac3b5 Mon Sep 17 00:00:00 2001 From: Bradley Walters Date: Fri, 2 Jan 2026 21:36:49 -0800 Subject: [PATCH 1/5] clang-21: fix DTST->getIdentifier() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - **Line 7086-7089**: Stores `NestedNameSpecifier *NNS` and `const IdentifierInfo *Name` as separate membe rs - **Line 7098-7099**: Provides `getQualifier()` and `getIdentifier()` methods - **Line 7258**: Now stores a single `DependentTemplateStorage Name` member (instead of separate NNS and I dentifierInfo) - **Line 7266-7268**: Provides `getDependentTemplateName()` method that returns `const DependentTemplateSt orage&` - **Removed**: `getQualifier()` and `getIdentifier()` methods are gone The `DependentTemplateStorage` class (defined in TemplateName.h:582-621) provides: - `getQualifier()` → returns `NestedNameSpecifier*` - `getName()` → returns `IdentifierOrOverloadedOperator` The `IdentifierOrOverloadedOperator` struct (TemplateName.h:545-572) provides: - `getIdentifier()` → returns `const IdentifierInfo*` The failing code at CommonRenameClassRewriteVisitor.h:313: ```cpp const IdentifierInfo *IdInfo = DTST->getIdentifier(); ``` Should be changed to: ```cpp const IdentifierInfo *IdInfo = DTST->getDependentTemplateName().getName().getIdentifier(); ``` This chains the new API calls: 1. `getDependentTemplateName()` returns the `DependentTemplateStorage` 2. `getName()` returns the `IdentifierOrOverloadedOperator` 3. `getIdentifier()` returns the `const IdentifierInfo*` --- clang_delta/CommonRenameClassRewriteVisitor.h | 4 ++++ clang_delta/RemoveNamespace.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/clang_delta/CommonRenameClassRewriteVisitor.h b/clang_delta/CommonRenameClassRewriteVisitor.h index 371bebbe..94b3f6fb 100644 --- a/clang_delta/CommonRenameClassRewriteVisitor.h +++ b/clang_delta/CommonRenameClassRewriteVisitor.h @@ -310,7 +310,11 @@ template bool CommonRenameClassRewriteVisitor:: dyn_cast(Ty); TransAssert(DTST && "Bad DependentTemplateSpecializationType!"); +#if LLVM_VERSION_MAJOR >= 21 + const IdentifierInfo *IdInfo = DTST->getDependentTemplateName().getName().getIdentifier(); +#else const IdentifierInfo *IdInfo = DTST->getIdentifier(); +#endif std::string IdName = IdInfo->getName().str(); std::string Name; if (getNewNameByName(IdName, Name)) { diff --git a/clang_delta/RemoveNamespace.cpp b/clang_delta/RemoveNamespace.cpp index 0f8fc427..339f564d 100644 --- a/clang_delta/RemoveNamespace.cpp +++ b/clang_delta/RemoveNamespace.cpp @@ -440,7 +440,11 @@ bool RemoveNamespaceRewriteVisitor::VisitDependentTemplateSpecializationTypeLoc( dyn_cast(Ty); TransAssert(DTST && "Bad DependentTemplateSpecializationType!"); +#if LLVM_VERSION_MAJOR >= 21 + const IdentifierInfo *IdInfo = DTST->getDependentTemplateName().getName().getIdentifier(); +#else const IdentifierInfo *IdInfo = DTST->getIdentifier(); +#endif std::string IdName = IdInfo->getName().str(); std::string Name; From 37defd44a7f270360fb8c51d4a7f2e07be92189a Mon Sep 17 00:00:00 2001 From: Bradley Walters Date: Fri, 2 Jan 2026 21:40:22 -0800 Subject: [PATCH 2/5] clang-21: remove TypeSpecWithTemplate The enum has **6 values**: - Line 79-102: `Identifier`, `Namespace`, `NamespaceAlias`, `TypeSpec`, **`TypeSpecWithTemplate`**, `Globa l`, `Super` - Line 52-56: Storage enum includes `StoredTypeSpec = 2` and `StoredTypeSpecWithTemplate = 3` The enum has **5 values** (one removed): - Line 78-97: `Identifier`, `Namespace`, `NamespaceAlias`, `TypeSpec`, `Global`, `Super` - **`TypeSpecWithTemplate` was removed** - Line 52-55: Storage enum only has `StoredTypeSpec = 2` (no `StoredTypeSpecWithTemplate`) In LLVM 21, the distinction between `TypeSpec` and `TypeSpecWithTemplate` was eliminated. The `template` k eyword information is now stored differently (likely in the `TypeLoc` or associated location information r ather than in the specifier kind). Since both cases were doing the same thing (calling `TraverseTypeLoc`), and LLVM 21 merged them into a sin gle `TypeSpec` case, simply removing the `TypeSpecWithTemplate` case is the correct fix. The functionality remains the same because type specs with or without template keywords now both use the `TypeSpec` enum va lue. --- clang_delta/RemoveNamespace.cpp | 6 ++++-- clang_delta/Transformation.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/clang_delta/RemoveNamespace.cpp b/clang_delta/RemoveNamespace.cpp index 339f564d..1d680b64 100644 --- a/clang_delta/RemoveNamespace.cpp +++ b/clang_delta/RemoveNamespace.cpp @@ -566,8 +566,10 @@ bool RemoveNamespaceRewriteVisitor::TraverseNestedNameSpecifierLoc( ND = NAD->getNamespace()->getCanonicalDecl(); break; } - case NestedNameSpecifier::TypeSpec: // Fall-through - case NestedNameSpecifier::TypeSpecWithTemplate: +#if LLVM_VERSION_MAJOR < 21 + case NestedNameSpecifier::TypeSpecWithTemplate: // Fall-through +#endif + case NestedNameSpecifier::TypeSpec: TraverseTypeLoc(Loc.getTypeLoc()); break; default: diff --git a/clang_delta/Transformation.cpp b/clang_delta/Transformation.cpp index b350eec5..24765971 100644 --- a/clang_delta/Transformation.cpp +++ b/clang_delta/Transformation.cpp @@ -635,8 +635,10 @@ const DeclContext *Transformation::getDeclContextFromSpecifier( const NamespaceAliasDecl *NAD = NNS->getAsNamespaceAlias(); return NAD->getNamespace()->getCanonicalDecl(); } - case NestedNameSpecifier::TypeSpec: // Fall-through - case NestedNameSpecifier::TypeSpecWithTemplate: { +#if LLVM_VERSION_MAJOR < 21 + case NestedNameSpecifier::TypeSpecWithTemplate: // Fall-through +#endif + case NestedNameSpecifier::TypeSpec: { const Type *Ty = NNS->getAsType(); if (const RecordType *RT = Ty->getAs()) return RT->getDecl(); From 2c224f135a388aed92cfb3d39466b4938973ede3 Mon Sep 17 00:00:00 2001 From: Bradley Walters Date: Fri, 2 Jan 2026 21:41:44 -0800 Subject: [PATCH 3/5] clang-21: OpenCLKernelAttr --> DeviceKernelAttr The following kernel attributes existed: - `OpenCLKernelAttr` - for OpenCL kernels - `NVPTXKernelAttr` - for NVIDIA PTX kernels - `SYCLKernelAttr` - for SYCL kernels The attribute system was refactored: - **`OpenCLKernelAttr` was removed** - **`NVPTXKernelAttr` was removed** - Replaced with a unified `DeviceKernelAttr` attribute - `SYCLKernelEntryPointAttr` exists for SYCL-specific entry points LLVM 21 consolidated the various kernel attributes (`OpenCLKernelAttr`, `NVPTXKernelAttr`, etc.) into a si ngle unified `DeviceKernelAttr` that works across different device programming models (OpenCL, CUDA, etc.) . This change reflects the consolidation of kernel attributes in LLVM 21. The `DeviceKernelAttr` now covers what `OpenCLKernelAttr` (and other kernel attributes) used to represent. **Purpose**: The code is checking if a function is a kernel function that should not be removed even if it appears unused, since kernel functions are entry points called by the runtime. The new `DeviceKernelAttr` serves this same purpose across all device programming models. --- clang_delta/RemoveUnusedFunction.cpp | 4 ++++ clang_delta/RenameFun.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/clang_delta/RemoveUnusedFunction.cpp b/clang_delta/RemoveUnusedFunction.cpp index f0632be5..225942ed 100644 --- a/clang_delta/RemoveUnusedFunction.cpp +++ b/clang_delta/RemoveUnusedFunction.cpp @@ -254,7 +254,11 @@ bool RUFAnalysisVisitor::VisitFunctionDecl(FunctionDecl *FD) if (FD->isReferenced() || FD->isMain() || +#if LLVM_VERSION_MAJOR >= 21 + FD->hasAttr() || +#else FD->hasAttr() || +#endif ConsumerInstance->hasReferencedSpecialization(CanonicalFD) || ConsumerInstance->isInlinedSystemFunction(CanonicalFD) || ConsumerInstance->isInReferencedSet(CanonicalFD) || diff --git a/clang_delta/RenameFun.cpp b/clang_delta/RenameFun.cpp index 8dee2431..f7c2255e 100644 --- a/clang_delta/RenameFun.cpp +++ b/clang_delta/RenameFun.cpp @@ -261,7 +261,11 @@ void RenameFun::addFun(const FunctionDecl *FD) { std::string Name = FD->getNameAsString(); // Skip special functions +#if LLVM_VERSION_MAJOR >= 21 + if (isSpecialFun(Name) || FD->hasAttr()) +#else if (isSpecialFun(Name) || FD->hasAttr()) +#endif FunToNameMap[FD] = Name; if (FunToNameMap.find(FD) != FunToNameMap.end()) From d655dcce6a31eefe70761bdadca9e00cd0a3cd41 Mon Sep 17 00:00:00 2001 From: Bradley Walters Date: Fri, 2 Jan 2026 21:46:36 -0800 Subject: [PATCH 4/5] clang-21: avoid deprecated FileManager::getDirectory The deprecated `getDirectory()` method that returned `ErrorOr` was removed in LLVM 21. The migration path is to use `getOptionalDirectoryRef()` which returns an `OptionalDirectoryEntryRef`. **Why this works**: - The original code checks the boolean value of the `ErrorOr` result (true if directory exists, false otherwise) - The new code checks the boolean value of the `OptionalDirectoryEntryRef` (true if directory exists, false otherwise) - Both support implicit conversion to bool in the same way, so the logic remains identical --- clang_delta/TransformationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang_delta/TransformationManager.cpp b/clang_delta/TransformationManager.cpp index 79b17cee..bf66354e 100644 --- a/clang_delta/TransformationManager.cpp +++ b/clang_delta/TransformationManager.cpp @@ -125,7 +125,7 @@ bool TransformationManager::initializeCompilerInstance(std::string &ErrorMsg) ClangInstance->createFileManager(); if(CLCPath != NULL && ClangInstance->hasFileManager() && - ClangInstance->getFileManager().getDirectory(CLCPath, false)) { + ClangInstance->getFileManager().getOptionalDirectoryRef(CLCPath, false)) { Args.push_back("-I"); Args.push_back(CLCPath); } From 751ba235ec011a81f75d2658022443479fd753ac Mon Sep 17 00:00:00 2001 From: Bradley Walters Date: Fri, 2 Jan 2026 21:49:46 -0800 Subject: [PATCH 5/5] clang-21: call CompilerInvocation::getTargetOpts **LLVM 20 & 21 (CompilerInvocation.h:80)**: - `TargetOpts` is a **protected** member in `CompilerInvocationBase` - Direct access like `.TargetOpts` is not allowed from outside the class **Solution**: Use the public getter method `getTargetOpts()` instead of direct member access **LLVM 20 (TargetInfo.h:305-306)**: - Signature: `CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr &Opts)` - Accepts a `std::shared_ptr` (shared pointer) **LLVM 21 (TargetInfo.h:316-317)**: - Signature: `CreateTargetInfo(DiagnosticsEngine &Diags, TargetOptions &Opts)` - Accepts a `TargetOptions &` (reference) 1. The code was directly accessing the protected member `TargetOpts` instead of using the public getter 2. The `CreateTargetInfo` API changed from accepting a `shared_ptr` to accepting a reference **Why this works**: 1. `getTargetOpts()` is a public method (defined at line 250 in `CompilerInvocation`) that returns `TargetOptions &` 2. This matches the new LLVM 21 signature that expects `TargetOptions &` instead of `std::shared_ptr` 3. The getter dereferences the shared_ptr internally (`return *TargetOpts`), providing the reference that the new API needs --- clang_delta/TransformationManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang_delta/TransformationManager.cpp b/clang_delta/TransformationManager.cpp index bf66354e..700c42c5 100644 --- a/clang_delta/TransformationManager.cpp +++ b/clang_delta/TransformationManager.cpp @@ -146,8 +146,13 @@ bool TransformationManager::initializeCompilerInstance(std::string &ErrorMsg) } TargetInfo *Target = +#if LLVM_VERSION_MAJOR >= 21 + TargetInfo::CreateTargetInfo(ClangInstance->getDiagnostics(), + ClangInstance->getInvocation().getTargetOpts()); +#else TargetInfo::CreateTargetInfo(ClangInstance->getDiagnostics(), ClangInstance->getInvocation().TargetOpts); +#endif ClangInstance->setTarget(Target); if (const char *env = getenv("CREDUCE_INCLUDE_PATH")) {