<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Yep, sorry, should be fixed in r276791.<br>
    <br>
    <div class="moz-cite-prefix">On 26.07.2016 22:13, Mike Aizatsky
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAGq4m1-2w3TQx4AQc7n+uppHtZXbftp=cyhjy1vm1Hg-nJTwFw@mail.gmail.com"
      type="cite">
      <div dir="ltr">Artem,
        <div><br>
        </div>
        <div>I think you broke the build. Could you take a look please?</div>
        <div><br>
        </div>
        <div><a moz-do-not-send="true"
href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer/builds/11051">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer/builds/11051</a><br>
        </div>
        <div><a moz-do-not-send="true"
href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer/builds/11051/steps/build%20clang/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer/builds/11051/steps/build%20clang/logs/stdio</a><br>
        </div>
        <div><br>
        </div>
        <div>
          <pre style="font-family:"courier new",courier,monotype,monospace;font-size:medium;line-height:normal"><span class="inbox-inbox-stdout">[80/140] Building CXX object tools/clang/lib/StaticAnalyzer/Checkers/CMakeFiles/clangStaticAnalyzerCheckers.dir/CloneChecker.cpp.o
FAILED: tools/clang/lib/StaticAnalyzer/Checkers/CMakeFiles/clangStaticAnalyzerCheckers.dir/CloneChecker.cpp.o 
/usr/bin/c++   -DCLANG_ENABLE_ARCMT -DCLANG_ENABLE_OBJC_REWRITER -DCLANG_ENABLE_STATIC_ANALYZER -DGTEST_HAS_RTTI=0 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools/clang/lib/StaticAnalyzer/Checkers -I/mnt/b/sanitizer-buildbo</span><span class="inbox-inbox-stdout">t5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers -I/mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/include -Itools/clang/include -Iinclude -I/mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/include -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -Werror=date-time -std=c++11 -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -fno-strict-aliasing -O3 -DNDEBUG    -fno-exceptions -fno-rtti -MMD -MT tools/clang/lib/StaticAn
alyzer/Checkers/CMakeFiles/clangStaticAnalyzerCheckers.dir/CloneChecker.cpp.o -MF tools/clang/lib/StaticAnalyzer/Checkers/CMakeFiles/clangStaticAnalyzerCheckers.dir/CloneChecker.cpp.o.d -o tools/clang/lib/StaticAnalyzer/Checkers/CMakeFiles/clangStaticAnalyzerCheckers.dir/CloneChecker.cpp.o -c /mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
</span><span class="inbox-inbox-stdout">/mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp:29:25: error: declaration of ‘clang::CloneDetector {anonymous}::CloneChecker::CloneDetector’ [-fpermissive]
   mutable CloneDetector CloneDetector;
                         ^
