forked from OSchip/llvm-project
316 lines
8.3 KiB
C++
316 lines
8.3 KiB
C++
#include "../clang-tidy/utils/DeclRefExprUtils.h"
|
|
#include "ClangTidyDiagnosticConsumer.h"
|
|
#include "ClangTidyTest.h"
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace tidy {
|
|
|
|
namespace {
|
|
using namespace clang::ast_matchers;
|
|
|
|
class ConstReferenceDeclRefExprsTransform : public ClangTidyCheck {
|
|
public:
|
|
ConstReferenceDeclRefExprsTransform(StringRef CheckName,
|
|
ClangTidyContext *Context)
|
|
: ClangTidyCheck(CheckName, Context) {}
|
|
|
|
void registerMatchers(MatchFinder *Finder) override {
|
|
Finder->addMatcher(varDecl(hasName("target")).bind("var"), this);
|
|
}
|
|
|
|
void check(const MatchFinder::MatchResult &Result) override {
|
|
const auto *D = Result.Nodes.getNodeAs<VarDecl>("var");
|
|
using utils::decl_ref_expr::constReferenceDeclRefExprs;
|
|
const auto const_decrefexprs = constReferenceDeclRefExprs(
|
|
*D, *cast<FunctionDecl>(D->getDeclContext())->getBody(),
|
|
*Result.Context);
|
|
|
|
for (const DeclRefExpr *const Expr : const_decrefexprs) {
|
|
assert(Expr);
|
|
diag(Expr->getBeginLoc(), "const usage")
|
|
<< FixItHint::CreateInsertion(Expr->getBeginLoc(), "/*const*/");
|
|
}
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
namespace test {
|
|
|
|
void RunTest(StringRef Snippet) {
|
|
|
|
StringRef CommonCode = R"(
|
|
struct ConstTag{};
|
|
struct NonConstTag{};
|
|
|
|
struct S {
|
|
void constMethod() const;
|
|
void nonConstMethod();
|
|
|
|
void operator()(ConstTag) const;
|
|
void operator()(NonConstTag);
|
|
|
|
void operator[](int);
|
|
void operator[](int) const;
|
|
|
|
bool operator==(const S&) const;
|
|
|
|
int int_member;
|
|
int* ptr_member;
|
|
|
|
};
|
|
|
|
struct Derived : public S {
|
|
|
|
};
|
|
|
|
void useVal(S);
|
|
void useRef(S&);
|
|
void usePtr(S*);
|
|
void usePtrPtr(S**);
|
|
void usePtrConstPtr(S* const*);
|
|
void useConstRef(const S&);
|
|
void useConstPtr(const S*);
|
|
void useConstPtrRef(const S*&);
|
|
void useConstPtrPtr(const S**);
|
|
void useConstPtrConstRef(const S* const&);
|
|
void useConstPtrConstPtr(const S* const*);
|
|
|
|
void useInt(int);
|
|
void useIntRef(int&);
|
|
void useIntConstRef(const int&);
|
|
void useIntPtr(int*);
|
|
void useIntConstPtr(const int*);
|
|
|
|
)";
|
|
|
|
std::string Code = (CommonCode + Snippet).str();
|
|
|
|
llvm::SmallVector<StringRef, 1> Parts;
|
|
StringRef(Code).split(Parts, "/*const*/");
|
|
|
|
EXPECT_EQ(Code, runCheckOnCode<ConstReferenceDeclRefExprsTransform>(
|
|
join(Parts, "")));
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) {
|
|
RunTest(R"(
|
|
void f(const S target) {
|
|
useVal(/*const*/target);
|
|
useConstRef(/*const*/target);
|
|
useConstPtr(&target);
|
|
useConstPtrConstRef(&target);
|
|
/*const*/target.constMethod();
|
|
/*const*/target(ConstTag{});
|
|
/*const*/target[42];
|
|
useConstRef((/*const*/target));
|
|
(/*const*/target).constMethod();
|
|
(void)(/*const*/target == /*const*/target);
|
|
(void)target;
|
|
(void)⌖
|
|
(void)*⌖
|
|
S copy1 = /*const*/target;
|
|
S copy2(/*const*/target);
|
|
useInt(target.int_member);
|
|
useIntConstRef(target.int_member);
|
|
useIntPtr(target.ptr_member);
|
|
useIntConstPtr(&target.int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {
|
|
RunTest(R"(
|
|
void f(const S& target) {
|
|
useVal(/*const*/target);
|
|
useConstRef(/*const*/target);
|
|
useConstPtr(&target);
|
|
useConstPtrConstRef(&target);
|
|
/*const*/target.constMethod();
|
|
/*const*/target(ConstTag{});
|
|
/*const*/target[42];
|
|
useConstRef((/*const*/target));
|
|
(/*const*/target).constMethod();
|
|
(void)(/*const*/target == /*const*/target);
|
|
(void)target;
|
|
(void)⌖
|
|
(void)*⌖
|
|
S copy1 = /*const*/target;
|
|
S copy2(/*const*/target);
|
|
useInt(target.int_member);
|
|
useIntConstRef(target.int_member);
|
|
useIntPtr(target.ptr_member);
|
|
useIntConstPtr(&target.int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
|
|
RunTest(R"(
|
|
void f(S target, const S& other) {
|
|
useConstRef(/*const*/target);
|
|
useVal(/*const*/target);
|
|
useConstPtr(&target);
|
|
useConstPtrConstRef(&target);
|
|
/*const*/target.constMethod();
|
|
target.nonConstMethod();
|
|
/*const*/target(ConstTag{});
|
|
target[42];
|
|
/*const*/target(ConstTag{});
|
|
target(NonConstTag{});
|
|
useRef(target);
|
|
usePtr(&target);
|
|
useConstRef((/*const*/target));
|
|
(/*const*/target).constMethod();
|
|
(void)(/*const*/target == /*const*/target);
|
|
(void)(/*const*/target == other);
|
|
(void)target;
|
|
(void)⌖
|
|
(void)*⌖
|
|
S copy1 = /*const*/target;
|
|
S copy2(/*const*/target);
|
|
useInt(target.int_member);
|
|
useIntConstRef(target.int_member);
|
|
useIntPtr(target.ptr_member);
|
|
useIntConstPtr(&target.int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, RefVar) {
|
|
RunTest(R"(
|
|
void f(S& target) {
|
|
useVal(/*const*/target);
|
|
useConstRef(/*const*/target);
|
|
useConstPtr(&target);
|
|
useConstPtrConstRef(&target);
|
|
/*const*/target.constMethod();
|
|
target.nonConstMethod();
|
|
/*const*/target(ConstTag{});
|
|
target[42];
|
|
useConstRef((/*const*/target));
|
|
(/*const*/target).constMethod();
|
|
(void)(/*const*/target == /*const*/target);
|
|
(void)target;
|
|
(void)⌖
|
|
(void)*⌖
|
|
S copy1 = /*const*/target;
|
|
S copy2(/*const*/target);
|
|
useInt(target.int_member);
|
|
useIntConstRef(target.int_member);
|
|
useIntPtr(target.ptr_member);
|
|
useIntConstPtr(&target.int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
|
|
RunTest(R"(
|
|
void f(S* target) {
|
|
useVal(*target);
|
|
useConstRef(*target);
|
|
useConstPtr(target);
|
|
useConstPtrConstRef(/*const*/target);
|
|
/*const*/target->constMethod();
|
|
target->nonConstMethod();
|
|
(*target)(ConstTag{});
|
|
(*target)[42];
|
|
target->operator[](42);
|
|
useConstRef((*target));
|
|
(/*const*/target)->constMethod();
|
|
(void)(*target == *target);
|
|
(void)*target;
|
|
(void)target;
|
|
S copy1 = *target;
|
|
S copy2(*target);
|
|
useInt(target->int_member);
|
|
useIntConstRef(target->int_member);
|
|
useIntPtr(target->ptr_member);
|
|
useIntConstPtr(&target->int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {
|
|
RunTest(R"(
|
|
void f(const S* target) {
|
|
useVal(*target);
|
|
useConstRef(*target);
|
|
useConstPtr(target);
|
|
useConstPtrRef(target);
|
|
useConstPtrPtr(&target);
|
|
useConstPtrConstPtr(&target);
|
|
useConstPtrConstRef(/*const*/target);
|
|
/*const*/target->constMethod();
|
|
(*target)(ConstTag{});
|
|
(*target)[42];
|
|
/*const*/target->operator[](42);
|
|
(void)(*target == *target);
|
|
(void)target;
|
|
(void)*target;
|
|
if(target) {}
|
|
S copy1 = *target;
|
|
S copy2(*target);
|
|
useInt(target->int_member);
|
|
useIntConstRef(target->int_member);
|
|
useIntPtr(target->ptr_member);
|
|
useIntConstPtr(&target->int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ConstPtrPtrVar) {
|
|
RunTest(R"(
|
|
void f(const S** target) {
|
|
useVal(**target);
|
|
useConstRef(**target);
|
|
useConstPtr(*target);
|
|
useConstPtrRef(*target);
|
|
useConstPtrPtr(target);
|
|
useConstPtrConstPtr(target);
|
|
useConstPtrConstRef(*target);
|
|
(void)target;
|
|
(void)*target;
|
|
(void)**target;
|
|
if(target) {}
|
|
if(*target) {}
|
|
S copy1 = **target;
|
|
S copy2(**target);
|
|
useInt((*target)->int_member);
|
|
useIntConstRef((*target)->int_member);
|
|
useIntPtr((*target)->ptr_member);
|
|
useIntConstPtr(&(*target)->int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(ConstReferenceDeclRefExprsTest, ConstPtrConstPtrVar) {
|
|
RunTest(R"(
|
|
void f(const S* const* target) {
|
|
useVal(**target);
|
|
useConstRef(**target);
|
|
useConstPtr(*target);
|
|
useConstPtrConstPtr(target);
|
|
useConstPtrConstRef(*target);
|
|
(void)target;
|
|
(void)target;
|
|
(void)**target;
|
|
if(target) {}
|
|
if(*target) {}
|
|
S copy1 = **target;
|
|
S copy2(**target);
|
|
useInt((*target)->int_member);
|
|
useIntConstRef((*target)->int_member);
|
|
useIntPtr((*target)->ptr_member);
|
|
useIntConstPtr(&(*target)->int_member);
|
|
}
|
|
)");
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace tidy
|
|
} // namespace clang
|