1//===- MemRegionDescriptiveNameTest.cpp -----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CheckerRegistration.h"
10#include "clang/StaticAnalyzer/Core/Checker.h"
11#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
12#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
13#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
14#include "gtest/gtest.h"
15
16using namespace clang;
17using namespace ento;
18
19namespace {
20
21class DescriptiveNameChecker : public Checker<check::PreCall> {
22public:
23 void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
24 if (!HandlerFn.matches(Call))
25 return;
26
27 const MemRegion *ArgReg = Call.getArgSVal(Index: 0).getAsRegion();
28 assert(ArgReg && "expecting a location as the first argument");
29
30 auto DescriptiveName = ArgReg->getDescriptiveName(/*UseQuotes=*/false);
31 if (ExplodedNode *Node = C.generateNonFatalErrorNode(State: C.getState())) {
32 auto Report =
33 std::make_unique<PathSensitiveBugReport>(args: Bug, args&: DescriptiveName, args&: Node);
34 C.emitReport(R: std::move(Report));
35 }
36 }
37
38private:
39 const BugType Bug{this, "DescriptiveNameBug"};
40 const CallDescription HandlerFn = {
41 CDM::SimpleFunc, {"reportDescriptiveName"}, 1};
42};
43
44void addDescriptiveNameChecker(AnalysisASTConsumer &AnalysisConsumer,
45 AnalyzerOptions &AnOpts) {
46 AnOpts.CheckersAndPackages = {{"DescriptiveNameChecker", true}};
47 AnalysisConsumer.AddCheckerRegistrationFn(Fn: [](CheckerRegistry &Registry) {
48 Registry.addChecker<DescriptiveNameChecker>(FullName: "DescriptiveNameChecker",
49 Desc: "Desc", DocsUri: "DocsURI");
50 });
51}
52
53bool runChecker(StringRef Code, std::string &Output) {
54 return runCheckerOnCode<addDescriptiveNameChecker>(Code: Code.str(), Diags&: Output,
55 /*OnlyEmitWarnings=*/true);
56}
57
58TEST(MemRegionDescriptiveNameTest, ConcreteIntElementRegionIndex) {
59 StringRef Code = R"cpp(
60void reportDescriptiveName(int *p);
61const unsigned int index = 1;
62extern int array[3];
63void top() {
64 reportDescriptiveName(&array[index]);
65})cpp";
66
67 std::string Output;
68 ASSERT_TRUE(runChecker(Code, Output));
69 EXPECT_EQ(Output, "DescriptiveNameChecker: array[1]\n");
70}
71
72TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndex) {
73 StringRef Code = R"cpp(
74void reportDescriptiveName(int *p);
75extern unsigned int index;
76extern int array[3];
77void top() {
78 reportDescriptiveName(&array[index]);
79})cpp";
80
81 std::string Output;
82 ASSERT_TRUE(runChecker(Code, Output));
83 EXPECT_EQ(Output, "DescriptiveNameChecker: array[index]\n");
84}
85
86TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexSymbolValFails) {
87 StringRef Code = R"cpp(
88void reportDescriptiveName(int *p);
89extern int* ptr;
90extern int array[3];
91void top() {
92 reportDescriptiveName(&array[(long long)ptr]);
93})cpp";
94
95 std::string Output;
96 ASSERT_TRUE(runChecker(Code, Output));
97 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
98}
99
100TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexOrigRegionFails) {
101 StringRef Code = R"cpp(
102void reportDescriptiveName(int *p);
103extern int getInt(void);
104extern int array[3];
105void top() {
106 reportDescriptiveName(&array[getInt()]);
107})cpp";
108
109 std::string Output;
110 ASSERT_TRUE(runChecker(Code, Output));
111 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
112}
113
114TEST(MemRegionDescriptiveNameTest, SymbolicElementRegionIndexDescrNameFails) {
115 StringRef Code = R"cpp(
116void reportDescriptiveName(int *p);
117extern int *ptr;
118extern int array[3];
119void top() {
120 reportDescriptiveName(&array[*ptr]);
121})cpp";
122
123 std::string Output;
124 ASSERT_TRUE(runChecker(Code, Output));
125 EXPECT_EQ(Output, "DescriptiveNameChecker: \n");
126}
127
128TEST(MemRegionDescriptiveNameTest,
129 SymbolicElementRegionIndexIncorrectSymbolName) {
130 StringRef Code = R"cpp(
131void reportDescriptiveName(int *p);
132extern int x, y;
133extern int array[3];
134void top() {
135 y = x;
136 reportDescriptiveName(&array[y]);
137})cpp";
138
139 std::string Output;
140 ASSERT_TRUE(runChecker(Code, Output));
141 // FIXME: Should return array[y], but returns array[x] (OriginRegion).
142 EXPECT_EQ(Output, "DescriptiveNameChecker: array[x]\n");
143}
144
145TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperElementReg) {
146 StringRef Code = R"cpp(
147void reportDescriptiveName(int *p);
148struct val_struct { int val; };
149extern struct val_struct val_struct_array[3];
150void top() {
151 reportDescriptiveName(&val_struct_array[0].val);
152})cpp";
153
154 std::string Output;
155 ASSERT_TRUE(runChecker(Code, Output));
156 EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[0].val\n");
157}
158
159TEST(MemRegionDescriptiveNameTest, FieldRegWithSuperMultidimElementReg) {
160 StringRef Code = R"cpp(
161void reportDescriptiveName(int *p);
162struct val_struct { int val; };
163extern struct val_struct val_struct_array[3][4];
164void top() {
165 reportDescriptiveName(&val_struct_array[1][2].val);
166})cpp";
167
168 std::string Output;
169 ASSERT_TRUE(runChecker(Code, Output));
170 EXPECT_EQ(Output, "DescriptiveNameChecker: val_struct_array[1][2].val\n");
171}
172
173} // namespace
174

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/unittests/StaticAnalyzer/MemRegionDescriptiveNameTest.cpp