clang  5.0.0
CloneDetection.h
Go to the documentation of this file.
1 //===--- CloneDetection.h - Finds code clones in an AST ---------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// /file
11 /// This file defines classes for searching and anlyzing source code clones.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_CLONEDETECTION_H
16 #define LLVM_CLANG_AST_CLONEDETECTION_H
17 
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/StmtVisitor.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/Regex.h"
24 #include <vector>
25 
26 namespace clang {
27 
28 class Stmt;
29 class Decl;
30 class VarDecl;
31 class ASTContext;
32 class CompoundStmt;
33 
34 namespace clone_detection {
35 
36 /// Returns a string that represents all macro expansions that expanded into the
37 /// given SourceLocation.
38 ///
39 /// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations
40 /// A and B are expanded from the same macros in the same order.
42 
43 /// Collects the data of a single Stmt.
44 ///
45 /// This class defines what a code clone is: If it collects for two statements
46 /// the same data, then those two statements are considered to be clones of each
47 /// other.
48 ///
49 /// All collected data is forwarded to the given data consumer of the type T.
50 /// The data consumer class needs to provide a member method with the signature:
51 /// update(StringRef Str)
52 template <typename T>
53 class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> {
54 
55  ASTContext &Context;
56  /// The data sink to which all data is forwarded.
57  T &DataConsumer;
58 
59 public:
60  /// Collects data of the given Stmt.
61  /// \param S The given statement.
62  /// \param Context The ASTContext of S.
63  /// \param DataConsumer The data sink to which all data is forwarded.
64  StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
65  : Context(Context), DataConsumer(DataConsumer) {
66  this->Visit(S);
67  }
68 
69  typedef unsigned DataPiece;
70 
71  // Below are utility methods for appending different data to the vector.
72 
73  void addData(DataPiece Integer) {
74  DataConsumer.update(
75  StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer)));
76  }
77 
78  void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
79 
80  void addData(const QualType &QT) { addData(QT.getAsString()); }
81 
82 // The functions below collect the class specific data of each Stmt subclass.
83 
84 // Utility macro for defining a visit method for a given class. This method
85 // calls back to the ConstStmtVisitor to visit all parent classes.
86 #define DEF_ADD_DATA(CLASS, CODE) \
87  void Visit##CLASS(const CLASS *S) { \
88  CODE; \
89  ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
90  }
91 
92  DEF_ADD_DATA(Stmt, {
93  addData(S->getStmtClass());
94  // This ensures that macro generated code isn't identical to macro-generated
95  // code.
96  addData(getMacroStack(S->getLocStart(), Context));
97  addData(getMacroStack(S->getLocEnd(), Context));
98  })
99  DEF_ADD_DATA(Expr, { addData(S->getType()); })
100 
101  //--- Builtin functionality ----------------------------------------------//
102  DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
103  DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
104  DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
105  DEF_ADD_DATA(TypeTraitExpr, {
106  addData(S->getTrait());
107  for (unsigned i = 0; i < S->getNumArgs(); ++i)
108  addData(S->getArg(i)->getType());
109  })
110 
111  //--- Calls --------------------------------------------------------------//
112  DEF_ADD_DATA(CallExpr, {
113  // Function pointers don't have a callee and we just skip hashing it.
114  if (const FunctionDecl *D = S->getDirectCallee()) {
115  // If the function is a template specialization, we also need to handle
116  // the template arguments as they are not included in the qualified name.
117  if (auto Args = D->getTemplateSpecializationArgs()) {
118  std::string ArgString;
119 
120  // Print all template arguments into ArgString
121  llvm::raw_string_ostream OS(ArgString);
122  for (unsigned i = 0; i < Args->size(); ++i) {
123  Args->get(i).print(Context.getLangOpts(), OS);
124  // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
125  OS << '\n';
126  }
127  OS.flush();
128 
129  addData(ArgString);
130  }
131  addData(D->getQualifiedNameAsString());
132  }
133  })
134 
135  //--- Exceptions ---------------------------------------------------------//
136  DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
137 
138  //--- C++ OOP Stmts ------------------------------------------------------//
139  DEF_ADD_DATA(CXXDeleteExpr, {
140  addData(S->isArrayFormAsWritten());
141  addData(S->isGlobalDelete());
142  })
143 
144  //--- Casts --------------------------------------------------------------//
145  DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
146 
147  //--- Miscellaneous Exprs ------------------------------------------------//
148  DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
149  DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
150 
151  //--- Control flow -------------------------------------------------------//
152  DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
153  DEF_ADD_DATA(IndirectGotoStmt, {
154  if (S->getConstantTarget())
155  addData(S->getConstantTarget()->getName());
156  })
157  DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
158  DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
159  DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
160 
161  //--- Objective-C --------------------------------------------------------//
162  DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
163  DEF_ADD_DATA(ObjCPropertyRefExpr, {
164  addData(S->isSuperReceiver());
165  addData(S->isImplicitProperty());
166  })
167  DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
168 
169  //--- Miscellaneous Stmts ------------------------------------------------//
170  DEF_ADD_DATA(CXXFoldExpr, {
171  addData(S->isRightFold());
172  addData(S->getOperator());
173  })
174  DEF_ADD_DATA(GenericSelectionExpr, {
175  for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
176  addData(S->getAssocType(i));
177  }
178  })
179  DEF_ADD_DATA(LambdaExpr, {
180  for (const LambdaCapture &C : S->captures()) {
181  addData(C.isPackExpansion());
182  addData(C.getCaptureKind());
183  if (C.capturesVariable())
184  addData(C.getCapturedVar()->getType());
185  }
186  addData(S->isGenericLambda());
187  addData(S->isMutable());
188  })
189  DEF_ADD_DATA(DeclStmt, {
190  auto numDecls = std::distance(S->decl_begin(), S->decl_end());
191  addData(static_cast<DataPiece>(numDecls));
192  for (const Decl *D : S->decls()) {
193  if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
194  addData(VD->getType());
195  }
196  }
197  })
198  DEF_ADD_DATA(AsmStmt, {
199  addData(S->isSimple());
200  addData(S->isVolatile());
201  addData(S->generateAsmString(Context));
202  for (unsigned i = 0; i < S->getNumInputs(); ++i) {
203  addData(S->getInputConstraint(i));
204  }
205  for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
206  addData(S->getOutputConstraint(i));
207  }
208  for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
209  addData(S->getClobber(i));
210  }
211  })
212  DEF_ADD_DATA(AttributedStmt, {
213  for (const Attr *A : S->getAttrs()) {
214  addData(std::string(A->getSpelling()));
215  }
216  })
217 };
218 } // namespace clone_detection
219 
220 /// Identifies a list of statements.
221 ///
222 /// Can either identify a single arbitrary Stmt object, a continuous sequence of
223 /// child statements inside a CompoundStmt or no statements at all.
225  /// If this object identifies a sequence of statements inside a CompoundStmt,
226  /// S points to this CompoundStmt. If this object only identifies a single
227  /// Stmt, then S is a pointer to this Stmt.
228  const Stmt *S;
229 
230  /// The declaration that contains the statements.
231  const Decl *D;
232 
233  /// If EndIndex is non-zero, then S is a CompoundStmt and this StmtSequence
234  /// instance is representing the CompoundStmt children inside the array
235  /// [StartIndex, EndIndex).
236  unsigned StartIndex;
237  unsigned EndIndex;
238 
239 public:
240  /// Constructs a StmtSequence holding multiple statements.
241  ///
242  /// The resulting StmtSequence identifies a continuous sequence of statements
243  /// in the body of the given CompoundStmt. Which statements of the body should
244  /// be identified needs to be specified by providing a start and end index
245  /// that describe a non-empty sub-array in the body of the given CompoundStmt.
246  ///
247  /// \param Stmt A CompoundStmt that contains all statements in its body.
248  /// \param D The Decl containing this Stmt.
249  /// \param StartIndex The inclusive start index in the children array of
250  /// \p Stmt
251  /// \param EndIndex The exclusive end index in the children array of \p Stmt.
252  StmtSequence(const CompoundStmt *Stmt, const Decl *D, unsigned StartIndex,
253  unsigned EndIndex);
254 
255  /// Constructs a StmtSequence holding a single statement.
256  ///
257  /// \param Stmt An arbitrary Stmt.
258  /// \param D The Decl containing this Stmt.
259  StmtSequence(const Stmt *Stmt, const Decl *D);
260 
261  /// Constructs an empty StmtSequence.
262  StmtSequence();
263 
264  typedef const Stmt *const *iterator;
265 
266  /// Returns an iterator pointing to the first statement in this sequence.
267  iterator begin() const;
268 
269  /// Returns an iterator pointing behind the last statement in this sequence.
270  iterator end() const;
271 
272  /// Returns the first statement in this sequence.
273  ///
274  /// This method should only be called on a non-empty StmtSequence object.
275  const Stmt *front() const {
276  assert(!empty());
277  return begin()[0];
278  }
279 
280  /// Returns the last statement in this sequence.
281  ///
282  /// This method should only be called on a non-empty StmtSequence object.
283  const Stmt *back() const {
284  assert(!empty());
285  return begin()[size() - 1];
286  }
287 
288  /// Returns the number of statements this object holds.
289  unsigned size() const {
290  if (holdsSequence())
291  return EndIndex - StartIndex;
292  if (S == nullptr)
293  return 0;
294  return 1;
295  }
296 
297  /// Returns true if and only if this StmtSequence contains no statements.
298  bool empty() const { return size() == 0; }
299 
300  /// Returns the related ASTContext for the stored Stmts.
301  ASTContext &getASTContext() const;
302 
303  /// Returns the declaration that contains the stored Stmts.
304  const Decl *getContainingDecl() const {
305  assert(D);
306  return D;
307  }
308 
309  /// Returns true if this objects holds a list of statements.
310  bool holdsSequence() const { return EndIndex != 0; }
311 
312  /// Returns the start sourcelocation of the first statement in this sequence.
313  ///
314  /// This method should only be called on a non-empty StmtSequence object.
315  SourceLocation getStartLoc() const;
316 
317  /// Returns the end sourcelocation of the last statement in this sequence.
318  ///
319  /// This method should only be called on a non-empty StmtSequence object.
320  SourceLocation getEndLoc() const;
321 
322  /// Returns the source range of the whole sequence - from the beginning
323  /// of the first statement to the end of the last statement.
324  SourceRange getSourceRange() const;
325 
326  bool operator==(const StmtSequence &Other) const {
327  return std::tie(S, StartIndex, EndIndex) ==
328  std::tie(Other.S, Other.StartIndex, Other.EndIndex);
329  }
330 
331  bool operator!=(const StmtSequence &Other) const {
332  return std::tie(S, StartIndex, EndIndex) !=
333  std::tie(Other.S, Other.StartIndex, Other.EndIndex);
334  }
335 
336  /// Returns true if and only if this sequence covers a source range that
337  /// contains the source range of the given sequence \p Other.
338  ///
339  /// This method should only be called on a non-empty StmtSequence object
340  /// and passed a non-empty StmtSequence object.
341  bool contains(const StmtSequence &Other) const;
342 };
343 
344 /// Searches for similar subtrees in the AST.
345 ///
346 /// First, this class needs several declarations with statement bodies which
347 /// can be passed via analyzeCodeBody. Afterwards all statements can be
348 /// searched for clones by calling findClones with a given list of constraints
349 /// that should specify the wanted properties of the clones.
350 ///
351 /// The result of findClones can be further constrained with the constrainClones
352 /// method.
353 ///
354 /// This class only searches for clones in exectuable source code
355 /// (e.g. function bodies). Other clones (e.g. cloned comments or declarations)
356 /// are not supported.
358 
359 public:
360  /// A collection of StmtSequences that share an arbitrary property.
362 
363  /// Generates and stores search data for all statements in the body of
364  /// the given Decl.
365  void analyzeCodeBody(const Decl *D);
366 
367  /// Constrains the given list of clone groups with the given constraint.
368  ///
369  /// The constraint is expected to have a method with the signature
370  /// `void constrain(std::vector<CloneDetector::CloneGroup> &Sequences)`
371  /// as this is the interface that the CloneDetector uses for applying the
372  /// constraint. The constraint is supposed to directly modify the passed list
373  /// so that all clones in the list fulfill the specific property this
374  /// constraint ensures.
375  template <typename T>
376  static void constrainClones(std::vector<CloneGroup> &CloneGroups, T C) {
377  C.constrain(CloneGroups);
378  }
379 
380  /// Constrains the given list of clone groups with the given list of
381  /// constraints.
382  ///
383  /// The constraints are applied in sequence in the order in which they are
384  /// passed to this function.
385  template <typename T1, typename... Ts>
386  static void constrainClones(std::vector<CloneGroup> &CloneGroups, T1 C,
387  Ts... ConstraintList) {
388  constrainClones(CloneGroups, C);
389  constrainClones(CloneGroups, ConstraintList...);
390  }
391 
392  /// Searches for clones in all previously passed statements.
393  /// \param Result Output parameter to which all created clone groups are
394  /// added.
395  /// \param ConstraintList The constraints that should be applied to the
396  // result.
397  template <typename... Ts>
398  void findClones(std::vector<CloneGroup> &Result, Ts... ConstraintList) {
399  // The initial assumption is that there is only one clone group and every
400  // statement is a clone of the others. This clone group will then be
401  // split up with the help of the constraints.
402  CloneGroup AllClones;
403  AllClones.reserve(Sequences.size());
404  for (const auto &C : Sequences) {
405  AllClones.push_back(C);
406  }
407 
408  Result.push_back(AllClones);
409 
410  constrainClones(Result, ConstraintList...);
411  }
412 
413 private:
414  CloneGroup Sequences;
415 };
416 
417 /// This class is a utility class that contains utility functions for building
418 /// custom constraints.
420 public:
421  /// Removes all groups by using a filter function.
422  /// \param CloneGroups The list of CloneGroups that is supposed to be
423  /// filtered.
424  /// \param Filter The filter function that should return true for all groups
425  /// that should be removed from the list.
426  static void
427  filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups,
428  std::function<bool(const CloneDetector::CloneGroup &)> Filter) {
429  CloneGroups.erase(
430  std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter),
431  CloneGroups.end());
432  }
433 
434  /// Splits the given CloneGroups until the given Compare function returns true
435  /// for all clones in a single group.
436  /// \param CloneGroups A list of CloneGroups that should be modified.
437  /// \param Compare The comparison function that all clones are supposed to
438  /// pass. Should return true if and only if two clones belong
439  /// to the same CloneGroup.
440  static void splitCloneGroups(
441  std::vector<CloneDetector::CloneGroup> &CloneGroups,
442  std::function<bool(const StmtSequence &, const StmtSequence &)> Compare);
443 };
444 
445 /// Searches all children of the given clones for type II clones (i.e. they are
446 /// identical in every aspect beside the used variable names).
448 
449  /// Generates and saves a hash code for the given Stmt.
450  /// \param S The given Stmt.
451  /// \param D The Decl containing S.
452  /// \param StmtsByHash Output parameter that will contain the hash codes for
453  /// each StmtSequence in the given Stmt.
454  /// \return The hash code of the given Stmt.
455  ///
456  /// If the given Stmt is a CompoundStmt, this method will also generate
457  /// hashes for all possible StmtSequences in the children of this Stmt.
458  size_t saveHash(const Stmt *S, const Decl *D,
459  std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash);
460 
461 public:
462  void constrain(std::vector<CloneDetector::CloneGroup> &Sequences);
463 };
464 
465 /// Ensures that every clone has at least the given complexity.
466 ///
467 /// Complexity is here defined as the total amount of children of a statement.
468 /// This constraint assumes the first statement in the group is representative
469 /// for all other statements in the group in terms of complexity.
471  unsigned MinComplexity;
472 
473 public:
474  MinComplexityConstraint(unsigned MinComplexity)
475  : MinComplexity(MinComplexity) {}
476 
477  size_t calculateStmtComplexity(const StmtSequence &Seq,
478  const std::string &ParentMacroStack = "");
479 
480  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
482  CloneGroups, [this](const CloneDetector::CloneGroup &A) {
483  if (!A.empty())
484  return calculateStmtComplexity(A.front()) < MinComplexity;
485  else
486  return false;
487  });
488  }
489 };
490 
491 /// Ensures that all clone groups contain at least the given amount of clones.
493  unsigned MinGroupSize;
494 
495 public:
496  MinGroupSizeConstraint(unsigned MinGroupSize = 2)
497  : MinGroupSize(MinGroupSize) {}
498 
499  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
500  CloneConstraint::filterGroups(CloneGroups,
501  [this](const CloneDetector::CloneGroup &A) {
502  return A.size() < MinGroupSize;
503  });
504  }
505 };
506 
507 /// Ensures that no clone group fully contains another clone group.
509  void constrain(std::vector<CloneDetector::CloneGroup> &Result);
510 };
511 
514  std::shared_ptr<llvm::Regex> IgnoredFilesRegex;
515 
516  FilenamePatternConstraint(StringRef IgnoredFilesPattern)
517  : IgnoredFilesPattern(IgnoredFilesPattern) {
518  IgnoredFilesRegex = std::make_shared<llvm::Regex>("^(" +
519  IgnoredFilesPattern.str() + "$)");
520  }
521 
522  bool isAutoGenerated(const CloneDetector::CloneGroup &Group);
523 
524  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
526  CloneGroups, [this](const CloneDetector::CloneGroup &Group) {
527  return isAutoGenerated(Group);
528  });
529  }
530 };
531 
532 /// Analyzes the pattern of the referenced variables in a statement.
534 
535  /// Describes an occurence of a variable reference in a statement.
536  struct VariableOccurence {
537  /// The index of the associated VarDecl in the Variables vector.
538  size_t KindID;
539  /// The statement in the code where the variable was referenced.
540  const Stmt *Mention;
541 
542  VariableOccurence(size_t KindID, const Stmt *Mention)
543  : KindID(KindID), Mention(Mention) {}
544  };
545 
546  /// All occurences of referenced variables in the order of appearance.
547  std::vector<VariableOccurence> Occurences;
548  /// List of referenced variables in the order of appearance.
549  /// Every item in this list is unique.
550  std::vector<const VarDecl *> Variables;
551 
552  /// Adds a new variable referenced to this pattern.
553  /// \param VarDecl The declaration of the variable that is referenced.
554  /// \param Mention The SourceRange where this variable is referenced.
555  void addVariableOccurence(const VarDecl *VarDecl, const Stmt *Mention);
556 
557  /// Adds each referenced variable from the given statement.
558  void addVariables(const Stmt *S);
559 
560 public:
561  /// Creates an VariablePattern object with information about the given
562  /// StmtSequence.
563  VariablePattern(const StmtSequence &Sequence) {
564  for (const Stmt *S : Sequence)
565  addVariables(S);
566  }
567 
568  /// Describes two clones that reference their variables in a different pattern
569  /// which could indicate a programming error.
571  /// Utility class holding the relevant information about a single
572  /// clone in this pair.
574  /// The variable which referencing in this clone was against the pattern.
575  const VarDecl *Variable;
576  /// Where the variable was referenced.
577  const Stmt *Mention;
578  /// The variable that should have been referenced to follow the pattern.
579  /// If Suggestion is a nullptr then it's not possible to fix the pattern
580  /// by referencing a different variable in this clone.
581  const VarDecl *Suggestion;
582  SuspiciousCloneInfo(const VarDecl *Variable, const Stmt *Mention,
583  const VarDecl *Suggestion)
584  : Variable(Variable), Mention(Mention), Suggestion(Suggestion) {}
586  };
587  /// The first clone in the pair which always has a suggested variable.
589  /// This other clone in the pair which can have a suggested variable.
591  };
592 
593  /// Counts the differences between this pattern and the given one.
594  /// \param Other The given VariablePattern to compare with.
595  /// \param FirstMismatch Output parameter that will be filled with information
596  /// about the first difference between the two patterns. This parameter
597  /// can be a nullptr, in which case it will be ignored.
598  /// \return Returns the number of differences between the pattern this object
599  /// is following and the given VariablePattern.
600  ///
601  /// For example, the following statements all have the same pattern and this
602  /// function would return zero:
603  ///
604  /// if (a < b) return a; return b;
605  /// if (x < y) return x; return y;
606  /// if (u2 < u1) return u2; return u1;
607  ///
608  /// But the following statement has a different pattern (note the changed
609  /// variables in the return statements) and would have two differences when
610  /// compared with one of the statements above.
611  ///
612  /// if (a < b) return b; return a;
613  ///
614  /// This function should only be called if the related statements of the given
615  /// pattern and the statements of this objects are clones of each other.
616  unsigned countPatternDifferences(
617  const VariablePattern &Other,
618  VariablePattern::SuspiciousClonePair *FirstMismatch = nullptr);
619 };
620 
621 /// Ensures that all clones reference variables in the same pattern.
623  void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups);
624 };
625 
626 } // end namespace clang
627 
628 #endif // LLVM_CLANG_AST_CLONEDETECTION_H
FilenamePatternConstraint(StringRef IgnoredFilesPattern)
const Stmt * front() const
Returns the first statement in this sequence.
A (possibly-)qualified type.
Definition: Type.h:616
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:187
Stmt - This represents one statement.
Definition: Stmt.h:60
Analyzes the pattern of the referenced variables in a statement.
bool operator==(const StmtSequence &Other) const
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
static void filterGroups(std::vector< CloneDetector::CloneGroup > &CloneGroups, std::function< bool(const CloneDetector::CloneGroup &)> Filter)
Removes all groups by using a filter function.
Defines the C++ template declaration subclasses.
bool empty() const
Returns true if and only if this StmtSequence contains no statements.
std::string getAsString() const
Definition: Type.h:942
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
void constrain(std::vector< CloneDetector::CloneGroup > &CloneGroups)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:758
Searches all children of the given clones for type II clones (i.e.
std::string getMacroStack(SourceLocation Loc, ASTContext &Context)
Returns a string that represents all macro expansions that expanded into the given SourceLocation...
SuspiciousCloneInfo(const VarDecl *Variable, const Stmt *Mention, const VarDecl *Suggestion)
const Stmt * back() const
Returns the last statement in this sequence.
Identifies a list of statements.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:128
This class is a utility class that contains utility functions for building custom constraints...
Ensures that all clones reference variables in the same pattern.
Ensures that all clone groups contain at least the given amount of clones.
static void constrainClones(std::vector< CloneGroup > &CloneGroups, T C)
Constrains the given list of clone groups with the given constraint.
void findClones(std::vector< CloneGroup > &Result, Ts...ConstraintList)
Searches for clones in all previously passed statements.
const LangOptions & getLangOpts() const
Definition: ASTContext.h:659
VariablePattern(const StmtSequence &Sequence)
Creates an VariablePattern object with information about the given StmtSequence.
Searches for similar subtrees in the AST.
void constrain(std::vector< CloneDetector::CloneGroup > &CloneGroups)
Describes two clones that reference their variables in a different pattern which could indicate a pro...
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:575
llvm::SmallVector< StmtSequence, 8 > CloneGroup
A collection of StmtSequences that share an arbitrary property.
ASTContext * Context
SuspiciousCloneInfo SecondCloneInfo
This other clone in the pair which can have a suggested variable.
Ensures that every clone has at least the given complexity.
const VarDecl * Suggestion
The variable that should have been referenced to follow the pattern.
std::shared_ptr< llvm::Regex > IgnoredFilesRegex
Utility class holding the relevant information about a single clone in this pair. ...
const Stmt * Mention
Where the variable was referenced.
MinComplexityConstraint(unsigned MinComplexity)
Encodes a location in the source.
const Stmt *const * iterator
void constrain(std::vector< CloneDetector::CloneGroup > &CloneGroups)
SourceRange getSourceRange(const SourceRange &Range)
Returns the SourceRange of a SourceRange.
Definition: FixIt.h:34
const Decl * getContainingDecl() const
Returns the declaration that contains the stored Stmts.
bool holdsSequence() const
Returns true if this objects holds a list of statements.
MinGroupSizeConstraint(unsigned MinGroupSize=2)
unsigned size() const
Returns the number of statements this object holds.
bool operator!=(const StmtSequence &Other) const
DEF_ADD_DATA(Stmt,{addData(S->getStmtClass());addData(getMacroStack(S->getLocStart(), Context));addData(getMacroStack(S->getLocEnd(), Context));}) DEF_ADD_DATA(Expr
static void constrainClones(std::vector< CloneGroup > &CloneGroups, T1 C, Ts...ConstraintList)
Constrains the given list of clone groups with the given list of constraints.
Defines the clang::SourceLocation class and associated facilities.
StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer)
Collects data of the given Stmt.
SuspiciousCloneInfo FirstCloneInfo
The first clone in the pair which always has a suggested variable.
A trivial tuple used to represent a source range.
const VarDecl * Variable
The variable which referencing in this clone was against the pattern.
Collects the data of a single Stmt.
const NamedDecl * Result
Definition: USRFinder.cpp:70
Ensures that no clone group fully contains another clone group.