1 //===--- CloneDetection.cpp - 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 ///  This file implements classes for searching and anlyzing source code clones.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/Analysis/CloneDetection.h"
15 
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/RecursiveASTVisitor.h"
18 #include "clang/AST/Stmt.h"
19 #include "clang/AST/StmtVisitor.h"
20 #include "llvm/ADT/StringRef.h"
21 
22 using namespace clang;
23 
24 StmtSequence::StmtSequence(const CompoundStmt *Stmt, ASTContext &Context,
25                            unsigned StartIndex, unsigned EndIndex)
26     : S(Stmt), Context(&Context), StartIndex(StartIndex), EndIndex(EndIndex) {
27   assert(Stmt && "Stmt must not be a nullptr");
28   assert(StartIndex < EndIndex && "Given array should not be empty");
29   assert(EndIndex <= Stmt->size() && "Given array too big for this Stmt");
30 }
31 
32 StmtSequence::StmtSequence(const Stmt *Stmt, ASTContext &Context)
33     : S(Stmt), Context(&Context), StartIndex(0), EndIndex(0) {}
34 
35 StmtSequence::StmtSequence()
36     : S(nullptr), Context(nullptr), StartIndex(0), EndIndex(0) {}
37 
38 bool StmtSequence::contains(const StmtSequence &Other) const {
39   // If both sequences reside in different translation units, they can never
40   // contain each other.
41   if (Context != Other.Context)
42     return false;
43 
44   const SourceManager &SM = Context->getSourceManager();
45 
46   // Otherwise check if the start and end locations of the current sequence
47   // surround the other sequence.
48   bool StartIsInBounds =
49       SM.isBeforeInTranslationUnit(getStartLoc(), Other.getStartLoc()) ||
50       getStartLoc() == Other.getStartLoc();
51   if (!StartIsInBounds)
52     return false;
53 
54   bool EndIsInBounds =
55       SM.isBeforeInTranslationUnit(Other.getEndLoc(), getEndLoc()) ||
56       Other.getEndLoc() == getEndLoc();
57   return EndIsInBounds;
58 }
59 
60 StmtSequence::iterator StmtSequence::begin() const {
61   if (!holdsSequence()) {
62     return &S;
63   }
64   auto CS = cast<CompoundStmt>(S);
65   return CS->body_begin() + StartIndex;
66 }
67 
68 StmtSequence::iterator StmtSequence::end() const {
69   if (!holdsSequence()) {
70     return reinterpret_cast<StmtSequence::iterator>(&S) + 1;
71   }
72   auto CS = cast<CompoundStmt>(S);
73   return CS->body_begin() + EndIndex;
74 }
75 
76 SourceLocation StmtSequence::getStartLoc() const {
77   return front()->getLocStart();
78 }
79 
80 SourceLocation StmtSequence::getEndLoc() const { return back()->getLocEnd(); }
81 
82 namespace {
83 
84 /// \brief Analyzes the pattern of the referenced variables in a statement.
85 class VariablePattern {
86 
87   /// \brief Describes an occurence of a variable reference in a statement.
88   struct VariableOccurence {
89     /// The index of the associated VarDecl in the Variables vector.
90     size_t KindID;
91 
92     VariableOccurence(size_t KindID) : KindID(KindID) {}
93   };
94 
95   /// All occurences of referenced variables in the order of appearance.
96   std::vector<VariableOccurence> Occurences;
97   /// List of referenced variables in the order of appearance.
98   /// Every item in this list is unique.
99   std::vector<const VarDecl *> Variables;
100 
101   /// \brief Adds a new variable referenced to this pattern.
102   /// \param VarDecl The declaration of the variable that is referenced.
103   void addVariableOccurence(const VarDecl *VarDecl) {
104     // First check if we already reference this variable
105     for (size_t KindIndex = 0; KindIndex < Variables.size(); ++KindIndex) {
106       if (Variables[KindIndex] == VarDecl) {
107         // If yes, add a new occurence that points to the existing entry in
108         // the Variables vector.
109         Occurences.emplace_back(KindIndex);
110         return;
111       }
112     }
113     // If this variable wasn't already referenced, add it to the list of
114     // referenced variables and add a occurence that points to this new entry.
115     Occurences.emplace_back(Variables.size());
116     Variables.push_back(VarDecl);
117   }
118 
119   /// \brief Adds each referenced variable from the given statement.
120   void addVariables(const Stmt *S) {
121     // Sometimes we get a nullptr (such as from IfStmts which often have nullptr
122     // children). We skip such statements as they don't reference any
123     // variables.
124     if (!S)
125       return;
126 
127     // Check if S is a reference to a variable. If yes, add it to the pattern.
128     if (auto D = dyn_cast<DeclRefExpr>(S)) {
129       if (auto VD = dyn_cast<VarDecl>(D->getDecl()->getCanonicalDecl()))
130         addVariableOccurence(VD);
131     }
132 
133     // Recursively check all children of the given statement.
134     for (const Stmt *Child : S->children()) {
135       addVariables(Child);
136     }
137   }
138 
139 public:
140   /// \brief Creates an VariablePattern object with information about the given
141   ///        StmtSequence.
142   VariablePattern(const StmtSequence &Sequence) {
143     for (const Stmt *S : Sequence)
144       addVariables(S);
145   }
146 
147   /// \brief Compares this pattern with the given one.
148   /// \param Other The given VariablePattern to compare with.
149   /// \return Returns true if and only if the references variables in this
150   ///         object follow the same pattern than the ones in the given
151   ///         VariablePattern.
152   ///
153   /// For example, the following statements all have the same pattern:
154   ///
155   ///   if (a < b) return a; return b;
156   ///   if (x < y) return x; return y;
157   ///   if (u2 < u1) return u2; return u1;
158   ///
159   /// but the following statement has a different pattern (note the changed
160   /// variables in the return statements).
161   ///
162   ///   if (a < b) return b; return a;
163   ///
164   /// This function should only be called if the related statements of the given
165   /// pattern and the statements of this objects are clones of each other.
166   bool comparePattern(const VariablePattern &Other) {
167     assert(Other.Occurences.size() == Occurences.size());
168     for (unsigned i = 0; i < Occurences.size(); ++i) {
169       if (Occurences[i].KindID != Other.Occurences[i].KindID) {
170         return false;
171       }
172     }
173     return true;
174   }
175 };
176 }
177 
178 namespace {
179 /// \brief Collects the data of a single Stmt.
180 ///
181 /// This class defines what a code clone is: If it collects for two statements
182 /// the same data, then those two statements are considered to be clones of each
183 /// other.
184 class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector> {
185 
186   ASTContext &Context;
187   std::vector<CloneDetector::DataPiece> &CollectedData;
188 
189 public:
190   /// \brief Collects data of the given Stmt.
191   /// \param S The given statement.
192   /// \param Context The ASTContext of S.
193   /// \param D The given data vector to which all collected data is appended.
194   StmtDataCollector(const Stmt *S, ASTContext &Context,
195                     std::vector<CloneDetector::DataPiece> &D)
196       : Context(Context), CollectedData(D) {
197     Visit(S);
198   }
199 
200   // Below are utility methods for appending different data to the vector.
201 
202   void addData(CloneDetector::DataPiece Integer) {
203     CollectedData.push_back(Integer);
204   }
205 
206   // FIXME: The functions below add long strings to the data vector which are
207   // probably not good for performance. Replace the strings with pointer values
208   // or a some other unique integer.
209 
210   void addData(llvm::StringRef Str) {
211     if (Str.empty())
212       return;
213 
214     const size_t OldSize = CollectedData.size();
215 
216     const size_t PieceSize = sizeof(CloneDetector::DataPiece);
217     // Calculate how many vector units we need to accomodate all string bytes.
218     size_t RoundedUpPieceNumber = (Str.size() + PieceSize - 1) / PieceSize;
219     // Allocate space for the string in the data vector.
220     CollectedData.resize(CollectedData.size() + RoundedUpPieceNumber);
221 
222     // Copy the string to the allocated space at the end of the vector.
223     std::memcpy(CollectedData.data() + OldSize, Str.data(), Str.size());
224   }
225 
226   void addData(const QualType &QT) { addData(QT.getAsString()); }
227 
228 // The functions below collect the class specific data of each Stmt subclass.
229 
230 // Utility macro for defining a visit method for a given class. This method
231 // calls back to the ConstStmtVisitor to visit all parent classes.
232 #define DEF_ADD_DATA(CLASS, CODE)                                              \
233   void Visit##CLASS(const CLASS *S) {                                          \
234     CODE;                                                                      \
235     ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S);                      \
236   }
237 
238   DEF_ADD_DATA(Stmt, { addData(S->getStmtClass()); })
239   DEF_ADD_DATA(Expr, { addData(S->getType()); })
240 
241   //--- Builtin functionality ----------------------------------------------//
242   DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); })
243   DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); })
244   DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); })
245   DEF_ADD_DATA(TypeTraitExpr, {
246     addData(S->getTrait());
247     for (unsigned i = 0; i < S->getNumArgs(); ++i)
248       addData(S->getArg(i)->getType());
249   })
250 
251   //--- Calls --------------------------------------------------------------//
252   DEF_ADD_DATA(CallExpr, {
253     // Function pointers don't have a callee and we just skip hashing it.
254     if (S->getDirectCallee())
255       addData(S->getDirectCallee()->getQualifiedNameAsString());
256   })
257 
258   //--- Exceptions ---------------------------------------------------------//
259   DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); })
260 
261   //--- C++ OOP Stmts ------------------------------------------------------//
262   DEF_ADD_DATA(CXXDeleteExpr, {
263     addData(S->isArrayFormAsWritten());
264     addData(S->isGlobalDelete());
265   })
266 
267   //--- Casts --------------------------------------------------------------//
268   DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); })
269 
270   //--- Miscellaneous Exprs ------------------------------------------------//
271   DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); })
272   DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); })
273 
274   //--- Control flow -------------------------------------------------------//
275   DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); })
276   DEF_ADD_DATA(IndirectGotoStmt, {
277     if (S->getConstantTarget())
278       addData(S->getConstantTarget()->getName());
279   })
280   DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); })
281   DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); })
282   DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); })
283 
284   //--- Objective-C --------------------------------------------------------//
285   DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); })
286   DEF_ADD_DATA(ObjCPropertyRefExpr, {
287     addData(S->isSuperReceiver());
288     addData(S->isImplicitProperty());
289   })
290   DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); })
291 
292   //--- Miscellaneous Stmts ------------------------------------------------//
293   DEF_ADD_DATA(CXXFoldExpr, {
294     addData(S->isRightFold());
295     addData(S->getOperator());
296   })
297   DEF_ADD_DATA(GenericSelectionExpr, {
298     for (unsigned i = 0; i < S->getNumAssocs(); ++i) {
299       addData(S->getAssocType(i));
300     }
301   })
302   DEF_ADD_DATA(LambdaExpr, {
303     for (const LambdaCapture &C : S->captures()) {
304       addData(C.isPackExpansion());
305       addData(C.getCaptureKind());
306       if (C.capturesVariable())
307         addData(C.getCapturedVar()->getType());
308     }
309     addData(S->isGenericLambda());
310     addData(S->isMutable());
311   })
312   DEF_ADD_DATA(DeclStmt, {
313     auto numDecls = std::distance(S->decl_begin(), S->decl_end());
314     addData(static_cast<CloneDetector::DataPiece>(numDecls));
315     for (const Decl *D : S->decls()) {
316       if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
317         addData(VD->getType());
318       }
319     }
320   })
321   DEF_ADD_DATA(AsmStmt, {
322     addData(S->isSimple());
323     addData(S->isVolatile());
324     addData(S->generateAsmString(Context));
325     for (unsigned i = 0; i < S->getNumInputs(); ++i) {
326       addData(S->getInputConstraint(i));
327     }
328     for (unsigned i = 0; i < S->getNumOutputs(); ++i) {
329       addData(S->getOutputConstraint(i));
330     }
331     for (unsigned i = 0; i < S->getNumClobbers(); ++i) {
332       addData(S->getClobber(i));
333     }
334   })
335   DEF_ADD_DATA(AttributedStmt, {
336     for (const Attr *A : S->getAttrs()) {
337       addData(std::string(A->getSpelling()));
338     }
339   })
340 };
341 } // end anonymous namespace
342 
343 namespace {
344 /// Generates CloneSignatures for a set of statements and stores the results in
345 /// a CloneDetector object.
346 class CloneSignatureGenerator {
347 
348   CloneDetector &CD;
349   ASTContext &Context;
350 
351   /// \brief Generates CloneSignatures for all statements in the given statement
352   /// tree and stores them in the CloneDetector.
353   ///
354   /// \param S The root of the given statement tree.
355   /// \return The CloneSignature of the root statement.
356   CloneDetector::CloneSignature generateSignatures(const Stmt *S) {
357     // Create an empty signature that will be filled in this method.
358     CloneDetector::CloneSignature Signature;
359 
360     // Collect all relevant data from S and put it into the empty signature.
361     StmtDataCollector(S, Context, Signature.Data);
362 
363     // Storage for the signatures of the direct child statements. This is only
364     // needed if the current statement is a CompoundStmt.
365     std::vector<CloneDetector::CloneSignature> ChildSignatures;
366     const CompoundStmt *CS = dyn_cast<const CompoundStmt>(S);
367 
368     // The signature of a statement includes the signatures of its children.
369     // Therefore we create the signatures for every child and add them to the
370     // current signature.
371     for (const Stmt *Child : S->children()) {
372       // Some statements like 'if' can have nullptr children that we will skip.
373       if (!Child)
374         continue;
375 
376       // Recursive call to create the signature of the child statement. This
377       // will also create and store all clone groups in this child statement.
378       auto ChildSignature = generateSignatures(Child);
379 
380       // Add the collected data to the signature of the current statement.
381       Signature.add(ChildSignature);
382 
383       // If the current statement is a CompoundStatement, we need to store the
384       // signature for the generation of the sub-sequences.
385       if (CS)
386         ChildSignatures.push_back(ChildSignature);
387     }
388 
389     // If the current statement is a CompoundStmt, we also need to create the
390     // clone groups from the sub-sequences inside the children.
391     if (CS)
392       handleSubSequences(CS, ChildSignatures);
393 
394     // Save the signature for the current statement in the CloneDetector object.
395     CD.add(StmtSequence(S, Context), Signature);
396 
397     return Signature;
398   }
399 
400   /// \brief Adds all possible sub-sequences in the child array of the given
401   ///        CompoundStmt to the CloneDetector.
402   /// \param CS The given CompoundStmt.
403   /// \param ChildSignatures A list of calculated signatures for each child in
404   ///                        the given CompoundStmt.
405   void handleSubSequences(
406       const CompoundStmt *CS,
407       const std::vector<CloneDetector::CloneSignature> &ChildSignatures) {
408 
409     // FIXME: This function has quadratic runtime right now. Check if skipping
410     // this function for too long CompoundStmts is an option.
411 
412     // The length of the sub-sequence. We don't need to handle sequences with
413     // the length 1 as they are already handled in CollectData().
414     for (unsigned Length = 2; Length <= CS->size(); ++Length) {
415       // The start index in the body of the CompoundStmt. We increase the
416       // position until the end of the sub-sequence reaches the end of the
417       // CompoundStmt body.
418       for (unsigned Pos = 0; Pos <= CS->size() - Length; ++Pos) {
419         // Create an empty signature and add the signatures of all selected
420         // child statements to it.
421         CloneDetector::CloneSignature SubSignature;
422 
423         for (unsigned i = Pos; i < Pos + Length; ++i) {
424           SubSignature.add(ChildSignatures[i]);
425         }
426 
427         // Save the signature together with the information about what children
428         // sequence we selected.
429         CD.add(StmtSequence(CS, Context, Pos, Pos + Length), SubSignature);
430       }
431     }
432   }
433 
434 public:
435   explicit CloneSignatureGenerator(CloneDetector &CD, ASTContext &Context)
436       : CD(CD), Context(Context) {}
437 
438   /// \brief Generates signatures for all statements in the given function body.
439   void consumeCodeBody(const Stmt *S) { generateSignatures(S); }
440 };
441 } // end anonymous namespace
442 
443 void CloneDetector::analyzeCodeBody(const Decl *D) {
444   assert(D);
445   assert(D->hasBody());
446   CloneSignatureGenerator Generator(*this, D->getASTContext());
447   Generator.consumeCodeBody(D->getBody());
448 }
449 
450 void CloneDetector::add(const StmtSequence &S,
451                         const CloneSignature &Signature) {
452   // StringMap only works with StringRefs, so we create one for our data vector.
453   auto &Data = Signature.Data;
454   StringRef DataRef = StringRef(reinterpret_cast<const char *>(Data.data()),
455                                 Data.size() * sizeof(unsigned));
456 
457   // Search with the help of the signature if we already have encountered a
458   // clone of the given StmtSequence.
459   auto I = CloneGroupIndexes.find(DataRef);
460   if (I == CloneGroupIndexes.end()) {
461     // We haven't found an existing clone group, so we create a new clone group
462     // for this StmtSequence and store the index of it in our search map.
463     CloneGroupIndexes[DataRef] = CloneGroups.size();
464     CloneGroups.emplace_back(S, Signature.Complexity);
465     return;
466   }
467 
468   // We have found an existing clone group and can expand it with the given
469   // StmtSequence.
470   CloneGroups[I->getValue()].Sequences.push_back(S);
471 }
472 
473 namespace {
474 /// \brief Returns true if and only if \p Stmt contains at least one other
475 /// sequence in the \p Group.
476 bool containsAnyInGroup(StmtSequence &Stmt, CloneDetector::CloneGroup &Group) {
477   for (StmtSequence &GroupStmt : Group.Sequences) {
478     if (Stmt.contains(GroupStmt))
479       return true;
480   }
481   return false;
482 }
483 
484 /// \brief Returns true if and only if all sequences in \p OtherGroup are
485 /// contained by a sequence in \p Group.
486 bool containsGroup(CloneDetector::CloneGroup &Group,
487                    CloneDetector::CloneGroup &OtherGroup) {
488   // We have less sequences in the current group than we have in the other,
489   // so we will never fulfill the requirement for returning true. This is only
490   // possible because we know that a sequence in Group can contain at most
491   // one sequence in OtherGroup.
492   if (Group.Sequences.size() < OtherGroup.Sequences.size())
493     return false;
494 
495   for (StmtSequence &Stmt : Group.Sequences) {
496     if (!containsAnyInGroup(Stmt, OtherGroup))
497       return false;
498   }
499   return true;
500 }
501 } // end anonymous namespace
502 
503 /// \brief Finds all actual clone groups in a single group of presumed clones.
504 /// \param Result Output parameter to which all found groups are added. Every
505 ///               clone in a group that was added this way follows the same
506 ///               variable pattern as the other clones in its group.
507 /// \param Group A group of clones. The clones are allowed to have a different
508 ///              variable pattern.
509 static void createCloneGroups(std::vector<CloneDetector::CloneGroup> &Result,
510                               const CloneDetector::CloneGroup &Group) {
511   // We remove the Sequences one by one, so a list is more appropriate.
512   std::list<StmtSequence> UnassignedSequences(Group.Sequences.begin(),
513                                               Group.Sequences.end());
514 
515   // Search for clones as long as there could be clones in UnassignedSequences.
516   while (UnassignedSequences.size() > 1) {
517 
518     // Pick the first Sequence as a protoype for a new clone group.
519     StmtSequence Prototype = UnassignedSequences.front();
520     UnassignedSequences.pop_front();
521 
522     CloneDetector::CloneGroup FilteredGroup(Prototype, Group.Complexity);
523 
524     // Analyze the variable pattern of the prototype. Every other StmtSequence
525     // needs to have the same pattern to get into the new clone group.
526     VariablePattern PrototypeFeatures(Prototype);
527 
528     // Search all remaining StmtSequences for an identical variable pattern
529     // and assign them to our new clone group.
530     auto I = UnassignedSequences.begin(), E = UnassignedSequences.end();
531     while (I != E) {
532       if (VariablePattern(*I).comparePattern(PrototypeFeatures)) {
533         FilteredGroup.Sequences.push_back(*I);
534         I = UnassignedSequences.erase(I);
535         continue;
536       }
537       ++I;
538     }
539 
540     // Add a valid clone group to the list of found clone groups.
541     if (!FilteredGroup.isValid())
542       continue;
543 
544     Result.push_back(FilteredGroup);
545   }
546 }
547 
548 void CloneDetector::findClones(std::vector<CloneGroup> &Result,
549                                unsigned MinGroupComplexity) {
550   // Add every valid clone group that fulfills the complexity requirement.
551   for (const CloneGroup &Group : CloneGroups) {
552     if (Group.isValid() && Group.Complexity >= MinGroupComplexity) {
553       createCloneGroups(Result, Group);
554     }
555   }
556 
557   std::vector<unsigned> IndexesToRemove;
558 
559   // Compare every group in the result with the rest. If one groups contains
560   // another group, we only need to return the bigger group.
561   // Note: This doesn't scale well, so if possible avoid calling any heavy
562   // function from this loop to minimize the performance impact.
563   for (unsigned i = 0; i < Result.size(); ++i) {
564     for (unsigned j = 0; j < Result.size(); ++j) {
565       // Don't compare a group with itself.
566       if (i == j)
567         continue;
568 
569       if (containsGroup(Result[j], Result[i])) {
570         IndexesToRemove.push_back(i);
571         break;
572       }
573     }
574   }
575 
576   // Erasing a list of indexes from the vector should be done with decreasing
577   // indexes. As IndexesToRemove is constructed with increasing values, we just
578   // reverse iterate over it to get the desired order.
579   for (auto I = IndexesToRemove.rbegin(); I != IndexesToRemove.rend(); ++I) {
580     Result.erase(Result.begin() + *I);
581   }
582 }
583