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.bergmann@collabora.com> Tested-by: Jenkins
This commit is contained in:
@@ -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*>());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
auto t2 = type2.getLocalUnqualifiedType();
|
||||
if (auto const et = llvm::dyn_cast<clang::ElaboratedType>(t2)) {
|
||||
t2 = et->getNamedType();
|
||||
#if CLANG_VERSION >= 220000
|
||||
if (type1->getTypeClass() != type2->getTypeClass()) {
|
||||
return false;
|
||||
}
|
||||
return t1 == t2;
|
||||
if (auto const t = llvm::dyn_cast<clang::TagType>(type1)) {
|
||||
return t->getOriginalDecl()->getCanonicalDecl() == llvm::dyn_cast<clang::TagType>(type2)->getOriginalDecl()->getCanonicalDecl();
|
||||
}
|
||||
if (auto const t = llvm::dyn_cast<clang::TypedefType>(type1)) {
|
||||
return t->getDecl() == llvm::dyn_cast<clang::TypedefType>(type2)->getDecl();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)\n";
|
||||
output << " bool " << traverse.name << "(" << traverse.argument1 << " arg1";
|
||||
if (!traverse.argument2.empty()) {
|
||||
output << ", " << traverse.argument2 << " arg2";
|
||||
}
|
||||
output << ")\n";
|
||||
output << " {\n";
|
||||
for( const PluginInfo& plugin : plugins[ type ] )
|
||||
{
|
||||
@@ -264,7 +269,11 @@ void generateVisitor( PluginType type )
|
||||
output << " if( " << plugin.variableName << " != nullptr ";
|
||||
output << ")\n";
|
||||
output << " {\n";
|
||||
output << " if( !" << plugin.variableName << "->Pre" << traverse.name << "( arg ))\n";
|
||||
output << " if( !" << plugin.variableName << "->Pre" << traverse.name << "( arg1";
|
||||
if (!traverse.argument2.empty()) {
|
||||
output << ", arg2";
|
||||
}
|
||||
output << " ))\n";
|
||||
// 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 << " {\n";
|
||||
@@ -274,7 +283,11 @@ void generateVisitor( PluginType type )
|
||||
output << " }\n";
|
||||
}
|
||||
}
|
||||
output << " bool ret = RecursiveASTVisitor::" << traverse.name << "( arg );\n";
|
||||
output << " bool ret = RecursiveASTVisitor::" << traverse.name << "( arg1";
|
||||
if (!traverse.argument2.empty()) {
|
||||
output << ", arg2";
|
||||
}
|
||||
output << " );\n";
|
||||
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 << ")\n";
|
||||
output << " {\n";
|
||||
output << " if( !" << plugin.variableName << "->Post" << traverse.name << "( arg, ret ))\n";
|
||||
output << " if( !" << plugin.variableName << "->Post" << traverse.name << "( arg1,";
|
||||
if (!traverse.argument2.empty()) {
|
||||
output << " arg2,";
|
||||
}
|
||||
output << " ret ))\n";
|
||||
// This will disable the plugin for the rest of the run.
|
||||
output << " save" << plugin.className << " = nullptr;\n";
|
||||
output << " }\n";
|
||||
@@ -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 );\n";
|
||||
output << " " << plugin.variableName << "->" << pluginTraverse->name << "( arg1";
|
||||
if (!traverse.argument2.empty()) {
|
||||
output << ", arg2";
|
||||
}
|
||||
output << " );\n";
|
||||
}
|
||||
output << " }\n";
|
||||
output << " return ret;\n";
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: */
|
||||
|
||||
@@ -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"); }
|
||||
|
||||
@@ -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]}}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user