r279366 - [analyzer] Make CloneDetector consider template arguments.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 20 02:57:22 PDT 2016
Author: dergachev
Date: Sat Aug 20 04:57:21 2016
New Revision: 279366
URL: http://llvm.org/viewvc/llvm-project?rev=279366&view=rev
Log:
[analyzer] Make CloneDetector consider template arguments.
For example, code samples `isa<Stmt>(S)' and `isa<Expr>(S)'
are no longer considered to be clones.
Patch by Raphael Isemann!
Differential Revision: https://reviews.llvm.org/D23555
Modified:
cfe/trunk/lib/Analysis/CloneDetection.cpp
cfe/trunk/test/Analysis/copypaste/call.cpp
Modified: cfe/trunk/lib/Analysis/CloneDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CloneDetection.cpp?rev=279366&r1=279365&r2=279366&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CloneDetection.cpp (original)
+++ cfe/trunk/lib/Analysis/CloneDetection.cpp Sat Aug 20 04:57:21 2016
@@ -315,8 +315,26 @@ public:
//--- Calls --------------------------------------------------------------//
DEF_ADD_DATA(CallExpr, {
// Function pointers don't have a callee and we just skip hashing it.
- if (S->getDirectCallee())
- addData(S->getDirectCallee()->getQualifiedNameAsString());
+ if (const FunctionDecl *D = 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 (D->isTemplateInstantiation()) {
+ auto Args = D->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);
+ // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'.
+ OS << '\n';
+ }
+ OS.flush();
+
+ addData(ArgString);
+ }
+ addData(D->getQualifiedNameAsString());
+ }
})
//--- Exceptions ---------------------------------------------------------//
Modified: cfe/trunk/test/Analysis/copypaste/call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/copypaste/call.cpp?rev=279366&r1=279365&r2=279366&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/copypaste/call.cpp (original)
+++ cfe/trunk/test/Analysis/copypaste/call.cpp Sat Aug 20 04:57:21 2016
@@ -34,3 +34,57 @@ bool fooPtr1(int x) {
return funcPtr(1);
return true;
}
+
+// Test that we respect the template arguments of function templates
+
+template<typename T, unsigned N>
+bool templateFunc() { unsigned i = N; return false; }
+
+bool fooTemplate1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<int, 1>();
+ return true;
+}
+
+bool fooTemplate2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<long, 1>();
+ return true;
+}
+
+bool fooTemplate3(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templateFunc<long, 2>();
+ return true;
+}
+
+// Test that we don't just concatenate the template arguments into a string
+// without having any padding between them (e.g. foo<X, XX>() != foo<XX, X>()).
+
+class X {};
+class XX {};
+
+template<typename T1, typename T2>
+bool templatePaddingFunc() { return false; }
+
+bool fooTemplatePadding1(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templatePaddingFunc<X, XX>();
+ return true;
+}
+
+bool fooTemplatePadding2(int x) {
+ if (x > 0)
+ return false;
+ else if (x < 0)
+ return templatePaddingFunc<XX, X>();
+ return true;
+}
More information about the cfe-commits
mailing list