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#include <fstream>
16
17using namespace clang;
18using namespace ento;
19
20namespace {
21
22class DescriptiveNameChecker : public Checker<check::PreCall> {
23public:
24 void checkPreCall(const CallEvent &Call, CheckerContext &C) const {
25 if (!HandlerFn.matches(Call))
26 return;
27
28 const MemRegion *ArgReg = Call.getArgSVal(Index: 0).getAsRegion();
29 assert(ArgReg && "expecting a location as the first argument");
30
31 auto DescriptiveName = ArgReg->getDescriptiveName(/*UseQuotes=*/false);
32 if (ExplodedNode *Node = C.generateNonFatalErrorNode(State: C.getState())) {
33 auto Report =
34 std::make_unique<PathSensitiveBugReport>(args: Bug, args&: DescriptiveName, args&: Node);
35 C.emitReport(R: std::move(Report));
36 }
37 }
38
39private:
40 const BugType Bug{this, "DescriptiveNameBug"};
41 const CallDescription HandlerFn = {{"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)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
145} // namespace
146

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