r333275 - [analyzer] Added template argument lists to the Pathdiagnostic output

Kristof Umann via cfe-commits cfe-commits at lists.llvm.org
Fri May 25 06:18:38 PDT 2018


Author: szelethus
Date: Fri May 25 06:18:38 2018
New Revision: 333275

URL: http://llvm.org/viewvc/llvm-project?rev=333275&view=rev
Log:
[analyzer] Added template argument lists to the Pathdiagnostic output

Because template parameter lists were not displayed
in the plist output, it was difficult to decide in
some cases whether a given checker found a true or a
false positive. This patch aims to correct this.

Differential Revision: https://reviews.llvm.org/D46933

Added:
    cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp
    cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp
Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=333275&r1=333274&r2=333275&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Fri May 25 06:18:38 2018
@@ -16,6 +16,7 @@
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/OperationKinds.h"
@@ -1000,11 +1001,49 @@ void PathDiagnosticCallPiece::setCallee(
         CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
 }
 
+static void describeTemplateParameters(raw_ostream &Out,
+                                       const ArrayRef<TemplateArgument> TAList,
+                                       const LangOptions &LO,
+                                       StringRef Prefix = StringRef(),
+                                       StringRef Postfix = StringRef());
+
+static void describeTemplateParameter(raw_ostream &Out,
+                                      const TemplateArgument &TArg,
+                                      const LangOptions &LO) {
+
+  if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
+    describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
+  } else {
+    TArg.print(PrintingPolicy(LO), Out);
+  }
+}
+
+static void describeTemplateParameters(raw_ostream &Out,
+                                       const ArrayRef<TemplateArgument> TAList,
+                                       const LangOptions &LO,
+                                       StringRef Prefix, StringRef Postfix) {
+  if (TAList.empty())
+    return;
+
+  Out << Prefix;
+  for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
+    describeTemplateParameter(Out, TAList[I], LO);
+    Out << ", ";
+  }
+  describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
+  Out << Postfix;
+}
+
 static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
                           StringRef Prefix = StringRef()) {
   if (!D->getIdentifier())
     return;
-  Out << Prefix << '\'' << *D << '\'';
+  Out << Prefix << '\'' << *D;
+  if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
+    describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
+                               D->getASTContext().getLangOpts(), "<", ">");
+
+  Out << '\'';
 }
 
 static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
@@ -1062,7 +1101,16 @@ static bool describeCodeDecl(raw_ostream
     return true;
   }
 
-  Out << Prefix << '\'' << cast<NamedDecl>(*D) << '\'';
+  Out << Prefix << '\'' << cast<NamedDecl>(*D);
+
+  // Adding template parameters.
+  if (const auto FD = dyn_cast<FunctionDecl>(D))
+    if (const TemplateArgumentList *TAList =
+                                    FD->getTemplateSpecializationArgs())
+      describeTemplateParameters(Out, TAList->asArray(),
+                                 FD->getASTContext().getLangOpts(), "<", ">");
+
+  Out << '\'';
   return true;
 }
 

Added: cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp?rev=333275&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp (added)
+++ cfe/trunk/test/Analysis/plist-diagnostics-template-function.cpp Fri May 25 06:18:38 2018
@@ -0,0 +1,41 @@
+// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=core %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+bool ret();
+
+template <class T>
+void f(int i) {
+  if (ret())
+    i = i / (i - 5);
+}
+
+template <>
+void f<int>(int i) {
+  if (ret())
+    i = i / (i - 5);
+}
+
+template <int N = 0>
+void defaultTemplateParameterFunction(int i) {
+  if (ret())
+    int a = 10 / i;
+}
+
+template <typename... Args>
+void variadicTemplateFunction(int i) {
+  if (ret())
+    int a = 10 / i;
+}
+
+int main() {
+  f<int>(5);
+  f<float>(5);
+  defaultTemplateParameterFunction<>(0);
+  variadicTemplateFunction<char, float, double, int *>(0);
+}
+
+// CHECK:      <string>Calling 'f<float>'</string>
+// CHECK:      <string>Calling 'f<int>'</string>
+// CHECK:      <string>Calling 'defaultTemplateParameterFunction<0>'</string>
+// CHECK:      <string>Calling 'variadicTemplateFunction<char, float, double, int *>'</string>
+

Added: cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp?rev=333275&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp (added)
+++ cfe/trunk/test/Analysis/plist-diagnostics-template-record.cpp Fri May 25 06:18:38 2018
@@ -0,0 +1,42 @@
+// RUN: %clang_analyze_cc1 -analyzer-output=plist -o %t.plist -std=c++11 -analyzer-checker=core %s
+// RUN: FileCheck --input-file=%t.plist %s
+
+bool ret();
+
+template <class A, class B, class C, int N>
+struct DivByZero {
+  int i;
+  DivByZero(bool b) {
+    if (ret())
+      i = 50 / (b - 1);
+  }
+};
+
+template <class B, class C, int N>
+struct DivByZero<char, B, C, N> {
+  int i;
+  DivByZero(bool b) {
+    if (ret())
+      i = 50 / (b - 1);
+  }
+};
+
+template <typename... Args>
+struct DivByZeroVariadic {
+  int i;
+  DivByZeroVariadic(bool b) {
+    if (ret())
+      i = 50 / (b - 1);
+  }
+};
+
+int main() {
+  DivByZero<int, float, double, 0> a(1);
+  DivByZero<char, float, double, 0> a2(1);
+  DivByZeroVariadic<char, float, double, decltype(nullptr)> a3(1);
+}
+
+// CHECK:      <string>Calling constructor for 'DivByZero<int, float, double, 0>'</string>
+// CHECK:      <string>Calling constructor for 'DivByZero<char, float, double, 0>'</string>
+// CHECK:      <string>Calling constructor for 'DivByZeroVariadic<char, float, double, nullptr_t>'</string>
+




More information about the cfe-commits mailing list