forked from OSchip/llvm-project
[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 llvm-svn: 333275
This commit is contained in:
parent
05b6a53340
commit
3ea7442bd6
|
@ -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(const CallEnter &CE,
|
|||
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 &Out, const Decl *D,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
Loading…
Reference in New Issue