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 +