In file included from /mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp:17:0:
/mnt/b/sanitizer-buildbot5/sanitizer-x86_64-linux-fuzzer/build/llvm/tools/clang/include/clang/Analysis/CloneDetection.h:158:7: error: changes meaning of ‘CloneDetector’ from ‘class clang::CloneDetector’ [-fpermissive]
 class CloneDetector {
       ^
</span></pre>
          <br class="inbox-inbox-Apple-interchange-newline">
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr">On Tue, Jul 26, 2016 at 11:28 AM Artem Dergachev
          via cfe-commits <<a moz-do-not-send="true"
            href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0 0 0
          .8ex;border-left:1px #ccc solid;padding-left:1ex">Author:
          dergachev<br>
          Date: Tue Jul 26 13:13:12 2016<br>
          New Revision: 276782<br>
          <br>
          URL: <a moz-do-not-send="true"
            href="http://llvm.org/viewvc/llvm-project?rev=276782&view=rev"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=276782&view=rev</a><br>
          Log:<br>
          [analyzer] Add basic capabilities to detect source code
          clones.<br>
          <br>
          This patch adds the CloneDetector class which allows searching
          source code<br>
          for clones.<br>
          <br>
          For every statement or group of statements within a compound
          statement,<br>
          CloneDetector computes a hash value, and finds clones by
          detecting<br>
          identical hash values.<br>
          <br>
          This initial patch only provides a simple hashing mechanism<br>
          that hashes the kind of each sub-statement.<br>
          <br>
          This patch also adds CloneChecker - a simple static analyzer
          checker<br>
          that uses CloneDetector to report copy-pasted code.<br>
          <br>
          Patch by Raphael Isemann!<br>
          <br>
          Differential Revision: <a moz-do-not-send="true"
            href="https://reviews.llvm.org/D20795" rel="noreferrer"
            target="_blank">https://reviews.llvm.org/D20795</a><br>
          <br>
          Added:<br>
              cfe/trunk/include/clang/Analysis/CloneDetection.h<br>
              cfe/trunk/lib/Analysis/CloneDetection.cpp<br>
              cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp<br>
              cfe/trunk/test/Analysis/copypaste/<br>
              cfe/trunk/test/Analysis/copypaste/blocks.cpp<br>
              cfe/trunk/test/Analysis/copypaste/false-positives.cpp<br>
              cfe/trunk/test/Analysis/copypaste/functions.cpp<br>
              cfe/trunk/test/Analysis/copypaste/objc-methods.m<br>
              cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp<br>
          Modified:<br>
             
          cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br>
              cfe/trunk/lib/Analysis/CMakeLists.txt<br>
              cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br>
          <br>
          Added: cfe/trunk/include/clang/Analysis/CloneDetection.h<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CloneDetection.h?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CloneDetection.h?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/include/clang/Analysis/CloneDetection.h (added)<br>
          +++ cfe/trunk/include/clang/Analysis/CloneDetection.h Tue Jul
          26 13:13:12 2016<br>
          @@ -0,0 +1,235 @@<br>
          +//===--- CloneDetection.h - Finds code clones in an AST
          ---------*- C++ -*-===//<br>
          +//<br>
          +//                     The LLVM Compiler Infrastructure<br>
          +//<br>
          +// This file is distributed under the University of Illinois
          Open Source<br>
          +// License. See LICENSE.TXT for details.<br>
          +//<br>
+//===----------------------------------------------------------------------===//<br>
          +///<br>
          +/// /file<br>
          +/// This file defines classes for searching and anlyzing
          source code clones.<br>
          +///<br>
+//===----------------------------------------------------------------------===//<br>
          +<br>
          +#ifndef LLVM_CLANG_AST_CLONEDETECTION_H<br>
          +#define LLVM_CLANG_AST_CLONEDETECTION_H<br>
          +<br>
          +#include "clang/Basic/SourceLocation.h"<br>
          +#include "llvm/ADT/StringMap.h"<br>
          +<br>
          +#include <vector><br>
          +<br>
          +namespace clang {<br>
          +<br>
          +class Stmt;<br>
          +class Decl;<br>
          +class ASTContext;<br>
          +class CompoundStmt;<br>
          +<br>
          +/// \brief Identifies a list of statements.<br>
          +///<br>
          +/// Can either identify a single arbitrary Stmt object, a
          continuous sequence of<br>
          +/// child statements inside a CompoundStmt or no statements
          at all.<br>
          +class StmtSequence {<br>
          +  /// If this object identifies a sequence of statements
          inside a CompoundStmt,<br>
          +  /// S points to this CompoundStmt. If this object only
          identifies a single<br>
          +  /// Stmt, then S is a pointer to this Stmt.<br>
          +  const Stmt *S;<br>
          +<br>
          +  /// The related ASTContext for S.<br>
          +  ASTContext *Context;<br>
          +<br>
          +  /// If EndIndex is non-zero, then S is a CompoundStmt and
          this StmtSequence<br>
          +  /// instance is representing the CompoundStmt children
          inside the array<br>
          +  /// [StartIndex, EndIndex).<br>
          +  unsigned StartIndex;<br>
          +  unsigned EndIndex;<br>
          +<br>
          +public:<br>
          +  /// \brief Constructs a StmtSequence holding multiple
          statements.<br>
          +  ///<br>
          +  /// The resulting StmtSequence identifies a continuous
          sequence of statements<br>
          +  /// in the body of the given CompoundStmt. Which statements
          of the body should<br>
          +  /// be identified needs to be specified by providing a
          start and end index<br>
          +  /// that describe a non-empty sub-array in the body of the
          given CompoundStmt.<br>
          +  ///<br>
          +  /// \param Stmt A CompoundStmt that contains all statements
          in its body.<br>
          +  /// \param Context The ASTContext for the given
          CompoundStmt.<br>
          +  /// \param StartIndex The inclusive start index in the
          children array of<br>
          +  ///                   \p Stmt<br>
          +  /// \param EndIndex The exclusive end index in the children
          array of \p Stmt.<br>
          +  StmtSequence(const CompoundStmt *Stmt, ASTContext
          &Context,<br>
          +               unsigned StartIndex, unsigned EndIndex);<br>
          +<br>
          +  /// \brief Constructs a StmtSequence holding a single
          statement.<br>
          +  ///<br>
          +  /// \param Stmt An arbitrary Stmt.<br>
          +  /// \param Context The ASTContext for the given Stmt.<br>
          +  StmtSequence(const Stmt *Stmt, ASTContext &Context);<br>
          +<br>
          +  /// \brief Constructs an empty StmtSequence.<br>
          +  StmtSequence();<br>
          +<br>
          +  typedef const Stmt *const *iterator;<br>
          +<br>
          +  /// Returns an iterator pointing to the first statement in
          this sequence.<br>
          +  iterator begin() const;<br>
          +<br>
          +  /// Returns an iterator pointing behind the last statement
          in this sequence.<br>
          +  iterator end() const;<br>
          +<br>
          +  /// Returns the first statement in this sequence.<br>
          +  ///<br>
          +  /// This method should only be called on a non-empty
          StmtSequence object.<br>
          +  const Stmt *front() const {<br>
          +    assert(!empty());<br>
          +    return begin()[0];<br>
          +  }<br>
          +<br>
          +  /// Returns the last statement in this sequence.<br>
          +  ///<br>
          +  /// This method should only be called on a non-empty
          StmtSequence object.<br>
          +  const Stmt *back() const {<br>
          +    assert(!empty());<br>
          +    return begin()[size() - 1];<br>
          +  }<br>
          +<br>
          +  /// Returns the number of statements this object holds.<br>
          +  unsigned size() const {<br>
          +    if (holdsSequence())<br>
          +      return EndIndex - StartIndex;<br>
          +    if (S == nullptr)<br>
          +      return 0;<br>
          +    return 1;<br>
          +  }<br>
          +<br>
          +  /// Returns true if and only if this StmtSequence contains
          no statements.<br>
          +  bool empty() const { return size() == 0; }<br>
          +<br>
          +  /// Returns the related ASTContext for the stored Stmts.<br>
          +  ASTContext &getASTContext() const {<br>
          +    assert(Context);<br>
          +    return *Context;<br>
          +  }<br>
          +<br>
          +  /// Returns true if this objects holds a list of
          statements.<br>
          +  bool holdsSequence() const { return EndIndex != 0; }<br>
          +<br>
          +  /// Returns the start sourcelocation of the first statement
          in this sequence.<br>
          +  ///<br>
          +  /// This method should only be called on a non-empty
          StmtSequence object.<br>
          +  SourceLocation getStartLoc() const;<br>
          +<br>
          +  /// Returns the end sourcelocation of the last statement in
          this sequence.<br>
          +  ///<br>
          +  /// This method should only be called on a non-empty
          StmtSequence object.<br>
          +  SourceLocation getEndLoc() const;<br>
          +<br>
          +  bool operator==(const StmtSequence &Other) const {<br>
          +    return std::tie(S, StartIndex, EndIndex) ==<br>
          +           std::tie(Other.S, Other.StartIndex,
          Other.EndIndex);<br>
          +  }<br>
          +<br>
          +  bool operator!=(const StmtSequence &Other) const {<br>
          +    return std::tie(S, StartIndex, EndIndex) !=<br>
          +           std::tie(Other.S, Other.StartIndex,
          Other.EndIndex);<br>
          +  }<br>
          +<br>
          +  /// Returns true if and only if this sequence covers a
          source range that<br>
          +  /// contains the source range of the given sequence \p
          Other.<br>
          +  ///<br>
          +  /// This method should only be called on a non-empty
          StmtSequence object<br>
          +  /// and passed a non-empty StmtSequence object.<br>
          +  bool contains(const StmtSequence &Other) const;<br>
          +};<br>
          +<br>
          +/// \brief Searches for clones in source code.<br>
          +///<br>
          +/// First, this class needs a translation unit which is
          passed via<br>
          +/// \p analyzeTranslationUnit . It will then generate and
          store search data<br>
          +/// for all statements inside the given translation unit.<br>
          +/// Afterwards the generated data can be used to find code
          clones by calling<br>
          +/// \p findClones .<br>
          +///<br>
          +/// This class only searches for clones in exectuable source
          code<br>
          +/// (e.g. function bodies). Other clones (e.g. cloned
          comments or declarations)<br>
          +/// are not supported.<br>
          +class CloneDetector {<br>
          +public:<br>
          +  /// Holds the data about a StmtSequence that is needed
          during the search for<br>
          +  /// code clones.<br>
          +  struct CloneSignature {<br>
          +    /// \brief Holds all relevant data of a StmtSequence.<br>
          +    ///<br>
          +    /// If this variable is equal for two different
          StmtSequences, then they can<br>
          +    /// be considered clones of each other.<br>
          +    std::vector<unsigned> Data;<br>
          +<br>
          +    /// \brief The complexity of the StmtSequence.<br>
          +    ///<br>
          +    /// This scalar value serves as a simple way of filtering
          clones that are<br>
          +    /// too small to be reported. A greater value indicates
          that the related<br>
          +    /// StmtSequence is probably more interesting to the
          user.<br>
          +    unsigned Complexity;<br>
          +<br>
          +    /// \brief Creates an empty CloneSignature without any
          data.<br>
          +    CloneSignature() : Complexity(1) {}<br>
          +<br>
          +    CloneSignature(const std::vector<unsigned>
          &Data, unsigned Complexity)<br>
          +        : Data(Data), Complexity(Complexity) {}<br>
          +<br>
          +    /// \brief Adds the data from the given CloneSignature to
          this one.<br>
          +    void add(const CloneSignature &Other) {<br>
          +      Data.insert(Data.end(), Other.Data.begin(),
          Other.Data.end());<br>
          +      Complexity += Other.Complexity;<br>
          +    }<br>
          +  };<br>
          +<br>
          +  /// Holds group of StmtSequences that are clones of each
          other and the<br>
          +  /// complexity value (see CloneSignature::Complexity) that
          all stored<br>
          +  /// StmtSequences have in common.<br>
          +  struct CloneGroup {<br>
          +    std::vector<StmtSequence> Sequences;<br>
          +    unsigned Complexity;<br>
          +<br>
          +    CloneGroup(const StmtSequence &Seq, unsigned
          Complexity)<br>
          +        : Complexity(Complexity) {<br>
          +      Sequences.push_back(Seq);<br>
          +    }<br>
          +<br>
          +    /// \brief Returns false if and only if this group should
          be skipped when<br>
          +    ///        searching for clones.<br>
          +    bool isValid() const {<br>
          +      // A clone group with only one member makes no sense,
          so we skip them.<br>
          +      return Sequences.size() > 1;<br>
          +    }<br>
          +  };<br>
          +<br>
          +  /// \brief Generates and stores search data for all
          statements in the body of<br>
          +  ///        the given Decl.<br>
          +  void analyzeCodeBody(const Decl *D);<br>
          +<br>
          +  /// \brief Stores the CloneSignature to allow future
          querying.<br>
          +  void add(const StmtSequence &S, const CloneSignature
          &Signature);<br>
          +<br>
          +  /// \brief Searches the provided statements for clones.<br>
          +  ///<br>
          +  /// \param Result Output parameter that is filled with a
          list of found<br>
          +  ///               clone groups. Each group contains
          multiple StmtSequences<br>
          +  ///               that were identified to be clones of each
          other.<br>
          +  /// \param MinGroupComplexity Only return clones which have
          at least this<br>
          +  ///                           complexity value.<br>
          +  void findClones(std::vector<CloneGroup> &Result,
          unsigned MinGroupComplexity);<br>
          +<br>
          +private:<br>
          +  /// Stores all found clone groups including invalid groups
          with only a single<br>
          +  /// statement.<br>
          +  std::vector<CloneGroup> CloneGroups;<br>
          +  /// Maps search data to its related index in the \p
          CloneGroups vector.<br>
          +  llvm::StringMap<std::size_t> CloneGroupIndexes;<br>
          +};<br>
          +<br>
          +} // end namespace clang<br>
          +<br>
          +#endif // LLVM_CLANG_AST_CLONEDETECTION_H<br>
          <br>
          Modified:
          cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=276782&r1=276781&r2=276782&view=diff"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=276782&r1=276781&r2=276782&view=diff</a><br>
