This revision was automatically updated to reflect the committed changes. Closed by commit rC333275: [analyzer] Added template argument lists to the Pathdiagnostic output (authored by Szelethus, committed by ). Herald added a subscriber: cfe-commits.
Repository: rC Clang https://reviews.llvm.org/D46933 Files: lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/plist-diagnostics-template-function.cpp test/Analysis/plist-diagnostics-template-record.cpp
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp =================================================================== --- lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -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 @@ 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 @@ 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; } Index: test/Analysis/plist-diagnostics-template-function.cpp =================================================================== --- test/Analysis/plist-diagnostics-template-function.cpp +++ test/Analysis/plist-diagnostics-template-function.cpp @@ -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> + Index: test/Analysis/plist-diagnostics-template-record.cpp =================================================================== --- test/Analysis/plist-diagnostics-template-record.cpp +++ test/Analysis/plist-diagnostics-template-record.cpp @@ -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> +
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits