More Clang 3.4 "(anonymous namespace)" fixes
Change-Id: I7cb43f915565dadd611b90ee30373e472f97efb5 Reviewed-on: https://gerrit.libreoffice.org/26748 Reviewed-by: Stephan Bergmann <sbergman@redhat.com> Tested-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
@@ -7,8 +7,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "check.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@@ -7,8 +7,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
namespace loplugin {
|
||||
|
||||
@@ -72,7 +74,15 @@ TypeCheck TypeCheck::NotSubstTemplateTypeParmType() const {
|
||||
? *this : TypeCheck();
|
||||
}
|
||||
|
||||
TerminalCheck NamespaceCheck::GlobalNamespace() const {
|
||||
ContextCheck DeclCheck::Operator(clang::OverloadedOperatorKind op) const {
|
||||
assert(op != clang::OO_None);
|
||||
auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
|
||||
return ContextCheck(
|
||||
f != nullptr && f->getOverloadedOperator() == op
|
||||
? f->getDeclContext() : nullptr);
|
||||
}
|
||||
|
||||
TerminalCheck ContextCheck::GlobalNamespace() const {
|
||||
return TerminalCheck(
|
||||
context_ != nullptr
|
||||
&& ((compat::isLookupContext(*context_)
|
||||
@@ -80,14 +90,14 @@ TerminalCheck NamespaceCheck::GlobalNamespace() const {
|
||||
->isTranslationUnit()));
|
||||
}
|
||||
|
||||
TerminalCheck NamespaceCheck::StdNamespace() const {
|
||||
TerminalCheck ContextCheck::StdNamespace() const {
|
||||
return TerminalCheck(
|
||||
context_ != nullptr && compat::isStdNamespace(*context_));
|
||||
}
|
||||
|
||||
NamespaceCheck NamespaceCheck::AnonymousNamespace() const {
|
||||
ContextCheck ContextCheck::AnonymousNamespace() const {
|
||||
auto n = llvm::dyn_cast_or_null<clang::NamespaceDecl>(context_);
|
||||
return NamespaceCheck(
|
||||
return ContextCheck(
|
||||
n != nullptr && n->isAnonymousNamespace() ? n->getParent() : nullptr);
|
||||
}
|
||||
|
@@ -7,23 +7,24 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
|
||||
#define INCLUDED_COMPILERPLUGINS_CLANG_TYPECHECK_HXX
|
||||
#ifndef INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
|
||||
#define INCLUDED_COMPILERPLUGINS_CLANG_CHECK_HXX
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <clang/AST/DeclBase.h>
|
||||
#include <clang/AST/Decl.h>
|
||||
#include <clang/AST/Type.h>
|
||||
#include <clang/Basic/OperatorKinds.h>
|
||||
|
||||
namespace loplugin {
|
||||
|
||||
class NamespaceCheck;
|
||||
class ContextCheck;
|
||||
class TerminalCheck;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t N> NamespaceCheck checkRecordDecl(
|
||||
template<std::size_t N> ContextCheck checkRecordDecl(
|
||||
clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
|
||||
|
||||
}
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
|
||||
TypeCheck LvalueReference() const;
|
||||
|
||||
template<std::size_t N> inline NamespaceCheck Class(char const (& id)[N])
|
||||
template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
|
||||
const;
|
||||
|
||||
TypeCheck NotSubstTemplateTypeParmType() const;
|
||||
@@ -55,50 +56,65 @@ private:
|
||||
clang::QualType const type_;
|
||||
};
|
||||
|
||||
class NamespaceCheck {
|
||||
public:
|
||||
explicit operator bool() const { return context_ != nullptr; }
|
||||
|
||||
TerminalCheck GlobalNamespace() const;
|
||||
|
||||
template<std::size_t N> inline NamespaceCheck Namespace(
|
||||
char const (& id)[N]) const;
|
||||
|
||||
TerminalCheck StdNamespace() const;
|
||||
|
||||
NamespaceCheck AnonymousNamespace() const;
|
||||
|
||||
private:
|
||||
friend TypeCheck;
|
||||
template<std::size_t N> friend NamespaceCheck detail::checkRecordDecl(
|
||||
clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
|
||||
|
||||
explicit NamespaceCheck(clang::DeclContext const * context = nullptr):
|
||||
context_(context) {}
|
||||
|
||||
clang::DeclContext const * const context_;
|
||||
};
|
||||
|
||||
class DeclCheck {
|
||||
public:
|
||||
explicit DeclCheck(clang::Decl const * decl): decl_(decl) {}
|
||||
|
||||
explicit operator bool() const { return decl_ != nullptr; }
|
||||
|
||||
template<std::size_t N> inline NamespaceCheck Struct(char const (& id)[N])
|
||||
template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
|
||||
const;
|
||||
|
||||
template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
|
||||
const;
|
||||
|
||||
template<std::size_t N> inline ContextCheck Function(char const (& id)[N])
|
||||
const;
|
||||
|
||||
ContextCheck Operator(clang::OverloadedOperatorKind op) const;
|
||||
|
||||
private:
|
||||
clang::Decl const * const decl_;
|
||||
};
|
||||
|
||||
class ContextCheck {
|
||||
public:
|
||||
explicit operator bool() const { return context_ != nullptr; }
|
||||
|
||||
TerminalCheck GlobalNamespace() const;
|
||||
|
||||
template<std::size_t N> inline ContextCheck Namespace(
|
||||
char const (& id)[N]) const;
|
||||
|
||||
TerminalCheck StdNamespace() const;
|
||||
|
||||
ContextCheck AnonymousNamespace() const;
|
||||
|
||||
template<std::size_t N> inline ContextCheck Class(char const (& id)[N])
|
||||
const;
|
||||
|
||||
template<std::size_t N> inline ContextCheck Struct(char const (& id)[N])
|
||||
const;
|
||||
|
||||
private:
|
||||
friend DeclCheck;
|
||||
friend TypeCheck;
|
||||
template<std::size_t N> friend ContextCheck detail::checkRecordDecl(
|
||||
clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N]);
|
||||
|
||||
explicit ContextCheck(clang::DeclContext const * context = nullptr):
|
||||
context_(context) {}
|
||||
|
||||
clang::DeclContext const * const context_;
|
||||
};
|
||||
|
||||
class TerminalCheck {
|
||||
public:
|
||||
explicit operator bool() const { return satisfied_; }
|
||||
|
||||
private:
|
||||
friend ContextCheck;
|
||||
friend TypeCheck;
|
||||
friend NamespaceCheck;
|
||||
|
||||
explicit TerminalCheck(bool satisfied): satisfied_(satisfied) {}
|
||||
|
||||
@@ -107,22 +123,22 @@ private:
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<std::size_t N> NamespaceCheck checkRecordDecl(
|
||||
template<std::size_t N> ContextCheck checkRecordDecl(
|
||||
clang::Decl const * decl, clang::TagTypeKind tag, char const (& id)[N])
|
||||
{
|
||||
auto r = llvm::dyn_cast_or_null<clang::RecordDecl>(decl);
|
||||
if (r != nullptr && r->getTagKind() == tag) {
|
||||
auto const i = r->getIdentifier();
|
||||
if (i != nullptr && i->isStr(id)) {
|
||||
return NamespaceCheck(r->getDeclContext());
|
||||
return ContextCheck(r->getDeclContext());
|
||||
}
|
||||
}
|
||||
return NamespaceCheck();
|
||||
return ContextCheck();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
|
||||
template<std::size_t N> ContextCheck TypeCheck::Class(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
if (!type_.isNull()) {
|
||||
@@ -131,10 +147,35 @@ template<std::size_t N> NamespaceCheck TypeCheck::Class(char const (& id)[N])
|
||||
return detail::checkRecordDecl(t->getDecl(), clang::TTK_Class, id);
|
||||
}
|
||||
}
|
||||
return NamespaceCheck();
|
||||
return ContextCheck();
|
||||
}
|
||||
|
||||
template<std::size_t N> NamespaceCheck NamespaceCheck::Namespace(
|
||||
template<std::size_t N> ContextCheck DeclCheck::Class(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
return detail::checkRecordDecl(decl_, clang::TTK_Class, id);
|
||||
}
|
||||
|
||||
template<std::size_t N> ContextCheck DeclCheck::Struct(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
|
||||
}
|
||||
|
||||
template<std::size_t N> ContextCheck DeclCheck::Function(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
auto f = llvm::dyn_cast_or_null<clang::FunctionDecl>(decl_);
|
||||
if (f != nullptr) {
|
||||
auto const i = f->getIdentifier();
|
||||
if (i != nullptr && i->isStr(id)) {
|
||||
return ContextCheck(f->getDeclContext());
|
||||
}
|
||||
}
|
||||
return ContextCheck();
|
||||
}
|
||||
|
||||
template<std::size_t N> ContextCheck ContextCheck::Namespace(
|
||||
char const (& id)[N]) const
|
||||
{
|
||||
if (context_) {
|
||||
@@ -142,17 +183,25 @@ template<std::size_t N> NamespaceCheck NamespaceCheck::Namespace(
|
||||
if (n != nullptr) {
|
||||
auto const i = n->getIdentifier();
|
||||
if (i != nullptr && i->isStr(id)) {
|
||||
return NamespaceCheck(n->getParent());
|
||||
return ContextCheck(n->getParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
return NamespaceCheck();
|
||||
return ContextCheck();
|
||||
}
|
||||
|
||||
template<std::size_t N> NamespaceCheck DeclCheck::Struct(char const (& id)[N])
|
||||
template<std::size_t N> ContextCheck ContextCheck::Class(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
return detail::checkRecordDecl(decl_, clang::TTK_Struct, id);
|
||||
return detail::checkRecordDecl(
|
||||
llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Class, id);
|
||||
}
|
||||
|
||||
template<std::size_t N> ContextCheck ContextCheck::Struct(char const (& id)[N])
|
||||
const
|
||||
{
|
||||
return detail::checkRecordDecl(
|
||||
llvm::dyn_cast_or_null<clang::Decl>(context_), clang::TTK_Struct, id);
|
||||
}
|
||||
|
||||
}
|
@@ -12,8 +12,10 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include "plugin.hxx"
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "plugin.hxx"
|
||||
|
||||
/**
|
||||
comparing floating point numbers using == or != is a bad idea.
|
||||
@@ -40,25 +42,6 @@ private:
|
||||
EState meState = EState::None;
|
||||
};
|
||||
|
||||
const std::set<std::string> whitelist {
|
||||
"rtl::math::approxEqual",
|
||||
"(anonymous namespace)::doubleToString",
|
||||
"(anonymous namespace)::stringToDouble",
|
||||
"rtl_math_round",
|
||||
"rtl_math_approxValue",
|
||||
"rtl_math_asinh",
|
||||
"rtl_math_acosh",
|
||||
"cppu::_equalSequence", // cppu/source/uno/eq.hxx
|
||||
"cppu::_equalData", // cppu/source/uno/eq.hxx
|
||||
"xmlscript::equalFont", // xmlscript/source/xmldlg_imexp/xmldlg_export.cxx
|
||||
|
||||
// these might need fixing
|
||||
"basegfx::tools::getSmallestDistancePointToPolygon", // basegfx/source/polygon/b2dpolygontools.cxx
|
||||
"basegfx::tools::getSmallestDistancePointToPolyPolygon", // basegfx/source/polygon/b2dpolypolygontools.cxx
|
||||
"bridge_test::performTest", // testtools/source/bridgetest/bridgetest.cxx
|
||||
"bridge_test::equals",
|
||||
"(anonymous namespace)::lcl_getNANInsteadDBL_MIN", // chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
|
||||
};
|
||||
bool FpComparison::TraverseFunctionDecl(FunctionDecl* function)
|
||||
{
|
||||
bool bIgnore = ignore(function);
|
||||
@@ -87,8 +70,35 @@ bool FpComparison::ignore(FunctionDecl* function)
|
||||
return true;
|
||||
}
|
||||
// ignore known good functions
|
||||
std::string s = function->getQualifiedNameAsString();
|
||||
if (whitelist.find(s) != whitelist.end()) {
|
||||
loplugin::DeclCheck dc(function);
|
||||
if ((dc.Function("approxEqual").Namespace("math").Namespace("rtl")
|
||||
.GlobalNamespace())
|
||||
|| dc.Function("doubleToString").AnonymousNamespace().GlobalNamespace()
|
||||
|| dc.Function("stringToDouble").AnonymousNamespace().GlobalNamespace()
|
||||
|| dc.Function("rtl_math_round").GlobalNamespace()
|
||||
|| dc.Function("rtl_math_approxValue").GlobalNamespace()
|
||||
|| dc.Function("rtl_math_asinh").GlobalNamespace()
|
||||
|| dc.Function("rtl_math_acosh").GlobalNamespace()
|
||||
|| dc.Function("_equalSequence").Namespace("cppu").GlobalNamespace()
|
||||
// cppu/source/uno/eq.hxx
|
||||
|| dc.Function("_equalData").Namespace("cppu").GlobalNamespace()
|
||||
// cppu/source/uno/eq.hxx
|
||||
|| dc.Function("equalFont").Namespace("xmlscript").GlobalNamespace()
|
||||
// xmlscript/source/xmldlg_imexp/xmldlg_export.cxx
|
||||
// These might need fixing:
|
||||
|| (dc.Function("getSmallestDistancePointToPolygon").Namespace("tools")
|
||||
.Namespace("basegfx").GlobalNamespace())
|
||||
// basegfx/source/polygon/b2dpolygontools.cxx
|
||||
|| (dc.Function("getSmallestDistancePointToPolyPolygon")
|
||||
.Namespace("tools").Namespace("basegfx").GlobalNamespace())
|
||||
// basegfx/source/polygon/b2dpolypolygontools.cxx
|
||||
|| dc.Function("performTest").Namespace("bridge_test").GlobalNamespace()
|
||||
// testtools/source/bridgetest/bridgetest.cxx
|
||||
|| dc.Function("equals").Namespace("bridge_test").GlobalNamespace()
|
||||
|| (dc.Function("lcl_getNANInsteadDBL_MIN").AnonymousNamespace()
|
||||
.GlobalNamespace()))
|
||||
// chart2/source/controller/chartapiwrapper/ChartDataWrapper.cxx
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// cout << "xxx " + function->getQualifiedNameAsString() << endl;
|
||||
|
@@ -20,8 +20,8 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include "check.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
|
||||
namespace {
|
||||
|
@@ -15,9 +15,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
#if CLANG_VERSION < 30700
|
||||
|
||||
|
@@ -10,9 +10,9 @@
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include "plugin.hxx"
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "typecheck.hxx"
|
||||
#include "plugin.hxx"
|
||||
|
||||
// Find places where various things are passed by value.
|
||||
// It's not very efficient, because we generally end up copying it twice - once into the parameter and
|
||||
@@ -244,22 +244,31 @@ void PassStuffByRef::checkReturnValue(const FunctionDecl * functionDecl, const C
|
||||
functionDecl->getCanonicalDecl()->getNameInfo().getLoc()))) {
|
||||
return;
|
||||
}
|
||||
loplugin::DeclCheck dc(functionDecl);
|
||||
std::string aFunctionName = functionDecl->getQualifiedNameAsString();
|
||||
// function is passed as parameter to another function
|
||||
if (aFunctionName == "GDIMetaFile::ImplColMonoFnc"
|
||||
|| aFunctionName == "editeng::SvxBorderLine::darkColor"
|
||||
if (dc.Function("ImplColMonoFnc").Class("GDIMetaFile").GlobalNamespace()
|
||||
|| (dc.Function("darkColor").Class("SvxBorderLine").Namespace("editeng")
|
||||
.GlobalNamespace())
|
||||
|| aFunctionName.compare(0, 8, "xforms::") == 0)
|
||||
return;
|
||||
// not sure how to exclude this yet, returns copy of one of it's params
|
||||
if (aFunctionName == "sameDistColor" || aFunctionName == "sameColor"
|
||||
|| aFunctionName == "pcr::(anonymous namespace)::StringIdentity::operator()"
|
||||
if (dc.Function("sameDistColor").GlobalNamespace()
|
||||
|| dc.Function("sameColor").GlobalNamespace()
|
||||
|| (dc.Operator(OO_Call).Struct("StringIdentity").AnonymousNamespace()
|
||||
.Namespace("pcr").GlobalNamespace())
|
||||
|| aFunctionName == "matop::COp<type-parameter-0-0, svl::SharedString>::operator()"
|
||||
|| aFunctionName == "slideshow::internal::accumulate"
|
||||
|| aFunctionName == "slideshow::internal::lerp")
|
||||
|| (dc.Function("accumulate").Namespace("internal")
|
||||
.Namespace("slideshow").GlobalNamespace())
|
||||
|| (dc.Function("lerp").Namespace("internal").Namespace("slideshow")
|
||||
.GlobalNamespace()))
|
||||
return;
|
||||
// depends on a define
|
||||
if (aFunctionName == "SfxObjectShell::GetSharedFileURL")
|
||||
if (dc.Function("GetSharedFileURL").Class("SfxObjectShell")
|
||||
.GlobalNamespace())
|
||||
{
|
||||
return;
|
||||
}
|
||||
mbInsideFunctionDecl = true;
|
||||
mbFoundDisqualifier = false;
|
||||
TraverseStmt(functionDecl->getBody());
|
||||
|
@@ -10,9 +10,9 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "plugin.hxx"
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "typecheck.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
|
||||
/**
|
||||
@@ -110,7 +110,6 @@ bool containsXInterfaceSubclass(const QualType& qType) {
|
||||
}
|
||||
|
||||
static std::vector<std::string> PROBABLY_GOOD_TEMPLATES = {
|
||||
"(anonymous namespace)::FindUnoInstanceHint",
|
||||
"abp::OMultiInstanceAutoRegistration",
|
||||
"com::sun::star::uno::Reference",
|
||||
"com::sun::star::uno::WeakReference",
|
||||
@@ -191,6 +190,11 @@ bool containsXInterfaceSubclass(const Type* pType0) {
|
||||
if (pRecordDecl) {
|
||||
const ClassTemplateSpecializationDecl* pTemplate = dyn_cast<ClassTemplateSpecializationDecl>(pRecordDecl);
|
||||
if (pTemplate) {
|
||||
if (loplugin::DeclCheck(pTemplate).Struct("FindUnoInstanceHint")
|
||||
.AnonymousNamespace().GlobalNamespace())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::string aName = pTemplate->getQualifiedNameAsString();
|
||||
if (std::find(PROBABLY_GOOD_TEMPLATES.begin(), PROBABLY_GOOD_TEMPLATES.end(), aName) != PROBABLY_GOOD_TEMPLATES.end())
|
||||
return false;
|
||||
|
@@ -14,9 +14,9 @@
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@@ -9,9 +9,9 @@
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
/*
|
||||
Look for member functions that can be static
|
||||
|
@@ -15,9 +15,9 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "check.hxx"
|
||||
#include "compat.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
// Define a "string constant" to be a constant expression either of type "array
|
||||
// of N char" where each array element is a non-NUL ASCII character---except
|
||||
|
@@ -7,8 +7,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "check.hxx"
|
||||
#include "plugin.hxx"
|
||||
#include "typecheck.hxx"
|
||||
|
||||
/* OWeakObject::release() disposes weak references. If that isn't done
|
||||
* because a sub-class improperly overrides release() then
|
||||
|
Reference in New Issue
Block a user