compilerplugins/clang/badstatics.cxx                                    |    7 
-
 compilerplugins/clang/bufferadd.cxx                                     |    6 
-
 compilerplugins/clang/casttovoid.cxx                                    |   28 
++--
 compilerplugins/clang/check.cxx                                         |   58 
++++++----
 compilerplugins/clang/check.hxx                                         |   10 
-
 compilerplugins/clang/compat.hxx                                        |   50 
++++++++
 compilerplugins/clang/cstylecast.cxx                                    |   21 
+++
 compilerplugins/clang/dyncastvisibility.cxx                             |    7 
-
 compilerplugins/clang/external.cxx                                      |    6 
-
 compilerplugins/clang/faileddyncast.cxx                                 |    5 
 compilerplugins/clang/fieldcanbelocal.cxx                               |    2 
 compilerplugins/clang/implinheritancehelper.cxx                         |    3 
 compilerplugins/clang/indentation.cxx                                   |    5 
 compilerplugins/clang/logexceptionnicely.cxx                            |   13 
+-
 compilerplugins/clang/loopvartoosmall.cxx                               |    2 
 compilerplugins/clang/plugin.cxx                                        |    7 
-
 compilerplugins/clang/reducevarscope.cxx                                |    4 
 compilerplugins/clang/redundantcast.cxx                                 |    8 
+
 compilerplugins/clang/refcounting.cxx                                   |    3 
 compilerplugins/clang/referencecasting.cxx                              |   25 
+++-
 compilerplugins/clang/rendercontext.cxx                                 |    5 
 compilerplugins/clang/selfinit.cxx                                      |   22 
+++
 compilerplugins/clang/sfxpoolitem.cxx                                   |   28 
++--
 compilerplugins/clang/sharedvisitor/analyzer.cxx                        |   18 
++-
 compilerplugins/clang/sharedvisitor/generator.cxx                       |   37 
+++++-
 compilerplugins/clang/staticmethods.cxx                                 |   11 
+
 compilerplugins/clang/stringadd.cxx                                     |    6 
-
 compilerplugins/clang/test/getstr.cxx                                   |    2 
 compilerplugins/clang/test/indentation.cxx                              |   11 
+
 compilerplugins/clang/test/passstuffbyref.cxx                           |   20 
+--
 compilerplugins/clang/test/redundantfcast.cxx                           |    4 
 compilerplugins/clang/test/refcounting.cxx                              |   21 
++-
 compilerplugins/clang/trivialconstructor.cxx                            |    3 
 compilerplugins/clang/trivialdestructor.cxx                             |    3 
 compilerplugins/clang/typedefparam.cxx                                  |   18 
++-
 compilerplugins/clang/unnecessaryoverride.cxx                           |    5 
 compilerplugins/clang/unusedfields.cxx                                  |    6 
-
 compilerplugins/clang/unusedmember.cxx                                  |   40 
+++---
 compilerplugins/clang/unusedvariablecheck.cxx                           |    2 
 compilerplugins/clang/unusedvariablemore.cxx                            |    8 
-
 compilerplugins/clang/unusedvarsglobal.cxx                              |    3 
 compilerplugins/clang/vclwidgets.cxx                                    |    6 
-
 compilerplugins/clang/writeonlyvars.cxx                                 |    3 
 compilerplugins/clang/xmlimport.cxx                                     |    2 
 external/skia/UnpackedTarball_skia.mk                                   |    1 
 external/skia/modified-skcms-0001-Change-use-of-removed-intrinsic.patch |   42 
+++++++
 46 files changed, 437 insertions(+), 160 deletions(-)

New commits:
commit 060c1b69ef22dbf011d6d2c0e2d5fda3c6dc002b
Author:     Stephan Bergmann <stephan.bergm...@collabora.com>
AuthorDate: Thu Aug 14 07:30:09 2025 +0200
Commit:     Stephan Bergmann <stephan.bergm...@collabora.com>
CommitDate: Sun Aug 17 19:42:56 2025 +0200

    Adapt compilerplugins to recent LLVM 22 trunk change
    
    
...<https://github.com/llvm/llvm-project/commit/91cdd35008e9ab32dffb7e401cdd7313b3461892>
    "[clang] Improve nested name specifier AST representation (#147835)".
    
    For one, clang::TypeDecl::getTypeForDecl no longer works for TagDecls, so 
the
    loplugin::TypeCheck ctor taking a TypeDecl started to fail at runtime.  So 
heed
    the advice given in the comment to clang::TypeDecl::getTypeForDecl and 
instead
    "ckeck out ASTContext::getTypeDeclType or one of...", which means that we 
now
    need to transport a clang::ASTContext to all those places that want to 
create
    such a loplugin::TypeCheck.
    
    For another, clang::TagType::getDecl ("renamed to `getOriginalDecl`" for 
now) no
    longer returns one dedicated Decl per type (so its results could be 
compared for
    equality), so wrap that in compat::getDecl to do an additional 
getCanonicalDecl.
    (But note how that requires an additional compat::getDefinitionOrSelf 
across the
    various loplugins' isWarnUnusedType implementations, to check for any 
attributes
    on the actual definitions rather than on whatever first declarations happen 
to
    be considered the canonical decls.)
    
    And the visitor's TraverseDecltypeTypeLoc takes an additional bool
    TraverseQualifier parameter now, so adapt the sharedvisitor machinery
    accordingly.
    
    Plus some bespoke fixes across various loplugins.
    
    loplugin:indentation is hit by
    <https://github.com/llvm/llvm-project/issues/153540> "Clang getBeginLoc of 
some
    CXXConstructExpr has moved past namespace prefix" (which would cause false
    
    > core/dbaccess/source/core/recovery/subcomponentrecovery.cxx:546:18: 
error: statement mis-aligned compared to neighbours  [loplugin:indentation]
    >   546 |             rtl::Reference( new SubComponentLoader( xController, 
xDocDefinition ) );
    >       |                  ^
    > core/dbaccess/source/core/recovery/subcomponentrecovery.cxx:545:13: note: 
measured against this one [loplugin:indentation]
    >   545 |             Reference< XController > xController( m_xDocumentUI, 
UNO_QUERY_THROW );
    >       |             ^
    
    etc.), so is disabled for Clang 22 for now, until that bug is fixed.
    
    (Various diagnostics are slightly different now, leading to some more
    expected-error-re variation in the tests.  And loplugin::refcounting no 
longer
    duplicates its warnings, which is probably a feature and not a bug.)
    
    Change-Id: I9fe152e47ee571ad57c7c57f0eaa9c10e620f03e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189694
    Reviewed-by: Stephan Bergmann <stephan.bergm...@collabora.com>
    Tested-by: Jenkins

diff --git a/compilerplugins/clang/badstatics.cxx 
b/compilerplugins/clang/badstatics.cxx
index aa16d44b7d42..6ed8582940d3 100644
--- a/compilerplugins/clang/badstatics.cxx
+++ b/compilerplugins/clang/badstatics.cxx
@@ -12,6 +12,7 @@
 #include <cassert>
 
 #include "check.hxx"
+#include "compat.hxx"
 #include "plugin.hxx"
 
 namespace {
@@ -85,7 +86,7 @@ public:
             std::vector<QualType> copy(rParents);
             copy.push_back(rpType.getUnqualifiedType().getCanonicalType());
             auto ctsd = dyn_cast<ClassTemplateSpecializationDecl>(
-                pRecordType->getDecl());
+                compat::getDecl(pRecordType));
             assert(ctsd != nullptr);
             auto const & args = ctsd->getTemplateArgs();
             assert(args.size() >= 1);
@@ -99,7 +100,7 @@ public:
             std::vector<QualType> copy(rParents);
             copy.push_back(rpType.getUnqualifiedType().getCanonicalType());
             auto ctsd = dyn_cast<ClassTemplateSpecializationDecl>(
-                pRecordType->getDecl());
+                compat::getDecl(pRecordType));
             assert(ctsd != nullptr);
             auto const & args = ctsd->getTemplateArgs();
             assert(args.size() >= 2);
@@ -109,7 +110,7 @@ public:
             }
             return isBadStaticType(args.get(1).getAsType(), chain, copy);
         }
-        RecordDecl const*const 
pDefinition(pRecordType->getDecl()->getDefinition());
+        RecordDecl const*const 
pDefinition(compat::getDecl(pRecordType)->getDefinition());
         if (!pDefinition) { // maybe no definition if it's a pointer/reference
             return std::make_pair(false, std::vector<FieldDecl const*>());
         }
