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:
Stephan Bergmann
2016-06-28 18:54:31 +02:00
parent 886637d355
commit 0d3738a258
12 changed files with 169 additions and 87 deletions

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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 {

View File

@@ -15,9 +15,9 @@
#include <string>
#include <vector>
#include "check.hxx"
#include "compat.hxx"
#include "plugin.hxx"
#include "typecheck.hxx"
#if CLANG_VERSION < 30700

View File

@@ -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());

View File

@@ -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;

View File

@@ -14,9 +14,9 @@
#include "clang/AST/Attr.h"
#include "check.hxx"
#include "compat.hxx"
#include "plugin.hxx"
#include "typecheck.hxx"
namespace {

View File

@@ -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

View File

@@ -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

View File

@@ -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