brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.6 KiB · 0cb3c59 Raw
124 lines · cpp
1//===- unittests/StaticAnalyzer/TestReturnValueUnderConstruction.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CheckerRegistration.h"10#include "clang/StaticAnalyzer/Core/Checker.h"11#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"12#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"13#include "clang/StaticAnalyzer/Frontend/AnalysisConsumer.h"14#include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h"15#include "clang/Tooling/Tooling.h"16#include "gtest/gtest.h"17#include <optional>18 19namespace clang {20namespace ento {21namespace {22 23class TestReturnValueUnderConstructionChecker24  : public Checker<check::PostCall> {25public:26  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {27    // Only calls with origin expression are checked. These are `returnC()`,28    // `returnD()`, C::C() and D::D().29    if (!Call.getOriginExpr())30      return;31 32    // Since `returnC` returns an object by value, the invocation results33    // in an object of type `C` constructed into variable `c`. Thus the34    // return value of `CallEvent::getReturnValueUnderConstruction()` must35    // be non-empty and has to be a `MemRegion`.36    std::optional<SVal> RetVal = Call.getReturnValueUnderConstruction();37    ASSERT_TRUE(RetVal);38    ASSERT_TRUE(RetVal->getAsRegion());39 40    const auto *RetReg = cast<TypedValueRegion>(RetVal->getAsRegion());41    const Expr *OrigExpr = Call.getOriginExpr();42    ASSERT_EQ(OrigExpr->getType()->getCanonicalTypeInternal(),43              RetReg->getValueType()->getCanonicalTypeInternal());44  }45};46 47void addTestReturnValueUnderConstructionChecker(48    AnalysisASTConsumer &AnalysisConsumer, AnalyzerOptions &AnOpts) {49  AnOpts.CheckersAndPackages =50    {{"test.TestReturnValueUnderConstruction", true}};51  AnalysisConsumer.AddCheckerRegistrationFn([](CheckerRegistry &Registry) {52    Registry.addChecker<TestReturnValueUnderConstructionChecker>(53        "test.TestReturnValueUnderConstruction", "MockDescription");54  });55}56 57TEST(TestReturnValueUnderConstructionChecker,58     ReturnValueUnderConstructionChecker) {59  EXPECT_TRUE(runCheckerOnCode<addTestReturnValueUnderConstructionChecker>(60      R"(class C {61         public:62           C(int nn): n(nn) {}63           virtual ~C() {}64         private:65           int n;66         };67 68         C returnC(int m) {69           C c(m);70           return c;71         }72 73         void foo() {74           C c = returnC(1);75         })"));76 77  EXPECT_TRUE(runCheckerOnCode<addTestReturnValueUnderConstructionChecker>(78      R"(class C {79         public:80           C(int nn): n(nn) {}81           explicit C(): C(0) {}82           virtual ~C() {}83         private:84           int n;85         };86 87         C returnC() {88           C c;89           return c;90         }91 92         void foo() {93           C c = returnC();94         })"));95 96  EXPECT_TRUE(runCheckerOnCode<addTestReturnValueUnderConstructionChecker>(97      R"(class C {98         public:99           C(int nn): n(nn) {}100           virtual ~C() {}101         private:102           int n;103         };104 105         class D: public C {106         public:107           D(int nn): C(nn) {}108           virtual ~D() {}109         };110 111         D returnD(int m) {112           D d(m);113           return d;114         }115 116         void foo() {117           D d = returnD(1); 118         })"));119}120 121} // namespace122} // namespace ento123} // namespace clang124