diff --git a/compilerplugins/clang/bufferadd.cxx 
b/compilerplugins/clang/bufferadd.cxx
index 0dd65868f640..161db77eb0e3 100644
--- a/compilerplugins/clang/bufferadd.cxx
+++ b/compilerplugins/clang/bufferadd.cxx
@@ -366,7 +366,8 @@ bool BufferAdd::isSideEffectFree(Expr const* expr)
             {
                 if (callExpr->getNumArgs() > 0)
                 {
-                    auto tc = 
loplugin::TypeCheck(calleeMethodDecl->getParent());
+                    auto tc = loplugin::TypeCheck(compat::getCanonicalTagType(
+                        compiler.getASTContext(), 
calleeMethodDecl->getParent()));
                     if (tc.Class("OUString") || tc.Class("OString"))
                     {
                         if (isSideEffectFree(callExpr->getArg(0)))
@@ -390,7 +391,8 @@ bool BufferAdd::isSideEffectFree(Expr const* expr)
         // O[U]String::operator std::[u16]string_view:
         if (auto const d = 
dyn_cast_or_null<CXXConversionDecl>(callExpr->getCalleeDecl()))
         {
-            auto tc = loplugin::TypeCheck(d->getParent());
+            auto tc = loplugin::TypeCheck(
+                compat::getCanonicalTagType(compiler.getASTContext(), 
d->getParent()));
             if (tc.Class("OString") || tc.Class("OUString"))
             {
                 return true;
diff --git a/compilerplugins/clang/casttovoid.cxx 
b/compilerplugins/clang/casttovoid.cxx
index 87c2f4852aac..4026162ea0c1 100644
--- a/compilerplugins/clang/casttovoid.cxx
+++ b/compilerplugins/clang/casttovoid.cxx
@@ -20,20 +20,6 @@
 
 namespace {
 
-bool isWarnUnusedType(QualType type) {
-    if (auto const t = type->getAs<TypedefType>()) {
-        if (t->getDecl()->hasAttr<WarnUnusedAttr>()) {
-            return true;
-        }
-    }
-    if (auto const t = type->getAs<RecordType>()) {
-        if (t->getDecl()->hasAttr<WarnUnusedAttr>()) {
-            return true;
-        }
-    }
-    return loplugin::isExtraWarnUnusedType(type);
-}
-
 Expr const * lookThroughInitListExpr(Expr const * expr) {
     if (auto const ile = dyn_cast<InitListExpr>(expr->IgnoreParenImpCasts())) {
         if (ile->getNumInits() == 1) {
@@ -445,6 +431,20 @@ private:
         }
     }
 
+    bool isWarnUnusedType(QualType type) {
+        if (auto const t = type->getAs<TypedefType>()) {
+            if (t->getDecl()->hasAttr<WarnUnusedAttr>()) {
+                return true;
+            }
+        }
+        if (auto const t = type->getAs<RecordType>()) {
+            if 
(compat::getDefinitionOrSelf(compat::getDecl(t))->hasAttr<WarnUnusedAttr>()) {
+                return true;
+            }
+        }
+        return loplugin::isExtraWarnUnusedType(compiler.getASTContext(), type);
+    }
+
     bool isFromCIncludeFile(SourceLocation spellingLocation) const {
         return !compiler.getSourceManager().isInMainFile(spellingLocation)
             && compat::ends_with(
diff --git a/compilerplugins/clang/check.cxx b/compilerplugins/clang/check.cxx
index 524885ce16e4..433627c53f02 100644
--- a/compilerplugins/clang/check.cxx
+++ b/compilerplugins/clang/check.cxx
@@ -9,6 +9,7 @@
 
 #include <cassert>
 
+#include <clang/AST/ASTContext.h>
 #include <clang/AST/DeclCXX.h>
 #include <clang/AST/DeclTemplate.h>
 
@@ -253,9 +254,9 @@ clang::DeclContext const * 
ContextCheck::lookThroughLinkageSpec() const {
 
 namespace {
 
-bool BaseCheckNotSomethingInterestingSubclass(const clang::CXXRecordDecl 
*BaseDefinition) {
+bool BaseCheckNotSomethingInterestingSubclass(clang::ASTContext const & 
context, const clang::CXXRecordDecl *BaseDefinition) {
     if (BaseDefinition) {
-        auto tc = TypeCheck(BaseDefinition);
+        auto tc = TypeCheck(compat::getCanonicalTagType(context, 
BaseDefinition));
         if (tc.Class("Dialog").GlobalNamespace() || 
tc.Class("SfxPoolItem").GlobalNamespace()) {
             return false;
         }
@@ -263,10 +264,10 @@ bool BaseCheckNotSomethingInterestingSubclass(const 
clang::CXXRecordDecl *BaseDe
     return true;
 }
 
-bool isDerivedFromSomethingInteresting(const clang::CXXRecordDecl *decl) {
+bool isDerivedFromSomethingInteresting(clang::ASTContext const & context, 
const clang::CXXRecordDecl *decl) {
     if (!decl)
         return false;
-    auto tc = TypeCheck(decl);
+    auto tc = TypeCheck(compat::getCanonicalTagType(context, decl));
     if (tc.Class("Dialog"))
         return true;
     if (tc.Class("SfxPoolItem"))
@@ -277,7 +278,7 @@ bool isDerivedFromSomethingInteresting(const 
clang::CXXRecordDecl *decl) {
     if (// not sure what hasAnyDependentBases() does,
         // but it avoids classes we don't want, e.g. 
WeakAggComponentImplHelper1
         !decl->hasAnyDependentBases() &&
-        !decl->forallBases(BaseCheckNotSomethingInterestingSubclass)) {
+        !decl->forallBases([&context](clang::CXXRecordDecl const * 
BaseDefinition) { return BaseCheckNotSomethingInterestingSubclass(context, 
BaseDefinition); })) {
         return true;
     }
     return false;
@@ -285,12 +286,12 @@ bool isDerivedFromSomethingInteresting(const 
clang::CXXRecordDecl *decl) {
 
 }
 
-bool isExtraWarnUnusedType(clang::QualType type) {
+bool isExtraWarnUnusedType(clang::ASTContext const & context, clang::QualType 
type) {
     auto const rec = type->getAsCXXRecordDecl();
     if (rec == nullptr) {
         return false;
     }
-    auto const tc = TypeCheck(rec);
+    auto const tc = TypeCheck(compat::getCanonicalTagType(context, rec));
     // Check some common non-LO types:
     if (tc.Class("basic_string").StdNamespace()
         || tc.Class("deque").StdNamespace()
@@ -306,24 +307,43 @@ bool isExtraWarnUnusedType(clang::QualType type) {
     {
         return true;
     }
-    return isDerivedFromSomethingInteresting(rec);
+    return isDerivedFromSomethingInteresting(context, rec);
 }
 
-namespace {
-
 // Make sure Foo and ::Foo are considered equal:
 bool areSameSugaredType(clang::QualType type1, clang::QualType type2) {
-    auto t1 = type1.getLocalUnqualifiedType();
-    if (auto const et = llvm::dyn_cast<clang::ElaboratedType>(t1)) {
-        t1 = et->getNamedType();
+    if (type1.getQualifiers() != type2.getQualifiers()) {
+        return false;
+    }
+#if CLANG_VERSION >= 220000
+    if (type1->getTypeClass() != type2->getTypeClass()) {
+        return false;
+    }
+    if (auto const t = llvm::dyn_cast<clang::TagType>(type1)) {
+        return t->getOriginalDecl()->getCanonicalDecl() == 
llvm::dyn_cast<clang::TagType>(type2)->getOriginalDecl()->getCanonicalDecl();
     }
-    auto t2 = type2.getLocalUnqualifiedType();
-    if (auto const et = llvm::dyn_cast<clang::ElaboratedType>(t2)) {
-        t2 = et->getNamedType();
+    if (auto const t = llvm::dyn_cast<clang::TypedefType>(type1)) {
+        return t->getDecl() == 
llvm::dyn_cast<clang::TypedefType>(type2)->getDecl();
     }
-    return t1 == t2;
+    if (auto const t = llvm::dyn_cast<clang::UsingType>(type1)) {
+        return t->getDecl() == 
llvm::dyn_cast<clang::UsingType>(type2)->getDecl();
+    }
+    if (auto const t = type1->getPointeeType(); !t.isNull()) {
+        return areSameSugaredType(t, type2->getPointeeType());
+    }
+#else
+    if (auto const et = llvm::dyn_cast<clang::ElaboratedType>(type1)) {
+        type1 = et->getNamedType();
+    }
+    if (auto const et = llvm::dyn_cast<clang::ElaboratedType>(type2)) {
+        type2 = et->getNamedType();
+    }
+#endif
+    return type1 == type2;
 }
 
+namespace {
+
 bool isArithmeticOp(clang::Expr const * expr) {
     expr = expr->IgnoreParenImpCasts();
     if (auto const e = llvm::dyn_cast<clang::BinaryOperator>(expr)) {
@@ -362,7 +382,7 @@ bool isOkToRemoveArithmeticCast(
     // suffix like L it could still be either long or long long):
     if ((t1->isIntegralType(context)
          || t1->isRealFloatingType())
-        && ((!areSameSugaredType(t1, t2)
+        && ((!areSameSugaredType(t1.getLocalUnqualifiedType(), 
t2.getLocalUnqualifiedType())
              && (loplugin::TypeCheck(t1).Typedef()
                  || loplugin::TypeCheck(t2).Typedef()
                  || llvm::isa<clang::DecltypeType>(t1) || 
llvm::isa<clang::DecltypeType>(t2)))
@@ -394,7 +414,7 @@ bool forAnyBase(
         if (t == nullptr) {
             return false;
         }
-        auto const b = 
llvm::cast_or_null<clang::CXXRecordDecl>(t->getDecl()->getDefinition());
+        auto const b = 
llvm::cast_or_null<clang::CXXRecordDecl>(compat::getDecl(t)->getDefinition());
         if (b == nullptr || (b->isDependentContext() && 
!b->isCurrentInstantiation(decl))) {
             return false;
         }
diff --git a/compilerplugins/clang/check.hxx b/compilerplugins/clang/check.hxx
index 65ee16d77f2c..09b3b25b2ba3 100644
--- a/compilerplugins/clang/check.hxx
+++ b/compilerplugins/clang/check.hxx
@@ -38,8 +38,6 @@ public:
 
     explicit TypeCheck(clang::Type const * type): type_(type, 0) {}
 
-    explicit TypeCheck(clang::TypeDecl const * decl): 
type_(decl->getTypeForDecl(), 0) {}
-
     explicit operator bool() const { return !type_.isNull(); }
 
     TypeCheck NonConst() const;
@@ -192,7 +190,7 @@ ContextCheck TypeCheck::Class(llvm::StringRef id)
     if (!type_.isNull()) {
         auto const t = type_->getAs<clang::RecordType>();
         if (t != nullptr) {
-            return detail::checkRecordDecl(t->getDecl(), 
compat::TagTypeKind::Class, id);
+            return detail::checkRecordDecl(compat::getDecl(t), 
compat::TagTypeKind::Class, id);
         }
     }
     return ContextCheck();
@@ -203,7 +201,7 @@ ContextCheck TypeCheck::Struct(llvm::StringRef id) const
     if (!type_.isNull()) {
         auto const t = type_->getAs<clang::RecordType>();
         if (t != nullptr) {
-            return detail::checkRecordDecl(t->getDecl(), 
compat::TagTypeKind::Struct, id);
+            return detail::checkRecordDecl(compat::getDecl(t), 
compat::TagTypeKind::Struct, id);
         }
     }
     return ContextCheck();
@@ -307,7 +305,9 @@ ContextCheck ContextCheck::Struct(llvm::StringRef id) const
         llvm::dyn_cast_or_null<clang::Decl>(context_), 
compat::TagTypeKind::Struct, id);
 }
 
-bool isExtraWarnUnusedType(clang::QualType type);
+bool isExtraWarnUnusedType(clang::ASTContext const & context, clang::QualType 
type);
+
+bool areSameSugaredType(clang::QualType type1, clang::QualType type2);
 
 bool isOkToRemoveArithmeticCast(
     clang::ASTContext & context, clang::QualType t1, clang::QualType t2,
diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx
index d0965f26902e..cb184c19c906 100644
--- a/compilerplugins/clang/compat.hxx
+++ b/compilerplugins/clang/compat.hxx
@@ -12,6 +12,7 @@
 #include <string>
 #include <utility>
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
@@ -278,8 +279,55 @@ inline unsigned getBitWidthValue(clang::FieldDecl const * 
decl, clang::ASTContex
 #endif
 }
 
+inline
+clang::QualType getCanonicalTagType(clang::ASTContext const & context, 
clang::TagDecl const * decl)
+{
+#if CLANG_VERSION >= 220000
+    return context.getCanonicalTagType(decl);
+#else
+    return context.getTypeDeclType(decl);
+#endif
+}
+
+inline clang::TagDecl const * getDefinitionOrSelf(clang::TagDecl const * decl) 
{
+#if CLANG_VERSION >= 220000
+    return decl->getDefinitionOrSelf();
+#else
+    if (auto const def = decl->getDefinition()) {
+        return def;
+    }
+    return decl;
+#endif
+}
+
+inline clang::RecordDecl const * getDecl(clang::RecordType const * type) {
+#if CLANG_VERSION >= 220000
+    return 
llvm::cast<clang::RecordDecl>(type->getOriginalDecl()->getCanonicalDecl());
+#else
+    return type->getDecl();
+#endif
+}
+
+inline clang::EnumDecl const * getDecl(clang::EnumType const * type) {
+#if CLANG_VERSION >= 220000
+    return type->getOriginalDecl()->getCanonicalDecl();
+#else
+    return type->getDecl();
+#endif
+}
+
+inline clang::CXXRecordDecl const * getDecl(clang::InjectedClassNameType const 
* type) {
+#if CLANG_VERSION >= 220000
+    return type->getOriginalDecl()->getCanonicalDecl();
+#else
+    return type->getDecl();
+#endif
+}
+
 inline clang::Type const * getClass(clang::MemberPointerType const * type) {
-#if CLANG_VERSION >= 210000
+#if CLANG_VERSION >= 220000
+    return type->getQualifier().getAsType();
+#elif CLANG_VERSION >= 210000
     return type->getQualifier()->getAsType();
 #else
     return type->getClass();
diff --git a/compilerplugins/clang/cstylecast.cxx 
b/compilerplugins/clang/cstylecast.cxx
index ff63ec0e8f97..1be7bc1fb468 100644
--- a/compilerplugins/clang/cstylecast.cxx
+++ b/compilerplugins/clang/cstylecast.cxx
@@ -13,6 +13,8 @@
 #include <set>
 #include <string>
 
+#include "config_clang.h"
+
 #include "compat.hxx"
 #include "plugin.hxx"
 
@@ -155,14 +157,29 @@ bool canBeUsedForFunctionalCast(TypeSourceInfo const * 
info) {
              + int(loc.hasWrittenTypeSpec()))
             == 1;
     }
-    if (isa<TagType>(type) || isa<TemplateTypeParmType>(type) || 
isa<AutoType>(type)
-        || isa<DecltypeType>(type) || isa<TypedefType>(type))
+    if (isa<TemplateTypeParmType>(type) || isa<AutoType>(type) || 
isa<DecltypeType>(type))
+    {
+        return true;
+    }
+#if CLANG_VERSION >= 220000
+    if (auto const t = dyn_cast<TagType>(type)) {
+        return t->getKeyword() == compat::ElaboratedTypeKeyword::None;
+    }
+    if (auto const t = dyn_cast<TypedefType>(type)) {
+        return t->getKeyword() == compat::ElaboratedTypeKeyword::None;
+    }
+    if (auto const t = dyn_cast<UsingType>(type)) {
+        return t->getKeyword() == compat::ElaboratedTypeKeyword::None;
+    }
+#else
+    if (isa<TagType>(type) || isa<TypedefType>(type))
     {
         return true;
     }
     if (auto const t = dyn_cast<ElaboratedType>(type)) {
         return t->getKeyword() == compat::ElaboratedTypeKeyword::None;
     }
+#endif
     return false;
 }
 
diff --git a/compilerplugins/clang/dyncastvisibility.cxx 
b/compilerplugins/clang/dyncastvisibility.cxx
index c5f95c6ef273..fbe606c417b4 100644
--- a/compilerplugins/clang/dyncastvisibility.cxx
+++ b/compilerplugins/clang/dyncastvisibility.cxx
@@ -17,6 +17,7 @@
 
 #include "config_clang.h"
 
+#include "compat.hxx"
 #include "plugin.hxx"
 
 namespace {
@@ -50,7 +51,7 @@ bool isDerivedFrom(
     bool derived = false;
     for (auto const & i: decl->bases()) {
         auto const bd
-            = (cast<CXXRecordDecl>(i.getType()->getAs<RecordType>()->getDecl())
+            = 
(cast<CXXRecordDecl>(compat::getDecl(i.getType()->getAs<RecordType>()))
                ->getDefinition());
         assert(bd != nullptr);
         if (bd == base) {
@@ -106,7 +107,7 @@ public:
         if (rtd == nullptr) {
             return true;
         }
-        auto const rdd = cast<CXXRecordDecl>(rtd->getDecl())->getDefinition();
+        auto const rdd = 
cast<CXXRecordDecl>(compat::getDecl(rtd))->getDefinition();
         if (rdd == nullptr) {
             return true;
         }
@@ -153,7 +154,7 @@ public:
         if (rts == nullptr) { // in case it's a dependent type
             return true;
         }
-        auto const rds = cast<CXXRecordDecl>(rts->getDecl())->getDefinition();
+        auto const rds = 
cast<CXXRecordDecl>(compat::getDecl(rts))->getDefinition();
         assert(rds != nullptr);
         Bases bs;
         bool hidden = false;
diff --git a/compilerplugins/clang/external.cxx 
b/compilerplugins/clang/external.cxx
index 4b147e79e764..0b8a1f5efbbb 100644
--- a/compilerplugins/clang/external.cxx
+++ b/compilerplugins/clang/external.cxx
@@ -27,7 +27,7 @@ bool derivesFromTestFixture(CXXRecordDecl const* decl)
     static auto const pred = [](CXXBaseSpecifier const& spec) {
         if (auto const t = spec.getType()->getAs<RecordType>())
         { // (may be a template parameter)
-            return 
derivesFromTestFixture(dyn_cast<CXXRecordDecl>(t->getDecl()));
+            return 
derivesFromTestFixture(dyn_cast<CXXRecordDecl>(compat::getDecl(t)));
         }
         return false;
     };
@@ -321,7 +321,7 @@ private:
         assert(affected != nullptr);
         if (auto const d = dyn_cast<EnumDecl>(decl))
         {
-            affected->push_back(compiler.getASTContext().getEnumType(d));
+            
affected->push_back(compat::getCanonicalTagType(compiler.getASTContext(), d));
         }
         else
         {
@@ -335,7 +335,7 @@ private:
             {
                 rec = cast<CXXRecordDecl>(decl);
             }
-            affected->push_back(compiler.getASTContext().getRecordType(rec));
+            
affected->push_back(compat::getCanonicalTagType(compiler.getASTContext(), rec));
             for (auto d = rec->decls_begin(); d != rec->decls_end(); ++d)
             {
                 if (*d != (*d)->getCanonicalDecl())
diff --git a/compilerplugins/clang/faileddyncast.cxx 
b/compilerplugins/clang/faileddyncast.cxx
index 078d5c884b27..c8240a53c999 100644
--- a/compilerplugins/clang/faileddyncast.cxx
+++ b/compilerplugins/clang/faileddyncast.cxx
@@ -13,6 +13,7 @@
 #include "clang/AST/Attr.h"
 #include "clang/AST/CXXInheritance.h"
 
+#include "compat.hxx"
 #include "plugin.hxx"
 
 namespace {
@@ -45,7 +46,7 @@ bool isAlwaysNull(CXXDynamicCastExpr const * expr) {
   auto SrcRT = SrcType->getAs<RecordType>();
   if (!SrcRT)
     return false;
-  const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(SrcRT->getDecl());
+  const CXXRecordDecl *SrcRD = cast<CXXRecordDecl>(compat::getDecl(SrcRT));
 #endif
 
 #if 0
@@ -60,7 +61,7 @@ bool isAlwaysNull(CXXDynamicCastExpr const * expr) {
   auto DestRT = DestType->getAs<RecordType>();
   if (!DestRT)
     return false;
-  const CXXRecordDecl *DestRD = cast<CXXRecordDecl>(DestRT->getDecl());
+  const CXXRecordDecl *DestRD = cast<CXXRecordDecl>(compat::getDecl(DestRT));
 #endif
 
 #if 1
diff --git a/compilerplugins/clang/fieldcanbelocal.cxx 
b/compilerplugins/clang/fieldcanbelocal.cxx
index 9d4b60fd094b..bfb56b809e32 100644
--- a/compilerplugins/clang/fieldcanbelocal.cxx
+++ b/compilerplugins/clang/fieldcanbelocal.cxx
@@ -419,7 +419,7 @@ bool FieldCanBeLocal::VisitInitListExpr(const InitListExpr* 
initListExpr)
     if (!recordType)
         return true;
 
-    auto recordDecl = recordType->getDecl();
+    auto recordDecl = compat::getDecl(recordType);
     for (auto it = recordDecl->field_begin(); it != recordDecl->field_end(); 
++it)
     {
         checkTouched(*it, insideFunctionDecl);
diff --git a/compilerplugins/clang/implinheritancehelper.cxx 
b/compilerplugins/clang/implinheritancehelper.cxx
index 1eb1db60a90b..9b1237633a48 100644
--- a/compilerplugins/clang/implinheritancehelper.cxx
+++ b/compilerplugins/clang/implinheritancehelper.cxx
@@ -11,6 +11,7 @@
 #include <iostream>
 
 #include "check.hxx"
+#include "compat.hxx"
 #include "plugin.hxx"
 #include "config_clang.h"
 #include "clang/AST/CXXInheritance.h"
@@ -94,7 +95,7 @@ bool ImplInheritanceHelper::VisitCXXRecordDecl(const 
CXXRecordDecl* cxxRecordDec
         auto rt = i.getType()->getAs<RecordType>();
         if (!rt)
             continue;
-        auto const bd = cast<CXXRecordDecl>(rt->getDecl())->getDefinition();
+        auto const bd = 
cast<CXXRecordDecl>(compat::getDecl(rt))->getDefinition();
         auto ctx = bd->getDeclContext();
         if (!ctx->isNamespace())
             break;
diff --git a/compilerplugins/clang/indentation.cxx 
b/compilerplugins/clang/indentation.cxx
index cf2512d1d25d..3d5c17256bcd 100644
--- a/compilerplugins/clang/indentation.cxx
+++ b/compilerplugins/clang/indentation.cxx
@@ -191,10 +191,15 @@ bool Indentation::VisitCompoundStmt(CompoundStmt const* 
compoundStmt)
                     
locationAfterToken(compiler.getSourceManager().getExpansionLoc(actualPrevEnd)),
                     
compiler.getSourceManager().getExpansionLoc(stmt->getBeginLoc()))))
                 continue;
+#if CLANG_VERSION                                                              
                    \
+    == 220000 // see <https://github.com/llvm/llvm-project/issues/153540> 
"Clang getBeginLoc of some CXXConstructExpr has moved past namespace prefix"
+            (void)firstStmt;
+#else
             report(DiagnosticsEngine::Warning, "statement mis-aligned compared 
to neighbours %0",
                    stmtLoc)
                 << macroName;
             report(DiagnosticsEngine::Note, "measured against this one", 
firstStmt->getBeginLoc());
+#endif
             //getParentStmt(compoundStmt)->dump();
             //stmt->dump();
         }
diff --git a/compilerplugins/clang/logexceptionnicely.cxx 
b/compilerplugins/clang/logexceptionnicely.cxx
index 6cc66fdf0289..02247b38a034 100644
--- a/compilerplugins/clang/logexceptionnicely.cxx
+++ b/compilerplugins/clang/logexceptionnicely.cxx
@@ -12,6 +12,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "config_clang.h"
 #include <fstream>
 #include <unordered_set>
@@ -65,11 +66,12 @@ public:
             TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
     }
 
-    static bool BaseCheckNotExceptionSubclass(const CXXRecordDecl* 
BaseDefinition)
+    static bool BaseCheckNotExceptionSubclass(clang::ASTContext const& context,
+                                              const CXXRecordDecl* 
BaseDefinition)
     {
         if (!BaseDefinition)
             return true;
-        auto tc = loplugin::TypeCheck(BaseDefinition);
+        auto tc = loplugin::TypeCheck(compat::getCanonicalTagType(context, 
BaseDefinition));
         if (tc.Class("Exception")
                 .Namespace("uno")
                 .Namespace("star")
@@ -84,7 +86,7 @@ public:
     {
         if (!decl || !decl->hasDefinition())
             return false;
-        auto tc = loplugin::TypeCheck(decl);
+        auto tc = 
loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
decl));
         if (tc.Class("Exception")
                 .Namespace("uno")
                 .Namespace("star")
@@ -94,7 +96,10 @@ public:
             return true;
         if ( // not sure what hasAnyDependentBases() does,
             // but it avoids classes we don't want, e.g. 
WeakAggComponentImplHelper1
-            !decl->hasAnyDependentBases() && 
!decl->forallBases(BaseCheckNotExceptionSubclass))
+            !decl->hasAnyDependentBases()
+            && !decl->forallBases([this](const CXXRecordDecl* BaseDefinition) {
+                   return 
BaseCheckNotExceptionSubclass(compiler.getASTContext(), BaseDefinition);
+               }))
         {
             return true;
         }
diff --git a/compilerplugins/clang/loopvartoosmall.cxx 
b/compilerplugins/clang/loopvartoosmall.cxx
index 33f4fbf4adc2..262bc59ab264 100644
--- a/compilerplugins/clang/loopvartoosmall.cxx
+++ b/compilerplugins/clang/loopvartoosmall.cxx
@@ -75,7 +75,7 @@ private:
 
 unsigned LoopVarTooSmall::getIntValueWidth(QualType type) const {
     if (auto const et = type->getAs<EnumType>()) {
-        auto const ed = et->getDecl();
+        auto const ed = compat::getDecl(et);
         if (!ed->isFixed()) {
             unsigned pos = ed->getNumPositiveBits();
             unsigned neg = ed->getNumNegativeBits();
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index f47fc01bd074..bec85eb9ac01 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -966,9 +966,12 @@ static const CXXRecordDecl* stripTypeSugar(QualType qt)
     const clang::Type* t = qt.getTypePtr();
     do
     {
+#if CLANG_VERSION < 220000
         if (auto elaboratedType = dyn_cast<ElaboratedType>(t))
             t = elaboratedType->desugar().getTypePtr();
-        else if (auto tsType = dyn_cast<TemplateSpecializationType>(t))
+        else
+#endif
+        if (auto tsType = dyn_cast<TemplateSpecializationType>(t))
             t = tsType->desugar().getTypePtr();
         else if (auto sttpType = dyn_cast<SubstTemplateTypeParmType>(t))
             t = sttpType->desugar().getTypePtr();
@@ -980,7 +983,7 @@ static const CXXRecordDecl* stripTypeSugar(QualType qt)
     auto recordType = dyn_cast<RecordType>(t);
     if (!recordType)
         return nullptr;
-    return dyn_cast_or_null<CXXRecordDecl>(recordType->getDecl());
+    return dyn_cast_or_null<CXXRecordDecl>(compat::getDecl(recordType));
 }
 
 int derivedFromCount(const CXXRecordDecl* subclassRecordDecl, const 
CXXRecordDecl* baseclassRecordDecl)
diff --git a/compilerplugins/clang/reducevarscope.cxx 
b/compilerplugins/clang/reducevarscope.cxx
index 76eece2131bb..5555ab5dd85f 100644
--- a/compilerplugins/clang/reducevarscope.cxx
+++ b/compilerplugins/clang/reducevarscope.cxx
@@ -18,6 +18,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "config_clang.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/StmtVisitor.h"
@@ -455,7 +456,8 @@ bool ReduceVarScope::isTypeOK(QualType varType)
         return true;
     if (!varType->isRecordType())
         return false;
-    auto recordDecl = 
dyn_cast_or_null<CXXRecordDecl>(varType->getAs<RecordType>()->getDecl());
+    auto recordDecl
+        = 
dyn_cast_or_null<CXXRecordDecl>(compat::getDecl(varType->getAs<RecordType>()));
     if (recordDecl && recordDecl->hasTrivialDestructor())
         return true;
     auto const tc = loplugin::TypeCheck(varType);
diff --git a/compilerplugins/clang/redundantcast.cxx 
b/compilerplugins/clang/redundantcast.cxx
index 07efeb568606..283553db72fa 100644
--- a/compilerplugins/clang/redundantcast.cxx
+++ b/compilerplugins/clang/redundantcast.cxx
@@ -25,6 +25,8 @@
 
 #include "clang/Sema/Sema.h"
 
+#include "config_clang.h"
+
 #include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
@@ -67,9 +69,15 @@ char const * printExprValueKind(ExprValueKind k) {
 }
 
 QualType desugarElaboratedType(QualType type) {
+#if CLANG_VERSION >= 220000
+    if (auto const t = dyn_cast<TagType>(type)) {
+        return t->desugar();
+    }
+#else
     if (auto const t = dyn_cast<ElaboratedType>(type)) {
         return t->desugar();
     }
+#endif
     return type;
 }
 
diff --git a/compilerplugins/clang/refcounting.cxx 
b/compilerplugins/clang/refcounting.cxx
index 3b4cea9d368c..8eab3ff7f751 100644
--- a/compilerplugins/clang/refcounting.cxx
+++ b/compilerplugins/clang/refcounting.cxx
@@ -11,6 +11,7 @@
 #include <iostream>
 
 #include "check.hxx"
+#include "compat.hxx"
 #include "plugin.hxx"
 #include "config_clang.h"
 #include "clang/AST/CXXInheritance.h"
@@ -455,7 +456,7 @@ bool RefCounting::VisitTypeLoc(clang::TypeLoc typeLoc)
             || tc.ClassOrStruct("shared_ptr").StdNamespace()
             || 
tc.ClassOrStruct("intrusive_ptr").Namespace("boost").GlobalNamespace())
         {
-            auto templateDecl = 
dyn_cast<ClassTemplateSpecializationDecl>(recordType->getDecl());
+            auto templateDecl = 
dyn_cast<ClassTemplateSpecializationDecl>(compat::getDecl(recordType));
             if (templateDecl && templateDecl->getTemplateArgs().size() > 0)
                 firstTemplateParamType = 
templateDecl->getTemplateArgs()[0].getAsType();
         }
diff --git a/compilerplugins/clang/referencecasting.cxx 
b/compilerplugins/clang/referencecasting.cxx
index cff5b050ea9f..375176ee40ad 100644
--- a/compilerplugins/clang/referencecasting.cxx
+++ b/compilerplugins/clang/referencecasting.cxx
@@ -12,6 +12,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "config_clang.h"
 #include <iostream>
 
@@ -191,8 +192,10 @@ bool ReferenceCasting::VisitCXXConstructExpr(const 
CXXConstructExpr* cce)
     if (!argTemplateType)
         return true;
 
-    CXXRecordDecl* templateParamRD = 
dyn_cast<CXXRecordDecl>(templateParamType->getDecl());
-    CXXRecordDecl* constructorArgRD = 
dyn_cast<CXXRecordDecl>(argTemplateType->getDecl());
+    CXXRecordDecl const* templateParamRD
+        = dyn_cast<CXXRecordDecl>(compat::getDecl(templateParamType));
+    CXXRecordDecl const* constructorArgRD
+        = dyn_cast<CXXRecordDecl>(compat::getDecl(argTemplateType));
 
     // querying for XInterface (instead of doing an upcast) has special 
semantics,
     // to check for UNO object equivalence.
@@ -313,8 +316,9 @@ bool ReferenceCasting::VisitCXXMemberCallExpr(const 
CXXMemberCallExpr* mce)
     if (!argTemplateType)
         return true;
 
-    CXXRecordDecl* templateParamRD = 
dyn_cast<CXXRecordDecl>(templateParamType->getDecl());
-    CXXRecordDecl* methodArgRD = 
dyn_cast<CXXRecordDecl>(argTemplateType->getDecl());
+    CXXRecordDecl const* templateParamRD
+        = dyn_cast<CXXRecordDecl>(compat::getDecl(templateParamType));
+    CXXRecordDecl const* methodArgRD = 
dyn_cast<CXXRecordDecl>(compat::getDecl(argTemplateType));
 
     // querying for XInterface (instead of doing an upcast) has special 
semantics,
     // to check for UNO object equivalence.
@@ -427,8 +431,9 @@ bool ReferenceCasting::VisitCallExpr(const CallExpr* ce)
     if (!argTemplateType)
         return true;
 
-    CXXRecordDecl* templateParamRD = 
dyn_cast<CXXRecordDecl>(templateParamType->getDecl());
-    CXXRecordDecl* methodArgRD = 
dyn_cast<CXXRecordDecl>(argTemplateType->getDecl());
+    CXXRecordDecl const* templateParamRD
+        = dyn_cast<CXXRecordDecl>(compat::getDecl(templateParamType));
+    CXXRecordDecl const* methodArgRD = 
dyn_cast<CXXRecordDecl>(compat::getDecl(argTemplateType));
 
     // querying for XInterface (instead of doing an upcast) has special 
semantics,
     // to check for UNO object equivalence.
@@ -491,8 +496,10 @@ static const RecordType* extractTemplateType(QualType 
cceType)
     if (cceType->isPointerType())
     {
         auto pointeeType = cceType->getPointeeType();
+#if CLANG_VERSION < 220000
         if (auto elaboratedType = dyn_cast<ElaboratedType>(pointeeType))
             pointeeType = elaboratedType->desugar();
+#endif
         if (auto substTemplateTypeParmType = 
dyn_cast<SubstTemplateTypeParmType>(pointeeType))
             pointeeType = substTemplateTypeParmType->desugar();
         if (auto recordType = dyn_cast<RecordType>(pointeeType))
@@ -504,7 +511,7 @@ static const RecordType* extractTemplateType(QualType 
cceType)
     {
         if (auto recType = dyn_cast<RecordType>(subst->desugar()))
         {
-            if (auto ctsd = 
dyn_cast<ClassTemplateSpecializationDecl>(recType->getDecl()))
+            if (auto ctsd = 
dyn_cast<ClassTemplateSpecializationDecl>(compat::getDecl(recType)))
             {
                 auto const& args = ctsd->getTemplateArgs();
                 if (args.size() > 0 && args[0].getKind() == 
TemplateArgument::ArgKind::Type)
@@ -513,8 +520,10 @@ static const RecordType* extractTemplateType(QualType 
cceType)
         }
     }
 
+#if CLANG_VERSION < 220000
     if (auto elaboratedType = dyn_cast<ElaboratedType>(cceType))
         cceType = elaboratedType->desugar();
+#endif
     auto cceTST = dyn_cast<TemplateSpecializationType>(cceType);
     if (!cceTST)
         return NULL;
@@ -523,8 +532,10 @@ static const RecordType* extractTemplateType(QualType 
cceType)
         return NULL;
     const TemplateArgument& cceTA = args[0];
     QualType templateParamType = cceTA.getAsType();
+#if CLANG_VERSION < 220000
     if (auto elaboratedType = dyn_cast<ElaboratedType>(templateParamType))
         templateParamType = elaboratedType->desugar();
+#endif
     return dyn_cast<RecordType>(templateParamType);
 }
 
diff --git a/compilerplugins/clang/rendercontext.cxx 
b/compilerplugins/clang/rendercontext.cxx
index 2508b449e8eb..5e09f758cd05 100644
--- a/compilerplugins/clang/rendercontext.cxx
+++ b/compilerplugins/clang/rendercontext.cxx
@@ -12,6 +12,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "clang/AST/CXXInheritance.h"
 
 // Check for calls to OutputDevice methods that are not passing through 
RenderContext
@@ -53,7 +54,7 @@ bool RenderContext::TraverseFunctionDecl(const FunctionDecl * 
pFunctionDecl)
     // Ignore methods inside the OutputDevice class
     const CXXMethodDecl *pCXXMethodDecl = 
dyn_cast<CXXMethodDecl>(pFunctionDecl);
     if (pCXXMethodDecl) {
-        if 
(loplugin::TypeCheck(pCXXMethodDecl->getParent()).Class("OutputDevice").GlobalNamespace())
+        if 
(loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
pCXXMethodDecl->getParent())).Class("OutputDevice").GlobalNamespace())
             return true;
     }
     // we are only currently interested in methods where the first parameter 
is RenderContext
@@ -76,7 +77,7 @@ bool RenderContext::VisitCXXMemberCallExpr(const 
CXXMemberCallExpr* pCXXMemberCa
         return true;
     }
     const CXXRecordDecl *pCXXRecordDecl = pCXXMemberCallExpr->getRecordDecl();
-    if 
(!loplugin::TypeCheck(pCXXRecordDecl).Class("OutputDevice").GlobalNamespace()) {
+    if 
(!loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
pCXXRecordDecl)).Class("OutputDevice").GlobalNamespace()) {
         return true;
     }
     // ignore a handful of methods. They will most probably still be present 
in Window for use during processing outside of the Paint()
diff --git a/compilerplugins/clang/selfinit.cxx 
b/compilerplugins/clang/selfinit.cxx
index 3891a5fc724f..d82222ef1b32 100644
--- a/compilerplugins/clang/selfinit.cxx
+++ b/compilerplugins/clang/selfinit.cxx
@@ -11,6 +11,8 @@
 
 #include <vector>
 
+#include "config_clang.h"
+
 #include "plugin.hxx"
 
 // Warn when a variable is referenced from its own initializer.  This is not 
invalid in general (see
@@ -63,8 +65,24 @@ public:
     bool TraverseCXXNoexceptExpr(CXXNoexceptExpr*) { return true; }
     bool PreTraverseCXXNoexceptExpr(CXXNoexceptExpr*) { return false; }
 
-    bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
-    bool PreTraverseDecltypeTypeLoc(DecltypeTypeLoc) { return false; }
+    bool TraverseDecltypeTypeLoc(DecltypeTypeLoc
+#if CLANG_VERSION >= 220000
+                                 ,
+                                 bool
+#endif
+    )
+    {
+        return true;
+    }
+    bool PreTraverseDecltypeTypeLoc(DecltypeTypeLoc
+#if CLANG_VERSION >= 220000
+                                    ,
+                                    bool
+#endif
+    )
+    {
+        return false;
+    }
 
     bool VisitDeclRefExpr(DeclRefExpr const* expr)
     {
diff --git a/compilerplugins/clang/sfxpoolitem.cxx 
b/compilerplugins/clang/sfxpoolitem.cxx
index 79ef64dd243e..70aec7b1e111 100644
--- a/compilerplugins/clang/sfxpoolitem.cxx
+++ b/compilerplugins/clang/sfxpoolitem.cxx
@@ -13,6 +13,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "clang/AST/CXXInheritance.h"
 
 /*
@@ -32,19 +33,24 @@ public:
     virtual void run() override { 
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
 
     bool VisitCXXRecordDecl( const CXXRecordDecl* );
+
+private:
+    bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl);
+
+    bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl);
 };
 
-bool BaseCheckNotSfxPoolItemSubclass(const CXXRecordDecl *BaseDefinition) {
-    if (BaseDefinition && 
loplugin::TypeCheck(BaseDefinition).Class("SfxPoolItem").GlobalNamespace()) {
+bool BaseCheckNotSfxPoolItemSubclass(clang::ASTContext const & context, const 
CXXRecordDecl *BaseDefinition) {
+    if (BaseDefinition && 
loplugin::TypeCheck(compat::getCanonicalTagType(context, 
BaseDefinition)).Class("SfxPoolItem").GlobalNamespace()) {
         return false;
     }
     return true;
 }
 
-bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) {
+bool SfxPoolItem::isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) {
     if (!decl)
         return false;
-    if (loplugin::TypeCheck(decl).Class("SfxPoolItem").GlobalNamespace())
+    if 
(loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
decl)).Class("SfxPoolItem").GlobalNamespace())
         return true;
     if (!decl->hasDefinition()) {
         return false;
@@ -52,24 +58,24 @@ bool isDerivedFromSfxPoolItem(const CXXRecordDecl *decl) {
     if (// not sure what hasAnyDependentBases() does,
         // but it avoids classes we don't want, e.g. 
WeakAggComponentImplHelper1
         !decl->hasAnyDependentBases() &&
-        !decl->forallBases(BaseCheckNotSfxPoolItemSubclass)) {
+        !decl->forallBases([this](const CXXRecordDecl *BaseDefinition) { 
return BaseCheckNotSfxPoolItemSubclass(compiler.getASTContext(), 
BaseDefinition); })) {
         return true;
     }
     return false;
 }
 
 
-bool BaseCheckNotSwMsgPoolItemSubclass(const CXXRecordDecl *BaseDefinition) {
-    if (BaseDefinition && 
loplugin::TypeCheck(BaseDefinition).Class("SwMsgPoolItem")) {
+bool BaseCheckNotSwMsgPoolItemSubclass(clang::ASTContext const & context, 
const CXXRecordDecl *BaseDefinition) {
+    if (BaseDefinition && 
loplugin::TypeCheck(compat::getCanonicalTagType(context, 
BaseDefinition)).Class("SwMsgPoolItem")) {
         return false;
     }
     return true;
 }
 
-bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) {
+bool SfxPoolItem::isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) {
     if (!decl)
         return false;
-    if (loplugin::TypeCheck(decl).Class("SwMsgPoolItem").GlobalNamespace())
+    if 
(loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
decl)).Class("SwMsgPoolItem").GlobalNamespace())
         return true;
     if (!decl->hasDefinition()) {
         return false;
@@ -77,7 +83,7 @@ bool isDerivedFromSwMsgPoolItem(const CXXRecordDecl *decl) {
     if (// not sure what hasAnyDependentBases() does,
         // but it avoids classes we don't want, e.g. 
WeakAggComponentImplHelper1
         !decl->hasAnyDependentBases() &&
-        !decl->forallBases(BaseCheckNotSwMsgPoolItemSubclass)) {
+        !decl->forallBases([this](const CXXRecordDecl *BaseDefinition) { 
return BaseCheckNotSwMsgPoolItemSubclass(compiler.getASTContext(), 
BaseDefinition); })) {
         return true;
     }
     return false;
@@ -108,7 +114,7 @@ bool SfxPoolItem::VisitCXXRecordDecl(const CXXRecordDecl* 
decl)
         return true;
     }
     // the enum types do some weird stuff involving SfxEnumItemInterface
-    auto tc = loplugin::TypeCheck(decl);
+    auto tc = 
loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
decl));
     if (tc.Class("SfxEnumItem").GlobalNamespace() || 
tc.Class("SfxAllEnumItem").GlobalNamespace())
         return true;
 
diff --git a/compilerplugins/clang/sharedvisitor/analyzer.cxx 
b/compilerplugins/clang/sharedvisitor/analyzer.cxx
index a23f0a16d01e..bfcc836f5298 100644
--- a/compilerplugins/clang/sharedvisitor/analyzer.cxx
+++ b/compilerplugins/clang/sharedvisitor/analyzer.cxx
@@ -36,7 +36,8 @@ using namespace loplugin;
 struct TraverseFunctionInfo
 {
     std::string name;
-    std::string argument;
+    std::string argument1;
+    std::string argument2;
     bool hasPre = false;
     bool hasPost = false;
 };
@@ -150,7 +151,17 @@ bool CheckFileVisitor::VisitCXXRecordDecl( CXXRecordDecl* 
decl )
             if( method->getNumParams() == 1 )
             {
                 TraverseFunctionInfo traverseInfo = 
findOrCreateTraverseFunctionInfo( method->getName());
-                traverseInfo.argument = method->getParamDecl( 0 
)->getTypeSourceInfo()->getType().getAsString();
+                traverseInfo.argument1 = method->getParamDecl( 0 
)->getTypeSourceInfo()->getType().getAsString();
+                traverseFunctions.insert( std::move( traverseInfo ));
+            }
+            else if( method->getNumParams() == 2 )
+            {
+                TraverseFunctionInfo traverseInfo = 
findOrCreateTraverseFunctionInfo( method->getName());
+                traverseInfo.argument1 = method->getParamDecl( 0 
)->getTypeSourceInfo()->getType().getAsString();
+                traverseInfo.argument2 = method->getParamDecl( 1 
)->getTypeSourceInfo()->getType().getAsString();
+                if (traverseInfo.argument2 == "_Bool") {
+                    traverseInfo.argument2 = "bool";
+                }
                 traverseFunctions.insert( std::move( traverseInfo ));
             }
             else
@@ -188,7 +199,8 @@ bool CheckFileVisitor::VisitCXXRecordDecl( CXXRecordDecl* 
decl )
     {
         std::cout << "TraverseFunctionStart" << std::endl;
         std::cout << "TraverseFunctionName:" << traverseFunction.name << 
std::endl;
-        std::cout << "TraverseFunctionArgument:" << traverseFunction.argument 
<< std::endl;
+        std::cout << "TraverseFunctionArgument1:" << 
traverseFunction.argument1 << std::endl;
+        std::cout << "TraverseFunctionArgument2:" << 
traverseFunction.argument2 << std::endl;
         std::cout << "TraverseFunctionHasPre:" << traverseFunction.hasPre << 
std::endl;
         std::cout << "TraverseFunctionHasPost:" << traverseFunction.hasPost << 
std::endl;
         std::cout << "TraverseFunctionEnd" << std::endl;
diff --git a/compilerplugins/clang/sharedvisitor/generator.cxx 
b/compilerplugins/clang/sharedvisitor/generator.cxx
index ca5d2743cb69..47a802d31b4a 100644
--- a/compilerplugins/clang/sharedvisitor/generator.cxx
+++ b/compilerplugins/clang/sharedvisitor/generator.cxx
@@ -29,7 +29,8 @@ struct VisitFunctionInfo
 struct TraverseFunctionInfo
 {
     std::string name;
-    std::string argument;
+    std::string argument1;
+    std::string argument2;
     bool hasPre = false;
     bool hasPost = false;
 };
@@ -251,7 +252,11 @@ void generateVisitor( PluginType type )
             traverseFunctions.insert( traverse );
     for( const TraverseFunctionInfo& traverse : traverseFunctions )
     {
-        output << "    bool " << traverse.name << "(" << traverse.argument << 
" arg)
";
+        output << "    bool " << traverse.name << "(" << traverse.argument1 << 
" arg1";
+        if (!traverse.argument2.empty()) {
+            output << ", " << traverse.argument2 << " arg2";
+        }
+        output << ")
";
         output << "    {
";
         for( const PluginInfo& plugin : plugins[ type ] )
         {
@@ -264,7 +269,11 @@ void generateVisitor( PluginType type )
                 output << "        if( " << plugin.variableName << " != 
nullptr ";
                 output << ")
";
                 output << "        {
";
-                output << "            if( !" << plugin.variableName << 
"->Pre" << traverse.name << "( arg ))
";
+                output << "            if( !" << plugin.variableName << 
"->Pre" << traverse.name << "( arg1";
+                if (!traverse.argument2.empty()) {
+                    output << ", arg2";
+                }
+                output << " ))
";
                 // This will disable the plugin for the time of the traverse, 
until restored later,
                 // just like directly returning from Traverse* would skip that 
part.
                 output << "            {
";
@@ -274,7 +283,11 @@ void generateVisitor( PluginType type )
                 output << "        }
";
             }
         }
-        output << "        bool ret = RecursiveASTVisitor::" << traverse.name 
<< "( arg );
";
+        output << "        bool ret = RecursiveASTVisitor::" << traverse.name 
<< "( arg1";
+        if (!traverse.argument2.empty()) {
+            output << ", arg2";
+        }
+        output << " );
";
         for( const PluginInfo& plugin : plugins[ type ] )
         {
             auto pluginTraverse = plugin.traverseFunctions.find( traverse );
@@ -285,7 +298,11 @@ void generateVisitor( PluginType type )
                 output << "        if( " << plugin.variableName << " != 
nullptr ";
                 output << ")
";
                 output << "        {
";
-                output << "            if( !" << plugin.variableName << 
"->Post" << traverse.name << "( arg, ret ))
";
+                output << "            if( !" << plugin.variableName << 
"->Post" << traverse.name << "( arg1,";
+                if (!traverse.argument2.empty()) {
+                    output << " arg2,";
+                }
+                output << " ret ))
";
                 // This will disable the plugin for the rest of the run.
                 output << "                save" << plugin.className << " = 
nullptr;
";
                 output << "        }
";
@@ -301,7 +318,11 @@ void generateVisitor( PluginType type )
             auto pluginTraverse = plugin.traverseFunctions.find( traverse );
             if( pluginTraverse == plugin.traverseFunctions.end())
                 continue;
-            output << "            " << plugin.variableName << "->" << 
pluginTraverse->name << "( arg );
";
+            output << "            " << plugin.variableName << "->" << 
pluginTraverse->name << "( arg1";
+            if (!traverse.argument2.empty()) {
+                output << ", arg2";
+            }
+            output << " );
";
         }
         output << "        }
";
         output << "        return ret;
";
@@ -412,7 +433,9 @@ static bool readFile( const std::string& fileName )
             getline( file, line );
             traverseInfo.name = getValue( line, "TraverseFunctionName" );
             getline( file, line );
-            traverseInfo.argument = getValue( line, "TraverseFunctionArgument" 
);
+            traverseInfo.argument1 = getValue( line, 
"TraverseFunctionArgument1" );
+            getline( file, line );
+            traverseInfo.argument2 = getValue( line, 
"TraverseFunctionArgument2" );
             getline( file, line );
             traverseInfo.hasPre = getValue( line, "TraverseFunctionHasPre" ) 
== "1";
             getline( file, line );
diff --git a/compilerplugins/clang/staticmethods.cxx 
b/compilerplugins/clang/staticmethods.cxx
index 214c26cdd449..7769d47e6493 100644
--- a/compilerplugins/clang/staticmethods.cxx
+++ b/compilerplugins/clang/staticmethods.cxx
@@ -12,6 +12,7 @@
 #include "config_clang.h"
 
 #include "check.hxx"
+#include "compat.hxx"
 #include "plugin.hxx"
 
 /*
@@ -38,23 +39,25 @@ public:
     bool VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *) 
{ bVisitedThis = true; return true; }
     bool VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *) { 
bVisitedThis = true; return true; }
 private:
+    bool isDerivedFromTestFixture(const CXXRecordDecl *decl);
+
     StringRef getFilename(SourceLocation loc);
 };
 
-bool BaseCheckNotTestFixtureSubclass(const CXXRecordDecl *BaseDefinition) {
-    if 
(loplugin::TypeCheck(BaseDefinition).Class("TestFixture").Namespace("CppUnit").GlobalNamespace())
 {
+bool BaseCheckNotTestFixtureSubclass(clang::ASTContext const & context, const 
CXXRecordDecl *BaseDefinition) {
+    if (loplugin::TypeCheck(compat::getCanonicalTagType(context, 
BaseDefinition)).Class("TestFixture").Namespace("CppUnit").GlobalNamespace()) {
         return false;
     }
     return true;
 }
 
-bool isDerivedFromTestFixture(const CXXRecordDecl *decl) {
+bool StaticMethods::isDerivedFromTestFixture(const CXXRecordDecl *decl) {
     if (!decl->hasDefinition())
         return false;
     if (// not sure what hasAnyDependentBases() does,
         // but it avoids classes we don't want, e.g. 
WeakAggComponentImplHelper1
         !decl->hasAnyDependentBases() &&
-        !decl->forallBases(BaseCheckNotTestFixtureSubclass)) {
+        !decl->forallBases([this](const CXXRecordDecl *BaseDefinition) { 
return BaseCheckNotTestFixtureSubclass(compiler.getASTContext(), 
BaseDefinition); })) {
         return true;
     }
     return false;
diff --git a/compilerplugins/clang/stringadd.cxx 
b/compilerplugins/clang/stringadd.cxx
index 0ac4ee6d3c65..60e61f04a8bb 100644
--- a/compilerplugins/clang/stringadd.cxx
+++ b/compilerplugins/clang/stringadd.cxx
@@ -416,7 +416,8 @@ bool StringAdd::isSideEffectFree(Expr const* expr)
                     && (name == "number" || name == "unacquired" || name == 
"boolean"
                         || name == "copy"))
                 {
-                    auto tc = 
loplugin::TypeCheck(calleeMethodDecl->getParent());
+                    auto tc = loplugin::TypeCheck(compat::getCanonicalTagType(
+                        compiler.getASTContext(), 
calleeMethodDecl->getParent()));
                     if (tc.Class("OUString") || tc.Class("OString"))
                     {
                         if (isSideEffectFree(callExpr->getArg(0)))
@@ -430,7 +431,8 @@ bool StringAdd::isSideEffectFree(Expr const* expr)
                         .ClassOrStruct("basic_string_view")
                         .StdNamespace())
                 {
-                    auto const tc = 
loplugin::TypeCheck(calleeMethodDecl->getParent());
+                    auto const tc = 
loplugin::TypeCheck(compat::getCanonicalTagType(
+                        compiler.getASTContext(), 
calleeMethodDecl->getParent()));
                     if (tc.Class("OUString").Namespace("rtl").GlobalNamespace()
                         || 
tc.Class("OString").Namespace("rtl").GlobalNamespace())
                     {
diff --git a/compilerplugins/clang/test/getstr.cxx 
b/compilerplugins/clang/test/getstr.cxx
index c10939202a9c..78cfa7ae176b 100644
--- a/compilerplugins/clang/test/getstr.cxx
+++ b/compilerplugins/clang/test/getstr.cxx
@@ -45,7 +45,7 @@ void f(std::ostream& st, OString const& s1, OStringBuffer 
const& s2,
        << s3.getStr() // expected-error-re {{suspicious use of 'getStr' on an 
object of type '{{(rtl::)?}}OUString'; the result is implicitly cast to a void 
pointer in a call of 'operator <<' [loplugin:getstr]}}
        << s4.getStr() // expected-error-re {{suspicious use of 'getStr' on an 
object of type '{{(rtl::)?}}OUStringBuffer'; the result is implicitly cast to a 
void pointer in a call of 'operator <<' [loplugin:getstr]}}
 #endif
-       << s5.getStr() // expected-error {{directly use object of type 'S' (aka 
'rtl::OString') in a call of 'operator <<', instead of calling 'getStr' first 
[loplugin:getstr]}}
+       << s5.getStr() // expected-error-re {{directly use object of type 'S' 
(aka '{{(::)?}}rtl::OString') in a call of 'operator <<', instead of calling 
'getStr' first [loplugin:getstr]}}
        << p1->getStr() // expected-error {{directly use object of type 
'rtl::OString' in a call of 'operator <<', instead of calling 'getStr' first 
[loplugin:getstr]}}
        << p2->getStr()
 #if !HAVE_DELETED_OPERATORS
diff --git a/compilerplugins/clang/test/indentation.cxx 
b/compilerplugins/clang/test/indentation.cxx
index 1c57c6ceea98..cac16d768a47 100644
--- a/compilerplugins/clang/test/indentation.cxx
+++ b/compilerplugins/clang/test/indentation.cxx
@@ -7,6 +7,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
+#include <sal/config.h>
+
+#include <config_clang.h>
+
+// See <https://github.com/llvm/llvm-project/issues/153540> "Clang getBeginLoc 
of some
+// CXXConstructExpr has moved past namespace prefix":
+#if CLANG_VERSION == 220000
+// expected-no-diagnostics
+#else
+
 int foo();
 int foo2(int);
 
@@ -106,5 +116,6 @@ void test5(bool x)
     }
 }
 
+#endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s 
cinkeys+=0=break: */
diff --git a/compilerplugins/clang/test/passstuffbyref.cxx 
b/compilerplugins/clang/test/passstuffbyref.cxx
index 08d91aeb1521..d3ecb81914de 100644
--- a/compilerplugins/clang/test/passstuffbyref.cxx
+++ b/compilerplugins/clang/test/passstuffbyref.cxx
@@ -31,21 +31,21 @@ struct S2 {
     S2(OUString v1, OUString v2)
       : mv1(std::move(v1)), mv2((std::move(v2))) {}
 
-    OUString get1() { return mv1; } // expected-error {{rather return class 
rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
-    OUString get2(bool b) { return b ? mv1 : mv2; } // expected-error {{rather 
return class rtl::OUString by const& than by value, to avoid unnecessary 
copying [loplugin:passstuffbyref]}}
-    OUString get3() { return child.mv1; } // expected-error {{rather return 
class rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
-    OUString get4() { return mv3[0]; } // expected-error {{rather return class 
rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
-    OUString get5() { return gs1; } // expected-error {{rather return class 
rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
+    OUString get1() { return mv1; } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
+    OUString get2(bool b) { return b ? mv1 : mv2; } // expected-error-re 
{{rather return {{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to 
avoid unnecessary copying [loplugin:passstuffbyref]}}
+    OUString get3() { return child.mv1; } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
+    OUString get4() { return mv3[0]; } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
+    OUString get5() { return gs1; } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
     OUString const & get6() { return gs1; }
-    OUString get7() { return get6(); } // expected-error {{rather return class 
rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
+    OUString get7() { return get6(); } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
     OUString & get8() { return gs1; }
-    OUString get9() { return get8(); } // expected-error {{rather return class 
rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
+    OUString get9() { return get8(); } // expected-error-re {{rather return 
{{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
     // TODO
     OUString get10() { return OUString(*&get6()); } // todoexpected-error 
{{rather return class rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
-    OUString get11() const { return mxCow->get(); } // expected-error {{rather 
return class rtl::OUString by const& than by value, to avoid unnecessary 
copying [loplugin:passstuffbyref]}}
-    OUString get12() { return child.get2(false); } // expected-error {{rather 
return class rtl::OUString by const& than by value, to avoid unnecessary 
copying [loplugin:passstuffbyref]}}
+    OUString get11() const { return mxCow->get(); } // expected-error-re 
{{rather return {{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to 
avoid unnecessary copying [loplugin:passstuffbyref]}}
+    OUString get12() { return child.get2(false); } // expected-error-re 
{{rather return {{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to 
avoid unnecessary copying [loplugin:passstuffbyref]}}
 
-    OUString get13() { return OUString(); } // expected-error {{rather return 
class rtl::OUString by const& than by value, to avoid unnecessary copying 
[loplugin:passstuffbyref]}}
+    OUString get13() { return OUString(); } // expected-error-re {{rather 
return {{(class )?}}{{(::)?}}rtl::OUString by const& than by value, to avoid 
unnecessary copying [loplugin:passstuffbyref]}}
 
     // no warning expected
     OUString set1() { return OUString("xxx"); }
diff --git a/compilerplugins/clang/test/redundantfcast.cxx 
b/compilerplugins/clang/test/redundantfcast.cxx
index 1d13d8bea238..190918adde9b 100644
--- a/compilerplugins/clang/test/redundantfcast.cxx
+++ b/compilerplugins/clang/test/redundantfcast.cxx
@@ -48,10 +48,10 @@ int main()
         s); // expected-error-re@-1 {{redundant functional cast from 
'{{(rtl::)?}}OUString' to '{{(rtl::)?}}OUString' [loplugin:redundantfcast]}}
     using T1 = OUString;
     (void)T1(
-        s); // expected-error-re@-1 {{redundant functional cast from 
'{{(rtl::)?}}OUString' to 'T1' (aka '{{(rtl::)?}}OUString') 
[loplugin:redundantfcast]}}
+        s); // expected-error-re@-1 {{redundant functional cast from 
'{{(rtl::)?}}OUString' to 'T1' (aka '{{((::)?rtl::)?}}OUString') 
[loplugin:redundantfcast]}}
     using T2 = OUString const;
     (void)T2(
-        s); // expected-error-re@-1 {{redundant functional cast from 
'{{(rtl::)?}}OUString' to 'T2' (aka 'const {{(rtl::?)}}OUString') 
[loplugin:redundantfcast]}}
+        s); // expected-error-re@-1 {{redundant functional cast from 
'{{(rtl::)?}}OUString' to 'T2' (aka 'const {{((::)?rtl::?)}}OUString') 
[loplugin:redundantfcast]}}
 
     (void)std::unique_ptr<int>(std::unique_ptr<int>(
         new int{})); // expected-error@-1 {{redundant functional cast from 
'std::unique_ptr<int>' to 'std::unique_ptr<int>' [loplugin:redundantfcast]}}
diff --git a/compilerplugins/clang/test/refcounting.cxx 
b/compilerplugins/clang/test/refcounting.cxx
index 54d4dbe14b38..fc2e5fa2d8e8 100644
--- a/compilerplugins/clang/test/refcounting.cxx
+++ b/compilerplugins/clang/test/refcounting.cxx
@@ -13,6 +13,7 @@
 #include <rtl/ref.hxx>
 #include <boost/intrusive_ptr.hpp>
 #include <com/sun/star/uno/XInterface.hpp>
+#include <config_clang.h>
 #include <cppuhelper/weak.hxx>
 #include <unotools/weakref.hxx>
 
@@ -29,23 +30,33 @@ struct UnoSubObject : public UnoObject
 
 struct Foo
 {
-    // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
+#if CLANG_VERSION < 220000
+// expected-error@+3 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
+#endif
     // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
     std::unique_ptr<UnoObject> m_foo1;
-    // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
+#if CLANG_VERSION < 220000
+    // expected-error@+3 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
+#endif
     // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
     std::shared_ptr<UnoObject> m_foo2;
-    // expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
+#if CLANG_VERSION < 220000
+    // expected-error@+3 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
+#endif
     // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being 
managed via smart pointer, should be managed via rtl::Reference 
[loplugin:refcounting]}}
     boost::intrusive_ptr<UnoObject> m_foo3;
     rtl::Reference<UnoObject> m_foo4; // no warning expected
 };
 
-// expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
+#if CLANG_VERSION < 220000
+// expected-error@+3 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
+#endif
 // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
 std::unique_ptr<UnoObject> foo1();
 rtl::Reference<UnoObject> foo2(); // no warning expected
-// expected-error@+2 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
+#if CLANG_VERSION < 220000
+// expected-error@+3 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
+#endif
 // expected-error@+1 {{cppu::OWeakObject subclass 'UnoObject' being managed 
via smart pointer, should be managed via rtl::Reference [loplugin:refcounting]}}
 void foo3(std::unique_ptr<UnoObject> p);
 
diff --git a/compilerplugins/clang/trivialconstructor.cxx 
b/compilerplugins/clang/trivialconstructor.cxx
index c991d71ae703..af9b26053e61 100644
--- a/compilerplugins/clang/trivialconstructor.cxx
+++ b/compilerplugins/clang/trivialconstructor.cxx
@@ -15,6 +15,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "config_clang.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/StmtVisitor.h"
@@ -141,7 +142,7 @@ bool 
TrivialConstructor::FieldHasTrivialConstructorBody(const FieldDecl* Field)
     if (!RT)
         return true;
 
-    CXXRecordDecl* FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    CXXRecordDecl const* FieldClassDecl = 
cast<CXXRecordDecl>(compat::getDecl(RT));
 
     // The constructor for an implicit anonymous union member is never invoked.
     if (FieldClassDecl->isUnion() && 
FieldClassDecl->isAnonymousStructOrUnion())
diff --git a/compilerplugins/clang/trivialdestructor.cxx 
b/compilerplugins/clang/trivialdestructor.cxx
index 5db1bbab705f..fa4d0bad9ac9 100644
--- a/compilerplugins/clang/trivialdestructor.cxx
+++ b/compilerplugins/clang/trivialdestructor.cxx
@@ -15,6 +15,7 @@
 
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 #include "config_clang.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/StmtVisitor.h"
@@ -102,7 +103,7 @@ bool TrivialDestructor::FieldHasTrivialDestructor(const 
FieldDecl* Field)
     if (!RT)
         return true;
 
-    CXXRecordDecl* FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+    CXXRecordDecl const* FieldClassDecl = 
cast<CXXRecordDecl>(compat::getDecl(RT));
 
     return FieldClassDecl->hasTrivialDestructor();
 }
diff --git a/compilerplugins/clang/typedefparam.cxx 
b/compilerplugins/clang/typedefparam.cxx
index aa132eb1547b..7302197a14b7 100644
--- a/compilerplugins/clang/typedefparam.cxx
+++ b/compilerplugins/clang/typedefparam.cxx
@@ -184,19 +184,27 @@ static bool areTypesEqual(QualType lhs, QualType rhs)
                 auto recordType = dyn_cast<RecordType>(type);
                 if (recordType)
                     return recordType;
+#if CLANG_VERSION < 220000
                 auto elaboratedType = dyn_cast<ElaboratedType>(type);
-                if (!elaboratedType)
-                    return static_cast<const clang::RecordType*>(nullptr);
-                return dyn_cast<RecordType>(elaboratedType->desugar());
+                if (elaboratedType)
+                    return dyn_cast<RecordType>(elaboratedType->desugar());
+#endif
+                return static_cast<const clang::RecordType*>(nullptr);
             };
             auto containsTypedefToRecord = [](clang::QualType type, RecordType 
const* recordType) {
                 TypedefType const* typedefType = type->getAs<TypedefType>();
                 if (!typedefType)
                     return false;
                 auto tmp = typedefType->desugar();
+#if CLANG_VERSION < 220000
                 if (auto elaboratedType = dyn_cast<ElaboratedType>(tmp))
                     tmp = elaboratedType->desugar();
-                return tmp.getTypePtr() == recordType;
+#endif
+                if (auto const rt = dyn_cast<RecordType>(tmp))
+                {
+                    return compat::getDecl(rt) == compat::getDecl(recordType);
+                }
+                return false;
             };
             if (auto recordType = 
extractRecordType(lhsPointer->getPointeeType()))
                 if (containsTypedefToRecord(rhsPointer->getPointeeType(), 
recordType))
@@ -207,6 +215,7 @@ static bool areTypesEqual(QualType lhs, QualType rhs)
         }
     }
 
+#if CLANG_VERSION < 220000
     if (auto lhsElaborated = dyn_cast<ElaboratedType>(lhsType))
     {
         return areTypesEqual(lhsElaborated->getNamedType(), rhs);
@@ -215,6 +224,7 @@ static bool areTypesEqual(QualType lhs, QualType rhs)
     {
         return areTypesEqual(lhs, rhsElaborated->getNamedType());
     }
+#endif
     if (auto lhsTemplate = dyn_cast<TemplateSpecializationType>(lhsType))
     {
         return areTypesEqual(lhsTemplate->desugar(), rhs);
diff --git a/compilerplugins/clang/unnecessaryoverride.cxx 
b/compilerplugins/clang/unnecessaryoverride.cxx
index d3c67b492a19..2c88fde21ca3 100644
--- a/compilerplugins/clang/unnecessaryoverride.cxx
+++ b/compilerplugins/clang/unnecessaryoverride.cxx
@@ -19,6 +19,7 @@
 #include "config_clang.h"
 #include "plugin.hxx"
 #include "check.hxx"
+#include "compat.hxx"
 
 /**
 look for methods where all they do is call their superclass method
@@ -180,7 +181,7 @@ bool UnnecessaryOverride::VisitCXXMethodDecl(const 
CXXMethodDecl* methodDecl)
                 const RecordType* baseRecordType = 
baseSpecifier->getType()->getAs<RecordType>();
                 if (baseRecordType)
                 {
-                    const CXXRecordDecl* baseRecordDecl = 
dyn_cast<CXXRecordDecl>(baseRecordType->getDecl());
+                    const CXXRecordDecl* baseRecordDecl = 
dyn_cast<CXXRecordDecl>(compat::getDecl(baseRecordType));
                     if (baseRecordDecl && baseRecordDecl->getDestructor()
                         && baseRecordDecl->getDestructor()->isVirtual())
                     {
@@ -452,7 +453,7 @@ const CXXMethodDecl* 
UnnecessaryOverride::findOverriddenOrSimilarMethodInSupercl
             bool bParamsMatch = true;
             for (unsigned i=0; i<methodDecl->param_size(); ++i)
             {
-                if (methodDecl->parameters()[i]->getType() != 
baseMethod->parameters()[i]->getType())
+                if 
(!loplugin::areSameSugaredType(methodDecl->parameters()[i]->getType(), 
baseMethod->parameters()[i]->getType()))
                 {
                     bParamsMatch = false;
                     break;
diff --git a/compilerplugins/clang/unusedfields.cxx 
b/compilerplugins/clang/unusedfields.cxx
index 35381632755a..76e41a8db5c9 100644
--- a/compilerplugins/clang/unusedfields.cxx
+++ b/compilerplugins/clang/unusedfields.cxx
@@ -1007,7 +1007,7 @@ void UnusedFields::checkIfWrittenTo(const FieldDecl* 
fieldDecl, const Expr* memb
 // return true if this not a collection type, or if it is a collection type, 
and we might be writing to it
 bool UnusedFields::checkForWriteWhenUsingCollectionType(const CXXMethodDecl * 
calleeMethodDecl)
 {
-    auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent());
+    auto const tc = 
loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
calleeMethodDecl->getParent()));
     bool listLike = false, setLike = false, mapLike = false, cssSequence = 
false;
     // Noting that I am deliberately not calling StdNamespace() on these 
checks, the loplugin::TypeCheck
     // code seems to be unreliable when dealing with 
ClassTemplateSpecializationDecl.
@@ -1071,7 +1071,7 @@ bool 
UnusedFields::checkForWriteWhenUsingCollectionType(const CXXMethodDecl * ca
 
 bool UnusedFields::checkForUsingMap(const CXXMethodDecl * calleeMethodDecl)
 {
-    auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent());
+    auto const tc = 
loplugin::TypeCheck(compat::getCanonicalTagType(compiler.getASTContext(), 
calleeMethodDecl->getParent()));
     if (!(tc.Class("map") || tc.Class("unordered_map")))
         return false;
     if (!calleeMethodDecl->isOverloadedOperator())
@@ -1148,7 +1148,7 @@ bool UnusedFields::VisitInitListExpr( const InitListExpr* 
initListExpr)
     if (!recordType)
         return true;
 
-    auto recordDecl = recordType->getDecl();
+    auto recordDecl = compat::getDecl(recordType);
     for (auto it = recordDecl->field_begin(); it != recordDecl->field_end(); 
++it)
     {
         MyFieldInfo fieldInfo = niceName(*it);
diff --git a/compilerplugins/clang/unusedmember.cxx 
b/compilerplugins/clang/unusedmember.cxx
index 610c94e162b3..c2c0dd838758 100644
--- a/compilerplugins/clang/unusedmember.cxx
+++ b/compilerplugins/clang/unusedmember.cxx
@@ -18,6 +18,8 @@
 #include <cassert>
 #include <set>
 
+#include "config_clang.h"
+
 #include "check.hxx"
 #include "compat.hxx"
 #include "plugin.hxx"
@@ -38,18 +40,6 @@ bool isTemplated(CXXRecordDecl const* decl)
     return false;
 }
 
-bool isWarnUnusedType(QualType type)
-{
-    if (auto const t = type->getAs<RecordType>())
-    {
-        if (t->getDecl()->hasAttr<WarnUnusedAttr>())
-        {
-            return true;
-        }
-    }
-    return loplugin::isExtraWarnUnusedType(type);
-}
-
 class UnusedMember final : public loplugin::FilteringPlugin<UnusedMember>
 {
 public:
@@ -68,7 +58,7 @@ public:
         // declaration of e clearly references it:
         if (auto const t = decl->getType()->getAs<EnumType>())
         {
-            deferred_.erase(t->getDecl());
+            deferred_.erase(compat::getDecl(t));
         }
         return true;
     }
@@ -229,11 +219,11 @@ public:
         RecordDecl const* d;
         if (auto const t2 = t1->getAs<InjectedClassNameType>())
         {
-            d = t2->getDecl();
+            d = compat::getDecl(t2);
         }
         else
         {
-            d = t1->castAs<RecordType>()->getDecl();
+            d = compat::getDecl(t1->castAs<RecordType>());
         }
         recordRecordDeclAndBases(d);
         return true;
@@ -269,7 +259,7 @@ public:
         }
         if (auto const t1 = t->getAs<RecordType>())
         {
-            recordRecordDeclAndBases(t1->getDecl());
+            recordRecordDeclAndBases(compat::getDecl(t1));
         }
         return true;
     }
@@ -306,6 +296,7 @@ public:
         return true;
     }
 
+#if CLANG_VERSION < 220000
     bool VisitElaboratedTypeLoc(ElaboratedTypeLoc tloc)
     {
         if (ignoreLocation(tloc))
@@ -337,6 +328,7 @@ public:
         }
         return true;
     }
+#endif
 
     void postRun() override
     {
@@ -389,6 +381,18 @@ private:
         }
     }
 
+    bool isWarnUnusedType(QualType type)
+    {
+        if (auto const t = type->getAs<RecordType>())
+        {
+            if 
(compat::getDefinitionOrSelf(compat::getDecl(t))->hasAttr<WarnUnusedAttr>())
+            {
+                return true;
+            }
+        }
+        return loplugin::isExtraWarnUnusedType(compiler.getASTContext(), type);
+    }
+
     bool isWarnWhenUnusedType(QualType type)
     {
         auto t = type;
@@ -409,7 +413,7 @@ private:
         {
             for (auto i = d2->bases_begin(); i != d2->bases_end(); ++i)
             {
-                
recordRecordDeclAndBases(i->getType()->castAs<RecordType>()->getDecl());
+                
recordRecordDeclAndBases(compat::getDecl(i->getType()->castAs<RecordType>()));
             }
             //TODO: doesn't iterate vbases, but presence of such would run 
counter to the layout
             // heuristic anyway
@@ -427,7 +431,7 @@ private:
             }
             if (auto const t1 = t->getAs<RecordType>())
             {
-                recordRecordDeclAndBases(t1->getDecl());
+                recordRecordDeclAndBases(compat::getDecl(t1));
             }
             break;
         }
diff --git a/compilerplugins/clang/unusedvariablecheck.cxx 
b/compilerplugins/clang/unusedvariablecheck.cxx
index f155219942b6..9ff433d65a1a 100644
--- a/compilerplugins/clang/unusedvariablecheck.cxx
+++ b/compilerplugins/clang/unusedvariablecheck.cxx
@@ -56,7 +56,7 @@ bool UnusedVariableCheck::VisitVarDecl( const VarDecl* var )
         return true;
 
     auto type = var->getType();
-    bool check = loplugin::isExtraWarnUnusedType(type);
+    bool check = loplugin::isExtraWarnUnusedType(compiler.getASTContext(), 
type);
 
     if (!check)
         check = isUnusedSmartPointer(var);
diff --git a/compilerplugins/clang/unusedvariablemore.cxx 
b/compilerplugins/clang/unusedvariablemore.cxx
index 908edf33a465..b60f2e1400a2 100644
--- a/compilerplugins/clang/unusedvariablemore.cxx
+++ b/compilerplugins/clang/unusedvariablemore.cxx
@@ -46,6 +46,8 @@ public:
     bool VisitFunctionDecl(FunctionDecl const*);
 
 private:
+    bool isWarnUnusedType(QualType type);
+
     bool checkifUnused(Stmt const*, VarDecl const*);
     bool isOkForParameter(const QualType&);
 
@@ -120,7 +122,7 @@ void UnusedVariableMore::run()
     }
 }
 
-bool isWarnUnusedType(QualType type)
+bool UnusedVariableMore::isWarnUnusedType(QualType type)
 {
     if (auto const t = type->getAs<TypedefType>())
     {
@@ -131,12 +133,12 @@ bool isWarnUnusedType(QualType type)
     }
     if (auto const t = type->getAs<RecordType>())
     {
-        if (t->getDecl()->hasAttr<WarnUnusedAttr>())
+        if 
(compat::getDefinitionOrSelf(compat::getDecl(t))->hasAttr<WarnUnusedAttr>())
         {
             return true;
         }
     }
-    return loplugin::isExtraWarnUnusedType(type);
+    return loplugin::isExtraWarnUnusedType(compiler.getASTContext(), type);
 }
 
 bool UnusedVariableMore::VisitVarDecl(VarDecl const* var)
diff --git a/compilerplugins/clang/unusedvarsglobal.cxx 
b/compilerplugins/clang/unusedvarsglobal.cxx
index f74bfedb6c0d..5b97cf8dcb11 100644
--- a/compilerplugins/clang/unusedvarsglobal.cxx
+++ b/compilerplugins/clang/unusedvarsglobal.cxx
@@ -847,7 +847,8 @@ void UnusedVarsGlobal::checkIfWrittenTo(const VarDecl* 
varDecl, const DeclRefExp
 // return true if this not a collection type, or if it is a collection type, 
and we might be writing to it
 bool UnusedVarsGlobal::checkForWriteWhenUsingCollectionType(const 
CXXMethodDecl* calleeMethodDecl)
 {
-    auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent());
+    auto const tc = loplugin::TypeCheck(
+        compat::getCanonicalTagType(compiler.getASTContext(), 
calleeMethodDecl->getParent()));
     bool listLike = false, setLike = false, mapLike = false, cssSequence = 
false;
     if (tc.Class("deque").StdNamespace() || tc.Class("list").StdNamespace()
         || tc.Class("queue").StdNamespace() || 
tc.Class("vector").StdNamespace())
diff --git a/compilerplugins/clang/vclwidgets.cxx 
b/compilerplugins/clang/vclwidgets.cxx
index 0d09e0ff52c6..06194db9d8bd 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -162,7 +162,7 @@ bool VCLWidgets::VisitCXXDestructorDecl(const 
CXXDestructorDecl* pCXXDestructorD
     {
         const RecordType *pFieldRecordType = 
fieldDecl->getType()->getAs<RecordType>();
         if (pFieldRecordType) {
-            if (loplugin::DeclCheck(pFieldRecordType->getDecl())
+            if (loplugin::DeclCheck(compat::getDecl(pFieldRecordType))
                 .Class("VclPtr").GlobalNamespace())
             {
                bFoundVclPtrField = true;
@@ -458,7 +458,7 @@ bool VCLWidgets::VisitFieldDecl(const FieldDecl * 
fieldDecl) {
     if (recordType == nullptr) {
         return true;
     }
-    const CXXRecordDecl *recordDecl = 
dyn_cast<CXXRecordDecl>(recordType->getDecl());
+    const CXXRecordDecl *recordDecl = 
dyn_cast<CXXRecordDecl>(compat::getDecl(recordType));
     if (recordDecl == nullptr) {
         return true;
     }
@@ -638,7 +638,7 @@ bool VCLWidgets::VisitFunctionDecl( const FunctionDecl* 
functionDecl )
             {
                 const RecordType* recordType = 
dyn_cast_or_null<RecordType>((*i)->getType()->getUnqualifiedDesugaredType());
                 if (recordType) {
-                    auto d = 
dyn_cast<ClassTemplateSpecializationDecl>(recordType->getDecl());
+                    auto d = 
dyn_cast<ClassTemplateSpecializationDecl>(compat::getDecl(recordType));
                     if (d && d->getTemplateArgs().size()>0) {
                         auto const type = 
loplugin::TypeCheck(d->getTemplateArgs()[0].getAsType());
                         if (type.Class("VclPtr").GlobalNamespace()) {
diff --git a/compilerplugins/clang/writeonlyvars.cxx 
b/compilerplugins/clang/writeonlyvars.cxx
index 3fb3f769b72d..efb5d1be1f6e 100644
--- a/compilerplugins/clang/writeonlyvars.cxx
+++ b/compilerplugins/clang/writeonlyvars.cxx
@@ -1002,7 +1002,8 @@ void WriteOnlyVars::checkIfWrittenTo(const VarDecl* 
varDecl, const Expr* memberE
 // return true if this not a collection type, or if it is a collection type, 
and we might be writing to it
 bool WriteOnlyVars::checkForWriteWhenUsingCollectionType(const CXXMethodDecl* 
calleeMethodDecl)
 {
-    auto const tc = loplugin::TypeCheck(calleeMethodDecl->getParent());
+    auto const tc = loplugin::TypeCheck(
+        compat::getCanonicalTagType(compiler.getASTContext(), 
calleeMethodDecl->getParent()));
     bool listLike = false, setLike = false, mapLike = false, cssSequence = 
false;
     if (tc.Class("deque").StdNamespace() || tc.Class("list").StdNamespace()
         || tc.Class("queue").StdNamespace() || 
tc.Class("vector").StdNamespace())
diff --git a/compilerplugins/clang/xmlimport.cxx 
b/compilerplugins/clang/xmlimport.cxx
index 1e883b60a918..0dc18346c2ed 100644
--- a/compilerplugins/clang/xmlimport.cxx
+++ b/compilerplugins/clang/xmlimport.cxx
@@ -362,7 +362,7 @@ bool XmlImport::isXmlTokEnum(const Expr* expr)
     expr = expr->IgnoreImplicit();
     // check that we have an unscoped enum type
     auto condEnumType = 
expr->getType()->getUnqualifiedDesugaredType()->getAs<EnumType>();
-    if (!condEnumType || condEnumType->getDecl()->isScoped())
+    if (!condEnumType || compat::getDecl(condEnumType)->isScoped())
         return false;
     auto declRefExpr = dyn_cast<DeclRefExpr>(expr);
     if (!declRefExpr)
commit 1b4afb164417b3fb906eff94cf0199227e0106e6
Author:     Stephan Bergmann <stephan.bergm...@collabora.com>
AuthorDate: Fri Aug 15 22:50:59 2025 +0200
Commit:     Stephan Bergmann <stephan.bergm...@collabora.com>
CommitDate: Sun Aug 17 19:42:43 2025 +0200

    external/skia: Adapt to recent LLVM 22 trunk change
    
    
...<https://github.com/llvm/llvm-project/commit/f8653cecd11ede482a175a5c4d6fa147812562dd>
    "[Clang][X86] Replace F16C `vcvtph2ps/256` intrinsics with
    `(convert|shuffle)vector` builtins (#152911)"; see
    <https://issues.skia.org/u/1/issues/438918298> "__builtin_ia32_vcvtph2ps256 
gone
    from Clang 22 trunk" and
    
<https://skia.googlesource.com/skcms/+/135488419331644e59091ecc73e682299d3937a4>
    "Change use of removed intrinsic", which needed to be slightly modified with
    s/_Float16/__fp16/ to avoid "error: _Float16 is not supported on this 
target"
    with Clang 12.0.1 on Linux
    (<https://ci.libreoffice.org/job/gerrit_linux_clang_dbgutil/188331/>), but 
which
    would then cause "error: ‘__fp16’ does not name a type" with GCC 12.2.1 on 
Linux
    (<https://ci.libreoffice.org/job/gerrit_linux_gcc_release/194504/>)
    
    Change-Id: I4e848b9caf2cda14e416711624db42450da60e82
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189730
    Reviewed-by: Stephan Bergmann <stephan.bergm...@collabora.com>
    Tested-by: Jenkins

diff --git a/external/skia/UnpackedTarball_skia.mk 
b/external/skia/UnpackedTarball_skia.mk
index cf2cd6c99b8d..1c915a86a53f 100644
--- a/external/skia/UnpackedTarball_skia.mk
+++ b/external/skia/UnpackedTarball_skia.mk
@@ -42,6 +42,7 @@ skia_patches := \
        0002-loong64-Honor-existing-LASX-LSX-settings.patch \
        0003-loong64-Fix-missing-rounding-in-loong64-scaled_mult-.patch \
        0004-loong64-Fix-the-remaining-implicit-vector-casts.patch \
+    modified-skcms-0001-Change-use-of-removed-intrinsic.patch \
 
 ifneq ($(MSYSTEM),)
 # use binary flag so patch from git-bash won't choke on mixed line-endings in 
patches
diff --git 
a/external/skia/modified-skcms-0001-Change-use-of-removed-intrinsic.patch 
b/external/skia/modified-skcms-0001-Change-use-of-removed-intrinsic.patch
new file mode 100644
index 000000000000..d7af3211d536
--- /dev/null
+++ b/external/skia/modified-skcms-0001-Change-use-of-removed-intrinsic.patch
@@ -0,0 +1,42 @@
+From 135488419331644e59091ecc73e682299d3937a4 Mon Sep 17 00:00:00 2001
+From: Devon Loehr <dlo...@google.com>
+Date: Fri, 15 Aug 2025 14:31:27 +0000
+Subject: Change use of removed intrinsic
+
+A recent LLVM change removed the __builtin_ia32_vcvtph2ps256 intrinsic
+because it can be implemented using __builtin_shufflevector and/or
+__builtin_convertvector. This CL changes skia to use convertvector as
+to match.
+
+Bug: chromium:438445382
+Change-Id: I2ed16cd507d7feeafba4c082b3840cbdd6368dd9
+Reviewed-on: https://skia-review.googlesource.com/c/skcms/+/1038217
+Reviewed-by: Ben Wagner <bunge...@google.com>
+Commit-Queue: Ben Wagner <bunge...@google.com>
+Auto-Submit: Devon Loehr <dlo...@google.com>
+---
+ src/Transform_inl.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/Transform_inl.h b/src/Transform_inl.h
+index bc10e7d..99faf25 100644
+--- a/modules/skcms/src/Transform_inl.h
++++ b/modules/skcms/src/Transform_inl.h
+@@ -156,8 +156,12 @@ SI F F_from_Half(U16 half) {
+ #elif defined(USING_AVX512F)
+     return (F)_mm512_cvtph_ps((__m256i)half);
+ #elif defined(USING_AVX_F16C)
+-    typedef int16_t __attribute__((vector_size(16))) I16;
+-    return __builtin_ia32_vcvtph2ps256((I16)half);
++#if defined __clang__
++    typedef __fp16 __attribute__((vector_size(16))) F16;
++#else
++    typedef _Float16 __attribute__((vector_size(16))) F16;
++#endif
++    return __builtin_convertvector((F16)half, F);
+ #else
+     U32 wide = cast<U32>(half);
+     // A half is 1-5-10 sign-exponent-mantissa, with 15 exponent bias.
+-- 
+2.50.1
+

Reply via email to