==============================================================================<br>
          ---
          cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
          (original)<br>
          +++
          cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
          Tue Jul 26 13:13:12 2016<br>
          @@ -77,6 +77,8 @@ def MPI : Package<"mpi">,
          InPackage<OptI<br>
           def LLVM : Package<"llvm">;<br>
           def Debug : Package<"debug">;<br>
          <br>
          +def CloneDetectionAlpha : Package<"clone">,
          InPackage<Alpha>, Hidden;<br>
          +<br>
 //===----------------------------------------------------------------------===//<br>
           // Core Checkers.<br>
 //===----------------------------------------------------------------------===//<br>
          @@ -661,3 +663,17 @@ def BugHashDumper :
          Checker<"DumpBugHash<br>
             DescFile<"DebugCheckers.cpp">;<br>
          <br>
           } // end "debug"<br>
          +<br>
          +<br>
+//===----------------------------------------------------------------------===//<br>
          +// Clone Detection<br>
+//===----------------------------------------------------------------------===//<br>
          +<br>
          +let ParentPackage = CloneDetectionAlpha in {<br>
          +<br>
          +def CloneChecker : Checker<"CloneChecker">,<br>
          +  HelpText<"Reports similar pieces of code.">,<br>
          +  DescFile<"CloneChecker.cpp">;<br>
          +<br>
          +} // end "clone"<br>
          +<br>
          <br>
          Modified: cfe/trunk/lib/Analysis/CMakeLists.txt<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=276782&r1=276781&r2=276782&view=diff"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=276782&r1=276781&r2=276782&view=diff</a><br>
