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