15 #ifndef LLVM_CLANG_AST_CLONEDETECTION_H
16 #define LLVM_CLANG_AST_CLONEDETECTION_H
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/Regex.h"
34 namespace clone_detection {
65 : Context(Context), DataConsumer(DataConsumer) {
75 StringRef(reinterpret_cast<char *>(&Integer),
sizeof(Integer)));
78 void addData(llvm::StringRef Str) { DataConsumer.update(Str); }
86 #define DEF_ADD_DATA(CLASS, CODE) \
87 void Visit##CLASS(const CLASS *S) { \
89 ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \
107 for (
unsigned i = 0; i <
S->getNumArgs(); ++i)
114 if (
const FunctionDecl *D =
S->getDirectCallee()) {
117 if (
auto Args = D->getTemplateSpecializationArgs()) {
118 std::string ArgString;
121 llvm::raw_string_ostream OS(ArgString);
122 for (
unsigned i = 0; i < Args->size(); ++i) {
131 addData(D->getQualifiedNameAsString());
154 if (
S->getConstantTarget())
155 addData(
S->getConstantTarget()->getName());
175 for (
unsigned i = 0; i <
S->getNumAssocs(); ++i) {
180 for (
const LambdaCapture &C :
S->captures()) {
183 if (
C.capturesVariable())
184 addData(
C.getCapturedVar()->getType());
191 addData(static_cast<DataPiece>(numDecls));
192 for (
const Decl *D :
S->decls()) {
193 if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
201 addData(
S->generateAsmString(Context));
202 for (
unsigned i = 0; i <
S->getNumInputs(); ++i) {
205 for (
unsigned i = 0; i <
S->getNumOutputs(); ++i) {
208 for (
unsigned i = 0; i <
S->getNumClobbers(); ++i) {
213 for (
const Attr *A :
S->getAttrs()) {
214 addData(std::string(A->getSpelling()));
285 return begin()[size() - 1];
291 return EndIndex - StartIndex;
298 bool empty()
const {
return size() == 0; }
327 return std::tie(
S, StartIndex, EndIndex) ==
328 std::tie(Other.S, Other.StartIndex, Other.EndIndex);
332 return std::tie(
S, StartIndex, EndIndex) !=
333 std::tie(Other.S, Other.StartIndex, Other.EndIndex);
365 void analyzeCodeBody(
const Decl *D);
375 template <
typename T>
377 C.constrain(CloneGroups);
385 template <
typename T1,
typename... Ts>
387 Ts... ConstraintList) {
388 constrainClones(CloneGroups, C);
389 constrainClones(CloneGroups, ConstraintList...);
397 template <
typename... Ts>
398 void findClones(std::vector<CloneGroup> &Result, Ts... ConstraintList) {
403 AllClones.reserve(Sequences.size());
404 for (
const auto &C : Sequences) {
405 AllClones.push_back(C);
408 Result.push_back(AllClones);
410 constrainClones(Result, ConstraintList...);
414 CloneGroup Sequences;
430 std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter),
440 static void splitCloneGroups(
441 std::vector<CloneDetector::CloneGroup> &CloneGroups,
458 size_t saveHash(
const Stmt *
S,
const Decl *D,
459 std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash);
462 void constrain(std::vector<CloneDetector::CloneGroup> &Sequences);
471 unsigned MinComplexity;
475 : MinComplexity(MinComplexity) {}
478 const std::string &ParentMacroStack =
"");
480 void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
484 return calculateStmtComplexity(A.front()) < MinComplexity;
493 unsigned MinGroupSize;
497 : MinGroupSize(MinGroupSize) {}
499 void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
502 return A.size() < MinGroupSize;
509 void constrain(std::vector<CloneDetector::CloneGroup> &
Result);
517 : IgnoredFilesPattern(IgnoredFilesPattern) {
518 IgnoredFilesRegex = std::make_shared<llvm::Regex>(
"^(" +
519 IgnoredFilesPattern.str() +
"$)");
524 void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) {
527 return isAutoGenerated(Group);
536 struct VariableOccurence {
542 VariableOccurence(
size_t KindID,
const Stmt *Mention)
543 : KindID(KindID), Mention(Mention) {}
547 std::vector<VariableOccurence> Occurences;
550 std::vector<const VarDecl *> Variables;
558 void addVariables(
const Stmt *
S);
564 for (
const Stmt *S : Sequence)
583 const VarDecl *Suggestion)
584 : Variable(Variable), Mention(Mention), Suggestion(Suggestion) {}
616 unsigned countPatternDifferences(
623 void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups);
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.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
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.
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
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...
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...
void addData(llvm::StringRef Str)
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 ...
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
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 }.
llvm::SmallVector< StmtSequence, 8 > CloneGroup
A collection of StmtSequences that share an arbitrary property.
SuspiciousCloneInfo SecondCloneInfo
This other clone in the pair which can have a suggested variable.
void addData(DataPiece Integer)
StringRef IgnoredFilesPattern
Ensures that every clone has at least the given complexity.
const VarDecl * Suggestion
The variable that should have been referenced to follow the pattern.
void addData(const QualType &QT)
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)
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.
Ensures that no clone group fully contains another clone group.