==============================================================================<br>
          --- cfe/trunk/lib/Analysis/CMakeLists.txt (original)<br>
          +++ cfe/trunk/lib/Analysis/CMakeLists.txt Tue Jul 26 13:13:12
          2016<br>
          @@ -9,6 +9,7 @@ add_clang_library(clangAnalysis<br>
             CFGReachabilityAnalysis.cpp<br>
             CFGStmtMap.cpp<br>
             CallGraph.cpp<br>
          +  CloneDetection.cpp<br>
             CocoaConventions.cpp<br>
             Consumed.cpp<br>
             CodeInjector.cpp<br>
          <br>
          Added: cfe/trunk/lib/Analysis/CloneDetection.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CloneDetection.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CloneDetection.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/lib/Analysis/CloneDetection.cpp (added)<br>
          +++ cfe/trunk/lib/Analysis/CloneDetection.cpp Tue Jul 26
          13:13:12 2016<br>
          @@ -0,0 +1,277 @@<br>
          +//===--- CloneDetection.cpp - Finds code clones in an AST
          -------*- C++ -*-===//<br>
          +//<br>
          +//                     The LLVM Compiler Infrastructure<br>
          +//<br>
          +// This file is distributed under the University of Illinois
          Open Source<br>
          +// License. See LICENSE.TXT for details.<br>
          +//<br>
+//===----------------------------------------------------------------------===//<br>
          +///<br>
          +///  This file implements classes for searching and anlyzing
          source code clones.<br>
          +///<br>
+//===----------------------------------------------------------------------===//<br>
          +<br>
          +#include "clang/Analysis/CloneDetection.h"<br>
          +<br>
          +#include "clang/AST/ASTContext.h"<br>
          +#include "clang/AST/RecursiveASTVisitor.h"<br>
          +#include "clang/AST/Stmt.h"<br>
          +#include "llvm/ADT/StringRef.h"<br>
          +<br>
          +using namespace clang;<br>
          +<br>
          +StmtSequence::StmtSequence(const CompoundStmt *Stmt,
          ASTContext &Context,<br>
          +                           unsigned StartIndex, unsigned
          EndIndex)<br>
          +    : S(Stmt), Context(&Context), StartIndex(StartIndex),
          EndIndex(EndIndex) {<br>
          +  assert(Stmt && "Stmt must not be a nullptr");<br>
          +  assert(StartIndex < EndIndex && "Given array
          should not be empty");<br>
          +  assert(EndIndex <= Stmt->size() && "Given
          array too big for this Stmt");<br>
          +}<br>
          +<br>
          +StmtSequence::StmtSequence(const Stmt *Stmt, ASTContext
          &Context)<br>
          +    : S(Stmt), Context(&Context), StartIndex(0),
          EndIndex(0) {}<br>
          +<br>
          +StmtSequence::StmtSequence()<br>
          +    : S(nullptr), Context(nullptr), StartIndex(0),
          EndIndex(0) {}<br>
          +<br>
          +bool StmtSequence::contains(const StmtSequence &Other)
          const {<br>
          +  // If both sequences reside in different translation units,
          they can never<br>
          +  // contain each other.<br>
          +  if (Context != Other.Context)<br>
          +    return false;<br>
          +<br>
          +  const SourceManager &SM =
          Context->getSourceManager();<br>
          +<br>
          +  // Otherwise check if the start and end locations of the
          current sequence<br>
          +  // surround the other sequence.<br>
          +  bool StartIsInBounds =<br>
          +      SM.isBeforeInTranslationUnit(getStartLoc(),
          Other.getStartLoc()) ||<br>
          +      getStartLoc() == Other.getStartLoc();<br>
          +  if (!StartIsInBounds)<br>
          +    return false;<br>
          +<br>
          +  bool EndIsInBounds =<br>
          +      SM.isBeforeInTranslationUnit(Other.getEndLoc(),
          getEndLoc()) ||<br>
          +      Other.getEndLoc() == getEndLoc();<br>
          +  return EndIsInBounds;<br>
          +}<br>
          +<br>
          +StmtSequence::iterator StmtSequence::begin() const {<br>
          +  if (!holdsSequence()) {<br>
          +    return &S;<br>
          +  }<br>
          +  auto CS = cast<CompoundStmt>(S);<br>
          +  return CS->body_begin() + StartIndex;<br>
          +}<br>
          +<br>
          +StmtSequence::iterator StmtSequence::end() const {<br>
          +  if (!holdsSequence()) {<br>
          +    return &S + 1;<br>
          +  }<br>
          +  auto CS = cast<CompoundStmt>(S);<br>
          +  return CS->body_begin() + EndIndex;<br>
          +}<br>
          +<br>
          +SourceLocation StmtSequence::getStartLoc() const {<br>
          +  return front()->getLocStart();<br>
          +}<br>
          +<br>
          +SourceLocation StmtSequence::getEndLoc() const { return
          back()->getLocEnd(); }<br>
          +<br>
          +namespace {<br>
          +/// Generates CloneSignatures for a set of statements and
          stores the results in<br>
          +/// a CloneDetector object.<br>
          +class CloneSignatureGenerator {<br>
          +<br>
          +  CloneDetector &CD;<br>
          +  ASTContext &Context;<br>
          +<br>
          +  /// \brief Generates CloneSignatures for all statements in
          the given statement<br>
          +  /// tree and stores them in the CloneDetector.<br>
          +  ///<br>
          +  /// \param S The root of the given statement tree.<br>
          +  /// \return The CloneSignature of the root statement.<br>
          +  CloneDetector::CloneSignature generateSignatures(const Stmt
          *S) {<br>
          +    // Create an empty signature that will be filled in this
          method.<br>
          +    CloneDetector::CloneSignature Signature;<br>
          +<br>
          +    // The only relevant data for now is the class of the
          statement.<br>
          +    // TODO: Collect statement class specific data.<br>
          +    Signature.Data.push_back(S->getStmtClass());<br>
          +<br>
          +    // Storage for the signatures of the direct child
          statements. This is only<br>
          +    // needed if the current statement is a CompoundStmt.<br>
          +    std::vector<CloneDetector::CloneSignature>
          ChildSignatures;<br>
          +    const CompoundStmt *CS = dyn_cast<const
          CompoundStmt>(S);<br>
          +<br>
          +    // The signature of a statement includes the signatures
          of its children.<br>
          +    // Therefore we create the signatures for every child and
          add them to the<br>
          +    // current signature.<br>
          +    for (const Stmt *Child : S->children()) {<br>
          +      // Some statements like 'if' can have nullptr children
          that we will skip.<br>
          +      if (!Child)<br>
          +        continue;<br>
          +<br>
          +      // Recursive call to create the signature of the child
          statement. This<br>
          +      // will also create and store all clone groups in this
          child statement.<br>
          +      auto ChildSignature = generateSignatures(Child);<br>
          +<br>
          +      // Add the collected data to the signature of the
          current statement.<br>
          +      Signature.add(ChildSignature);<br>
          +<br>
          +      // If the current statement is a CompoundStatement, we
          need to store the<br>
          +      // signature for the generation of the sub-sequences.<br>
          +      if (CS)<br>
          +        ChildSignatures.push_back(ChildSignature);<br>
          +    }<br>
          +<br>
          +    // If the current statement is a CompoundStmt, we also
          need to create the<br>
          +    // clone groups from the sub-sequences inside the
          children.<br>
          +    if (CS)<br>
          +      handleSubSequences(CS, ChildSignatures);<br>
          +<br>
          +    // Save the signature for the current statement in the
          CloneDetector object.<br>
          +    CD.add(StmtSequence(S, Context), Signature);<br>
          +<br>
          +    return Signature;<br>
          +  }<br>
          +<br>
          +  /// \brief Adds all possible sub-sequences in the child
          array of the given<br>
          +  ///        CompoundStmt to the CloneDetector.<br>
          +  /// \param CS The given CompoundStmt.<br>
          +  /// \param ChildSignatures A list of calculated signatures
          for each child in<br>
          +  ///                        the given CompoundStmt.<br>
          +  void handleSubSequences(<br>
          +      const CompoundStmt *CS,<br>
          +      const std::vector<CloneDetector::CloneSignature>
          &ChildSignatures) {<br>
          +<br>
          +    // FIXME: This function has quadratic runtime right now.
          Check if skipping<br>
          +    // this function for too long CompoundStmts is an option.<br>
          +<br>
          +    // The length of the sub-sequence. We don't need to
          handle sequences with<br>
          +    // the length 1 as they are already handled in
          CollectData().<br>
          +    for (unsigned Length = 2; Length <= CS->size();
          ++Length) {<br>
          +      // The start index in the body of the CompoundStmt. We
          increase the<br>
          +      // position until the end of the sub-sequence reaches
          the end of the<br>
          +      // CompoundStmt body.<br>
          +      for (unsigned Pos = 0; Pos <= CS->size() -
          Length; ++Pos) {<br>
          +        // Create an empty signature and add the signatures
          of all selected<br>
          +        // child statements to it.<br>
          +        CloneDetector::CloneSignature SubSignature;<br>
          +<br>
          +        for (unsigned i = Pos; i < Pos + Length; ++i) {<br>
          +          SubSignature.add(ChildSignatures[i]);<br>
          +        }<br>
          +<br>
          +        // Save the signature together with the information
          about what children<br>
          +        // sequence we selected.<br>
          +        CD.add(StmtSequence(CS, Context, Pos, Pos + Length),
          SubSignature);<br>
          +      }<br>
          +    }<br>
          +  }<br>
          +<br>
          +public:<br>
          +  explicit CloneSignatureGenerator(CloneDetector &CD,
          ASTContext &Context)<br>
          +      : CD(CD), Context(Context) {}<br>
          +<br>
          +  /// \brief Generates signatures for all statements in the
          given function body.<br>
          +  void consumeCodeBody(const Stmt *S) {
          generateSignatures(S); }<br>
          +};<br>
          +} // end anonymous namespace<br>
          +<br>
          +void CloneDetector::analyzeCodeBody(const Decl *D) {<br>
          +  assert(D);<br>
          +  assert(D->hasBody());<br>
          +  CloneSignatureGenerator Generator(*this,
          D->getASTContext());<br>
          +  Generator.consumeCodeBody(D->getBody());<br>
          +}<br>
          +<br>
          +void CloneDetector::add(const StmtSequence &S,<br>
          +                        const CloneSignature &Signature)
          {<br>
          +  // StringMap only works with StringRefs, so we create one
          for our data vector.<br>
          +  auto &Data = Signature.Data;<br>
          +  StringRef DataRef = StringRef(reinterpret_cast<const
          char *>(Data.data()),<br>
          +                                Data.size() *
          sizeof(unsigned));<br>
          +<br>
          +  // Search with the help of the signature if we already have
          encountered a<br>
          +  // clone of the given StmtSequence.<br>
          +  auto I = CloneGroupIndexes.find(DataRef);<br>
          +  if (I == CloneGroupIndexes.end()) {<br>
          +    // We haven't found an existing clone group, so we create
          a new clone group<br>
          +    // for this StmtSequence and store the index of it in our
          search map.<br>
          +    CloneGroupIndexes[DataRef] = CloneGroups.size();<br>
          +    CloneGroups.emplace_back(S, Signature.Complexity);<br>
          +    return;<br>
          +  }<br>
          +<br>
          +  // We have found an existing clone group and can expand it
          with the given<br>
          +  // StmtSequence.<br>
          +  CloneGroups[I->getValue()].Sequences.push_back(S);<br>
          +}<br>
          +<br>
          +namespace {<br>
          +/// \brief Returns true if and only if \p Stmt contains at
          least one other<br>
          +/// sequence in the \p Group.<br>
          +bool containsAnyInGroup(StmtSequence &Stmt,<br>
          +                            CloneDetector::CloneGroup
          &Group) {<br>
          +  for (StmtSequence &GroupStmt : Group.Sequences) {<br>
          +    if (Stmt.contains(GroupStmt))<br>
          +      return true;<br>
          +  }<br>
          +  return false;<br>
          +}<br>
          +<br>
          +/// \brief Returns true if and only if all sequences in \p
          OtherGroup are<br>
          +/// contained by a sequence in \p Group.<br>
          +bool containsGroup(CloneDetector::CloneGroup &Group,<br>
          +                   CloneDetector::CloneGroup &OtherGroup)
          {<br>
          +  // We have less sequences in the current group than we have
          in the other,<br>
          +  // so we will never fulfill the requirement for returning
          true. This is only<br>
          +  // possible because we know that a sequence in Group can
          contain at most<br>
          +  // one sequence in OtherGroup.<br>
          +  if (Group.Sequences.size() <
          OtherGroup.Sequences.size())<br>
          +    return false;<br>
          +<br>
          +  for (StmtSequence &Stmt : Group.Sequences) {<br>
          +    if (!containsAnyInGroup(Stmt, OtherGroup))<br>
          +      return false;<br>
          +  }<br>
          +  return true;<br>
          +}<br>
          +} // end anonymous namespace<br>
          +<br>
          +void CloneDetector::findClones(std::vector<CloneGroup>
          &Result,<br>
          +                               unsigned MinGroupComplexity) {<br>
          +  // Add every valid clone group that fulfills the complexity
          requirement.<br>
          +  for (const CloneGroup &Group : CloneGroups) {<br>
          +    if (Group.isValid() && Group.Complexity >=
          MinGroupComplexity) {<br>
          +      Result.push_back(Group);<br>
          +    }<br>
          +  }<br>
          +<br>
          +  std::vector<unsigned> IndexesToRemove;<br>
          +<br>
          +  // Compare every group in the result with the rest. If one
          groups contains<br>
          +  // another group, we only need to return the bigger group.<br>
          +  // Note: This doesn't scale well, so if possible avoid
          calling any heavy<br>
          +  // function from this loop to minimize the performance
          impact.<br>
          +  for (unsigned i = 0; i < Result.size(); ++i) {<br>
          +    for (unsigned j = 0; j < Result.size(); ++j) {<br>
          +      // Don't compare a group with itself.<br>
          +      if (i == j)<br>
          +        continue;<br>
          +<br>
          +      if (containsGroup(Result[j], Result[i])) {<br>
          +        IndexesToRemove.push_back(i);<br>
          +        break;<br>
          +      }<br>
          +    }<br>
          +  }<br>
          +<br>
          +  // Erasing a list of indexes from the vector should be done
          with decreasing<br>
          +  // indexes. As IndexesToRemove is constructed with
          increasing values, we just<br>
          +  // reverse iterate over it to get the desired order.<br>
          +  for (auto I = IndexesToRemove.rbegin(); I !=
          IndexesToRemove.rend(); ++I) {<br>
          +    Result.erase(Result.begin() + *I);<br>
          +  }<br>
          +}<br>
          <br>
          Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=276782&r1=276781&r2=276782&view=diff"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=276782&r1=276781&r2=276782&view=diff</a><br>
==============================================================================<br>
          --- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
          (original)<br>
          +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Tue
          Jul 26 13:13:12 2016<br>
          @@ -22,6 +22,7 @@ add_clang_library(clangStaticAnalyzerChe<br>
             CheckerDocumentation.cpp<br>
             ChrootChecker.cpp<br>
             ClangCheckers.cpp<br>
          +  CloneChecker.cpp<br>
             CXXSelfAssignmentChecker.cpp<br>
             DeadStoresChecker.cpp<br>
             DebugCheckers.cpp<br>
          <br>
          Added: cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
          (added)<br>
          +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp Tue
          Jul 26 13:13:12 2016<br>
          @@ -0,0 +1,96 @@<br>
          +//===--- CloneChecker.cpp - Clone detection checker
          -------------*- C++ -*-===//<br>
          +//<br>
          +//                     The LLVM Compiler Infrastructure<br>
          +//<br>
          +// This file is distributed under the University of Illinois
          Open Source<br>
          +// License. See LICENSE.TXT for details.<br>
          +//<br>
+//===----------------------------------------------------------------------===//<br>
          +///<br>
          +/// \file<br>
          +/// CloneChecker is a checker that reports clones in the
          current translation<br>
          +/// unit.<br>
          +///<br>
+//===----------------------------------------------------------------------===//<br>
          +<br>
          +#include "ClangSACheckers.h"<br>
          +#include "clang/Analysis/CloneDetection.h"<br>
          +#include "clang/Basic/Diagnostic.h"<br>
          +#include "clang/StaticAnalyzer/Core/Checker.h"<br>
          +#include "clang/StaticAnalyzer/Core/CheckerManager.h"<br>
          +#include
          "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"<br>
          +<br>
          +using namespace clang;<br>
          +using namespace ento;<br>
          +<br>
          +namespace {<br>
          +class CloneChecker<br>
          +    : public Checker<check::ASTCodeBody,
          check::EndOfTranslationUnit> {<br>
          +  mutable CloneDetector CloneDetector;<br>
          +<br>
          +public:<br>
          +  void checkASTCodeBody(const Decl *D, AnalysisManager
          &Mgr,<br>
          +                        BugReporter &BR) const;<br>
          +<br>
          +  void checkEndOfTranslationUnit(const TranslationUnitDecl
          *TU,<br>
          +                                 AnalysisManager &Mgr,
          BugReporter &BR) const;<br>
          +};<br>
          +} // end anonymous namespace<br>
          +<br>
          +void CloneChecker::checkASTCodeBody(const Decl *D,
          AnalysisManager &Mgr,<br>
          +                                    BugReporter &BR)
          const {<br>
          +  // Every statement that should be included in the search
          for clones needs to<br>
          +  // be passed to the CloneDetector.<br>
          +  CloneDetector.analyzeCodeBody(D);<br>
          +}<br>
          +<br>
          +void CloneChecker::checkEndOfTranslationUnit(const
          TranslationUnitDecl *TU,<br>
          +                                             AnalysisManager
          &Mgr,<br>
          +                                             BugReporter
          &BR) const {<br>
          +  // At this point, every statement in the translation unit
          has been analyzed by<br>
          +  // the CloneDetector. The only thing left to do is to
          report the found clones.<br>
          +<br>
          +  int MinComplexity =
          Mgr.getAnalyzerOptions().getOptionAsInteger(<br>
          +      "MinimumCloneComplexity", 10, this);<br>
          +<br>
          +  assert(MinComplexity >= 0);<br>
          +<br>
          +  SourceManager &SM = BR.getSourceManager();<br>
          +<br>
          +  std::vector<CloneDetector::CloneGroup> CloneGroups;<br>
          +  CloneDetector.findClones(CloneGroups, MinComplexity);<br>
          +<br>
          +  DiagnosticsEngine &DiagEngine = Mgr.getDiagnostic();<br>
          +<br>
          +  unsigned WarnID =
          DiagEngine.getCustomDiagID(DiagnosticsEngine::Warning,<br>
          +                                               "Detected code
          clone.");<br>
          +<br>
          +  unsigned NoteID =
          DiagEngine.getCustomDiagID(DiagnosticsEngine::Note,<br>
          +                                               "Related code
          clone is here.");<br>
          +<br>
          +  for (CloneDetector::CloneGroup &Group : CloneGroups) {<br>
          +    // For readability reasons we sort the clones by line
          numbers.<br>
          +    std::sort(Group.Sequences.begin(), Group.Sequences.end(),<br>
          +              [&SM](const StmtSequence &LHS, const
          StmtSequence &RHS) {<br>
          +                return
          SM.isBeforeInTranslationUnit(LHS.getStartLoc(),<br>
          +                                                   
          RHS.getStartLoc()) &&<br>
          +                     
           SM.isBeforeInTranslationUnit(LHS.getEndLoc(),<br>
          +                                                   
          RHS.getEndLoc());<br>
          +              });<br>
          +<br>
          +    // We group the clones by printing the first as a warning
          and all others<br>
          +    // as a note.<br>
          +    DiagEngine.Report(Group.Sequences.front().getStartLoc(),
          WarnID);<br>
          +    for (unsigned i = 1; i < Group.Sequences.size(); ++i)
          {<br>
          +      DiagEngine.Report(Group.Sequences[i].getStartLoc(),
          NoteID);<br>
          +    }<br>
          +  }<br>
          +}<br>
          +<br>
+//===----------------------------------------------------------------------===//<br>
          +// Register CloneChecker<br>
+//===----------------------------------------------------------------------===//<br>
          +<br>
          +void ento::registerCloneChecker(CheckerManager &Mgr) {<br>
          +  Mgr.registerChecker<CloneChecker>();<br>
          +}<br>
          <br>
          Added: cfe/trunk/test/Analysis/copypaste/blocks.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/blocks.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/blocks.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/test/Analysis/copypaste/blocks.cpp (added)<br>
          +++ cfe/trunk/test/Analysis/copypaste/blocks.cpp Tue Jul 26
          13:13:12 2016<br>
          @@ -0,0 +1,19 @@<br>
          +// RUN: %clang_cc1 -analyze -fblocks -std=c++11
          -analyzer-checker=alpha.clone.CloneChecker -verify %s<br>
          +<br>
          +// This tests if we search for clones in blocks.<br>
          +<br>
          +void log();<br>
          +<br>
          +auto BlockA = ^(int a, int b){ // expected-warning{{Detected
          code clone.}}<br>
          +  log();<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +};<br>
          +<br>
          +auto BlockB = ^(int a, int b){ // expected-note{{Related code
          clone is here.}}<br>
          +  log();<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +};<br>
          <br>
          Added: cfe/trunk/test/Analysis/copypaste/false-positives.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/false-positives.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/false-positives.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/test/Analysis/copypaste/false-positives.cpp
          (added)<br>
          +++ cfe/trunk/test/Analysis/copypaste/false-positives.cpp Tue
          Jul 26 13:13:12 2016<br>
          @@ -0,0 +1,29 @@<br>
          +// RUN: %clang_cc1 -analyze -std=c++11
          -analyzer-checker=alpha.clone.CloneChecker -verify %s<br>
          +<br>
          +// This test contains false-positive reports from the
          CloneChecker that need to<br>
          +// be fixed.<br>
          +<br>
          +void log();<br>
          +<br>
          +int max(int a, int b) { // expected-warning{{Detected code
          clone.}}<br>
          +  log();<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +<br>
          +// FIXME: Detect different binary operator kinds.<br>
          +int min1(int a, int b) { // expected-note{{Related code clone
          is here.}}<br>
          +  log();<br>
          +  if (a < b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +<br>
          +// FIXME: Detect different variable patterns.<br>
          +int min2(int a, int b) { // expected-note{{Related code clone
          is here.}}<br>
          +  log();<br>
          +  if (b > a)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          <br>
          Added: cfe/trunk/test/Analysis/copypaste/functions.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/functions.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/functions.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/test/Analysis/copypaste/functions.cpp (added)<br>
          +++ cfe/trunk/test/Analysis/copypaste/functions.cpp Tue Jul 26
          13:13:12 2016<br>
          @@ -0,0 +1,25 @@<br>
          +// RUN: %clang_cc1 -analyze -std=c++11
          -analyzer-checker=alpha.clone.CloneChecker -verify %s<br>
          +<br>
          +// This tests if we search for clones in functions.<br>
          +<br>
          +void log();<br>
          +<br>
          +int max(int a, int b) { // expected-warning{{Detected code
          clone.}}<br>
          +  log();<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +<br>
          +int maxClone(int x, int y) { // expected-note{{Related code
          clone is here.}}<br>
          +  log();<br>
          +  if (x > y)<br>
          +    return x;<br>
          +  return y;<br>
          +}<br>
          +<br>
          +// Functions below are not clones and should not be reported.<br>
          +<br>
          +int foo(int a, int b) { // no-warning<br>
          +  return a + b;<br>
          +}<br>
          <br>
          Added: cfe/trunk/test/Analysis/copypaste/objc-methods.m<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/objc-methods.m?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/objc-methods.m?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/test/Analysis/copypaste/objc-methods.m (added)<br>
          +++ cfe/trunk/test/Analysis/copypaste/objc-methods.m Tue Jul
          26 13:13:12 2016<br>
          @@ -0,0 +1,27 @@<br>
          +// RUN: %clang_cc1 -analyze -Wno-objc-root-class
          -analyzer-checker=alpha.clone.CloneChecker -verify %s<br>
          +<br>
          +// This tests if we search for clones in Objective-C methods.<br>
          +<br>
          +@interface A<br>
          +- (int) setOk : (int) a : (int) b;<br>
          +@end<br>
          +<br>
          +@implementation A<br>
          +- (int) setOk : (int) a : (int) b {  //
          expected-warning{{Detected code clone.}}<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +@end<br>
          +<br>
          +@interface B<br>
          +- (int) setOk : (int) a : (int) b;<br>
          +@end<br>
          +<br>
          +@implementation B<br>
          +- (int) setOk : (int) a : (int) b { // expected-note{{Related
          code clone is here.}}<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +@end<br>
          <br>
          Added: cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp<br>
          URL: <a moz-do-not-send="true"
