mirror of
https://github.com/intel/llvm.git
synced 2026-02-02 01:30:24 +08:00
[analyzer] Improve usability of ExprInspectionChecker
Some of the magic functions take arguments of arbitrary type. However, for semantic correctness, the compiler still requires a declaration of these functions with the correct type. Since C does not have argument-type-overloaded function, this made those functions hard to use in C code. Improve this situation by allowing arbitrary suffixes in the affected magic functions' names, thus allowing the user to create different declarations for different types. A patch by Keno Fischer! Differential Revision: https://reviews.llvm.org/D30589 llvm-svn: 297325
This commit is contained in:
@@ -178,15 +178,21 @@ ExprInspection checks
|
||||
This function explains the value of its argument in a human-readable manner
|
||||
in the warning message. You can make as many overrides of its prototype
|
||||
in the test code as necessary to explain various integral, pointer,
|
||||
or even record-type values.
|
||||
or even record-type values. To simplify usage in C code (where overloading
|
||||
the function declaration is not allowed), you may append an arbitrary suffix
|
||||
to the function name, without affecting functionality.
|
||||
|
||||
Example usage::
|
||||
|
||||
void clang_analyzer_explain(int);
|
||||
void clang_analyzer_explain(void *);
|
||||
|
||||
// Useful in C code
|
||||
void clang_analyzer_explain_int(int);
|
||||
|
||||
void foo(int param, void *ptr) {
|
||||
clang_analyzer_explain(param); // expected-warning{{argument 'param'}}
|
||||
clang_analyzer_explain_int(param); // expected-warning{{argument 'param'}}
|
||||
if (!ptr)
|
||||
clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,8 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
|
||||
&ExprInspectionChecker::analyzerWarnIfReached)
|
||||
.Case("clang_analyzer_warnOnDeadSymbol",
|
||||
&ExprInspectionChecker::analyzerWarnOnDeadSymbol)
|
||||
.Case("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
|
||||
.Case("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump)
|
||||
.StartsWith("clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
|
||||
.StartsWith("clang_analyzer_dump", &ExprInspectionChecker::analyzerDump)
|
||||
.Case("clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent)
|
||||
.Case("clang_analyzer_printState",
|
||||
&ExprInspectionChecker::analyzerPrintState)
|
||||
|
||||
25
clang/test/Analysis/explain-svals.c
Normal file
25
clang/test/Analysis/explain-svals.c
Normal file
@@ -0,0 +1,25 @@
|
||||
// RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core.builtin,debug.ExprInspection,unix.cstring -verify %s
|
||||
|
||||
struct S {
|
||||
int z;
|
||||
};
|
||||
|
||||
void clang_analyzer_explain_int(int);
|
||||
void clang_analyzer_explain_voidp(void *);
|
||||
void clang_analyzer_explain_S(struct S);
|
||||
|
||||
int glob;
|
||||
|
||||
void test_1(int param, void *ptr) {
|
||||
clang_analyzer_explain_voidp(&glob); // expected-warning-re{{{{^pointer to global variable 'glob'$}}}}
|
||||
clang_analyzer_explain_int(param); // expected-warning-re{{{{^argument 'param'$}}}}
|
||||
clang_analyzer_explain_voidp(ptr); // expected-warning-re{{{{^argument 'ptr'$}}}}
|
||||
if (param == 42)
|
||||
clang_analyzer_explain_int(param); // expected-warning-re{{{{^signed 32-bit integer '42'$}}}}
|
||||
}
|
||||
|
||||
void test_2(struct S s) {
|
||||
clang_analyzer_explain_S(s); //expected-warning-re{{{{^lazily frozen compound value of parameter 's'$}}}}
|
||||
clang_analyzer_explain_voidp(&s); // expected-warning-re{{{{^pointer to parameter 's'$}}}}
|
||||
clang_analyzer_explain_int(s.z); // expected-warning-re{{{{^initial value of field 'z' of parameter 's'$}}}}
|
||||
}
|
||||
Reference in New Issue
Block a user