brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · d0148a8 Raw
111 lines · cpp
1//===- unittests/Analysis/CloneDetectionTest.cpp - Clone detection tests --===//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 "clang/Analysis/CloneDetection.h"10#include "clang/AST/DynamicRecursiveASTVisitor.h"11#include "clang/Tooling/Tooling.h"12#include "gtest/gtest.h"13 14namespace clang {15namespace analysis {16namespace {17 18class CloneDetectionVisitor : public DynamicRecursiveASTVisitor {19 20  CloneDetector &Detector;21 22public:23  explicit CloneDetectionVisitor(CloneDetector &D) : Detector(D) {}24 25  bool VisitFunctionDecl(FunctionDecl *D) override {26    Detector.analyzeCodeBody(D);27    return true;28  }29};30 31/// Example constraint for testing purposes.32/// Filters out all statements that are in a function which name starts with33/// "bar".34class NoBarFunctionConstraint {35public:36  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {37    CloneConstraint::splitCloneGroups(38        CloneGroups, [](const StmtSequence &A, const StmtSequence &B) {39          // Check if one of the sequences is in a function which name starts40          // with "bar".41          for (const StmtSequence &Arg : {A, B}) {42            if (const auto *D =43                    dyn_cast<const FunctionDecl>(Arg.getContainingDecl())) {44              if (D->getName().starts_with("bar"))45                return false;46            }47          }48          return true;49        });50  }51};52 53TEST(CloneDetector, FilterFunctionsByName) {54  auto ASTUnit =55      clang::tooling::buildASTFromCode("void foo1(int &a1) { a1++; }\n"56                                       "void foo2(int &a2) { a2++; }\n"57                                       "void bar1(int &a3) { a3++; }\n"58                                       "void bar2(int &a4) { a4++; }\n");59  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();60 61  CloneDetector Detector;62  // Push all the function bodies into the detector.63  CloneDetectionVisitor Visitor(Detector);64  Visitor.TraverseTranslationUnitDecl(TU);65 66  // Find clones with the usual settings, but we want to filter out67  // all statements from functions which names start with "bar".68  std::vector<CloneDetector::CloneGroup> CloneGroups;69  Detector.findClones(CloneGroups, NoBarFunctionConstraint(),70                      RecursiveCloneTypeIIHashConstraint(),71                      MinComplexityConstraint(2), MinGroupSizeConstraint(2),72                      RecursiveCloneTypeIIVerifyConstraint(),73                      OnlyLargestCloneConstraint());74 75  ASSERT_EQ(CloneGroups.size(), 1u);76  ASSERT_EQ(CloneGroups.front().size(), 2u);77 78  for (auto &Clone : CloneGroups.front()) {79    const auto ND = dyn_cast<const FunctionDecl>(Clone.getContainingDecl());80    ASSERT_TRUE(ND != nullptr);81    // Check that no function name starting with "bar" is in the results...82    ASSERT_TRUE(ND->getNameAsString().find("bar") != 0);83  }84 85  // Retry above's example without the filter...86  CloneGroups.clear();87 88  Detector.findClones(CloneGroups, RecursiveCloneTypeIIHashConstraint(),89                      MinComplexityConstraint(2), MinGroupSizeConstraint(2),90                      RecursiveCloneTypeIIVerifyConstraint(),91                      OnlyLargestCloneConstraint());92  ASSERT_EQ(CloneGroups.size(), 1u);93  ASSERT_EQ(CloneGroups.front().size(), 4u);94 95  // Count how many functions with the bar prefix we have in the results.96  int FoundFunctionsWithBarPrefix = 0;97  for (auto &Clone : CloneGroups.front()) {98    const auto ND = dyn_cast<const FunctionDecl>(Clone.getContainingDecl());99    ASSERT_TRUE(ND != nullptr);100    // This time check that we picked up the bar functions from above101    if (ND->getNameAsString().find("bar") == 0) {102      FoundFunctionsWithBarPrefix++;103    }104  }105  // We should have found the two functions bar1 and bar2.106  ASSERT_EQ(FoundFunctionsWithBarPrefix, 2);107}108} // namespace109} // namespace analysis110} // namespace clang111