New loplugin:selfinit
...to find more bugs like the one addressed in6340daac7b
"Revert broken loplugin:sequentialassign change". What it does is: "Warn when a variable is referenced from its own initializer. This is not invalid in general (see C++17 [basic.life]), but is at least suspicious." It found one false positive (addressed with884ad0d1af
"Split localProcessFactory function into class with setter and getter") and five true positives (addressed withe0ccbe72ed
"Fix use of variable before its lifetime begins" and0e335af4d3
"Fix uses of variables before their lifetimes begin"). Change-Id: I4c45cceaa042e93b37ad24a54784c027f6ca1f87 Reviewed-on: https://gerrit.libreoffice.org/70897 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
88
compilerplugins/clang/selfinit.cxx
Normal file
88
compilerplugins/clang/selfinit.cxx
Normal file
@@ -0,0 +1,88 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "plugin.hxx"
|
||||
|
||||
// Warn when a variable is referenced from its own initializer. This is not invalid in general (see
|
||||
// C++17 [basic.life]), but is at least suspicious.
|
||||
|
||||
namespace
|
||||
{
|
||||
class SelfInit : public loplugin::FilteringPlugin<SelfInit>
|
||||
{
|
||||
public:
|
||||
explicit SelfInit(loplugin::InstantiationData const& data)
|
||||
: FilteringPlugin(data)
|
||||
{
|
||||
}
|
||||
|
||||
bool TraverseVarDecl(VarDecl* decl)
|
||||
{
|
||||
decls_.push_back({ decl, decl->getCanonicalDecl() });
|
||||
auto const ret = FilteringPlugin::TraverseVarDecl(decl);
|
||||
decls_.pop_back();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr* expr)
|
||||
{
|
||||
if (expr->getKind() == UETT_SizeOf)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return FilteringPlugin::TraverseUnaryExprOrTypeTraitExpr(expr);
|
||||
}
|
||||
|
||||
bool TraverseCXXTypeidExpr(CXXTypeidExpr const*) { return true; }
|
||||
|
||||
bool TraverseCXXNoexceptExpr(CXXNoexceptExpr const*) { return true; }
|
||||
|
||||
bool TraverseDecltypeTypeLoc(DecltypeTypeLoc) { return true; }
|
||||
|
||||
bool VisitDeclRefExpr(DeclRefExpr const* expr)
|
||||
{
|
||||
if (ignoreLocation(expr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for (auto const& i : decls_)
|
||||
{
|
||||
if (expr->getDecl()->getCanonicalDecl() == i.canonical)
|
||||
{
|
||||
report(
|
||||
DiagnosticsEngine::Warning,
|
||||
("referencing a variable during its own initialization is error-prone and thus"
|
||||
" suspicious"),
|
||||
expr->getLocation())
|
||||
<< expr->getSourceRange();
|
||||
report(DiagnosticsEngine::Note, "variable declared here", i.current->getLocation())
|
||||
<< i.current->getSourceRange();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
|
||||
|
||||
struct Decl
|
||||
{
|
||||
VarDecl const* current;
|
||||
VarDecl const* canonical;
|
||||
};
|
||||
|
||||
std::vector<Decl> decls_;
|
||||
};
|
||||
|
||||
loplugin::Plugin::Registration<SelfInit> X("selfinit");
|
||||
}
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
33
compilerplugins/clang/test/selfinit.cxx
Normal file
33
compilerplugins/clang/test/selfinit.cxx
Normal file
@@ -0,0 +1,33 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
extern int i;
|
||||
int i = i;
|
||||
// expected-error@-1 {{referencing a variable during its own initialization is error-prone and thus suspicious [loplugin:selfinit]}}
|
||||
// expected-note@-2 {{variable declared here [loplugin:selfinit]}}
|
||||
|
||||
int j = [](int n) { return j + n; }(0);
|
||||
// expected-error@-1 {{referencing a variable during its own initialization is error-prone and thus suspicious [loplugin:selfinit]}}
|
||||
// expected-note@-2 {{variable declared here [loplugin:selfinit]}}
|
||||
|
||||
int k = sizeof k;
|
||||
|
||||
int f(std::type_info const&);
|
||||
|
||||
int l = f(typeid(l));
|
||||
|
||||
bool m = noexcept(m);
|
||||
|
||||
template <typename T> int g();
|
||||
|
||||
int n = g<decltype(n)>();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|
@@ -51,6 +51,7 @@ $(eval $(call gb_CompilerTest_add_exception_objects,compilerplugins_clang, \
|
||||
compilerplugins/clang/test/salcall \
|
||||
compilerplugins/clang/test/sallogareas \
|
||||
compilerplugins/clang/test/salunicodeliteral \
|
||||
compilerplugins/clang/test/selfinit \
|
||||
compilerplugins/clang/test/sequentialassign \
|
||||
compilerplugins/clang/test/shouldreturnbool \
|
||||
compilerplugins/clang/test/simplifybool \
|
||||
|
Reference in New Issue
Block a user