teemperor created this revision.
teemperor added reviewers: v.g.vassilev, NoQ.
teemperor added a subscriber: cfe-commits.

The CloneDetector currently ignores template arguments in function calls which 
leads to false-positive clones such as `isa<Expr>(S)` and `isa<Stmt>(S)`.

This patch adds functionality to handle template arguments for those function 
calls.

https://reviews.llvm.org/D23555

Files:
  lib/Analysis/CloneDetection.cpp
  test/Analysis/copypaste/call.cpp

Index: test/Analysis/copypaste/call.cpp
===================================================================
--- test/Analysis/copypaste/call.cpp
+++ test/Analysis/copypaste/call.cpp
@@ -34,3 +34,32 @@
     return funcPtr(1);
   return true;
 }
+
+// Test that we respect the template arguments of function templates
+
+template<typename T, unsigned N>
+bool tempFunc() { unsigned i = N; return false; }
+
+bool fooTemp1(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<int, 1>();
+  return true;
+}
+
+bool fooTemp2(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<long, 1>();
+  return true;
+}
+
+bool fooTemp3(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<long, 2>();
+  return true;
+}
Index: lib/Analysis/CloneDetection.cpp
===================================================================
--- lib/Analysis/CloneDetection.cpp
+++ lib/Analysis/CloneDetection.cpp
@@ -151,8 +151,24 @@
   //--- Calls --------------------------------------------------------------//
   DEF_ADD_DATA(CallExpr, {
     // Function pointers don't have a callee and we just skip hashing it.
-    if (S->getDirectCallee())
+    if (S->getDirectCallee()) {
+      // If the function is a template instantiation, we also need to handle
+      // the template arguments as they are no included in the qualified name.
+      if (S->getDirectCallee()->isTemplateInstantiation()) {
+        auto Args = S->getDirectCallee()->getTemplateSpecializationArgs();
+        std::string ArgString;
+
+        // Print all template arguments into ArgString
+        llvm::raw_string_ostream OS(ArgString);
+        for (unsigned i = 0; i < Args->size(); ++i) {
+          Args->get(i).print(Context.getLangOpts(), OS);
+        }
+        OS.flush();
+
+        addData(ArgString);
+      }
       addData(S->getDirectCallee()->getQualifiedNameAsString());
+    }
   })
 
   //--- Exceptions ---------------------------------------------------------//


Index: test/Analysis/copypaste/call.cpp
===================================================================
--- test/Analysis/copypaste/call.cpp
+++ test/Analysis/copypaste/call.cpp
@@ -34,3 +34,32 @@
     return funcPtr(1);
   return true;
 }
+
+// Test that we respect the template arguments of function templates
+
+template<typename T, unsigned N>
+bool tempFunc() { unsigned i = N; return false; }
+
+bool fooTemp1(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<int, 1>();
+  return true;
+}
+
+bool fooTemp2(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<long, 1>();
+  return true;
+}
+
+bool fooTemp3(int x) {
+  if (x > 0)
+    return false;
+  else if (x < 0)
+    return tempFunc<long, 2>();
+  return true;
+}
Index: lib/Analysis/CloneDetection.cpp
===================================================================
--- lib/Analysis/CloneDetection.cpp
+++ lib/Analysis/CloneDetection.cpp
@@ -151,8 +151,24 @@
   //--- Calls --------------------------------------------------------------//
   DEF_ADD_DATA(CallExpr, {
     // Function pointers don't have a callee and we just skip hashing it.
-    if (S->getDirectCallee())
+    if (S->getDirectCallee()) {
+      // If the function is a template instantiation, we also need to handle
+      // the template arguments as they are no included in the qualified name.
+      if (S->getDirectCallee()->isTemplateInstantiation()) {
+        auto Args = S->getDirectCallee()->getTemplateSpecializationArgs();
+        std::string ArgString;
+
+        // Print all template arguments into ArgString
+        llvm::raw_string_ostream OS(ArgString);
+        for (unsigned i = 0; i < Args->size(); ++i) {
+          Args->get(i).print(Context.getLangOpts(), OS);
+        }
+        OS.flush();
+
+        addData(ArgString);
+      }
       addData(S->getDirectCallee()->getQualifiedNameAsString());
+    }
   })
 
   //--- Exceptions ---------------------------------------------------------//
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to