href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp?rev=276782&view=auto"
            rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp?rev=276782&view=auto</a><br>
==============================================================================<br>
          --- cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp
          (added)<br>
          +++ cfe/trunk/test/Analysis/copypaste/sub-sequences.cpp Tue
          Jul 26 13:13:12 2016<br>
          @@ -0,0 +1,27 @@<br>
          +// RUN: %clang_cc1 -analyze -std=c++11
          -analyzer-checker=alpha.clone.CloneChecker -verify %s<br>
          +<br>
          +// This tests if sub-sequences can match with normal
          sequences.<br>
          +<br>
          +void log2(int a);<br>
          +void log();<br>
          +<br>
          +int max(int a, int b) {<br>
          +  log2(a);<br>
          +  log(); // expected-warning{{Detected code clone.}}<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +<br>
          +int maxClone(int a, int b) {<br>
          +  log(); // expected-note{{Related code clone is here.}}<br>
          +  if (a > b)<br>
          +    return a;<br>
          +  return b;<br>
          +}<br>
          +<br>
          +// Functions below are not clones and should not be reported.<br>
          +<br>
          +int foo(int a, int b) { // no-warning<br>
          +  return a + b;<br>
          +}<br>
          <br>
          <br>
          _______________________________________________<br>
          cfe-commits mailing list<br>
          <a moz-do-not-send="true"
            href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
          <a moz-do-not-send="true"
            href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits"
            rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
        </blockquote>
      </div>
      <div dir="ltr">-- <br>
      </div>
      <div data-smartmail="gmail_signature">Mike<br>
        Sent from phone</div>
    </blockquote>
    <br>
  </body>
</html>