diff --git a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -40,6 +40,7 @@ void analyzerNumTimesReached(const CallExpr *CE, CheckerContext &C) const; void analyzerCrash(const CallExpr *CE, CheckerContext &C) const; void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const; + void analyzerDumpSValType(const CallExpr *CE, CheckerContext &C) const; void analyzerDump(const CallExpr *CE, CheckerContext &C) const; void analyzerExplain(const CallExpr *CE, CheckerContext &C) const; void analyzerPrintState(const CallExpr *CE, CheckerContext &C) const; @@ -98,6 +99,8 @@ &ExprInspectionChecker::analyzerDumpExtent) .Case("clang_analyzer_dumpElementCount", &ExprInspectionChecker::analyzerDumpElementCount) + .StartsWith("clang_analyzer_dumpSvalType", + &ExprInspectionChecker::analyzerDumpSValType) .StartsWith("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump) .Case("clang_analyzer_getExtent", @@ -255,6 +258,16 @@ reportBug(Ex.Visit(V), C); } +void ExprInspectionChecker::analyzerDumpSValType(const CallExpr *CE, + CheckerContext &C) const { + const Expr *Arg = getArgExpr(CE, C); + if (!Arg) + return; + + QualType Ty = C.getSVal(Arg).getType(C.getASTContext()); + reportBug(Ty.getAsString(), C); +} + void ExprInspectionChecker::analyzerDump(const CallExpr *CE, CheckerContext &C) const { const Expr *Arg = getArgExpr(CE, C); diff --git a/clang/test/Analysis/expr-inspection.c b/clang/test/Analysis/expr-inspection.c --- a/clang/test/Analysis/expr-inspection.c +++ b/clang/test/Analysis/expr-inspection.c @@ -6,12 +6,16 @@ void clang_analyzer_dump(int x); void clang_analyzer_dump_pointer(int *p); +void clang_analyzer_dumpSvalType(int x); +void clang_analyzer_dumpSvalType_pointer(int *p); void clang_analyzer_printState(void); void clang_analyzer_numTimesReached(void); void foo(int x) { clang_analyzer_dump(x); // expected-warning{{reg_$0}} clang_analyzer_dump(x + (-1)); // expected-warning{{(reg_$0) - 1}} + clang_analyzer_dumpSvalType(x); // expected-warning {{int}} + int y = 1; for (; y < 3; ++y) { clang_analyzer_numTimesReached(); // expected-warning{{2}} @@ -53,4 +57,5 @@ void test_field_dumps(struct S s, struct S *p) { clang_analyzer_dump_pointer(&s.x); // expected-warning{{&s.x}} clang_analyzer_dump_pointer(&p->x); // expected-warning{{&SymRegion{reg_$1}.x}} + clang_analyzer_dumpSvalType_pointer(&s.x); // expected-warning {{int *}} }