summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2019-12-14 13:33:58 -0800
committerPhilip Chimento <philip.chimento@gmail.com>2019-12-16 23:12:20 -0500
commit3c1250fc78f6fdb6957e523416a599a71d8e7f8d (patch)
tree36b34349c3e9f1f73dd5e5e45bbe3dfc8b1447da
parent0a1c3fa2c6f1498d17ad24fe976b17e3c81f3a90 (diff)
assertion: Handle ExprWithCleanups
This type of expression can occur in several instances, but primarily in C++ where a temporary object is created. In is_assertion_stmt() and _simplify_boolean_expr(), only consider the expression and ignore the cleanups. Adds some machinery to the build system and the test runner script so that we can have test files in C++, for testing C++-only features.
-rw-r--r--clang-plugin/assertion-extracter.cpp16
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/assertion-extraction-cpp.cpp17
-rw-r--r--tests/assertion.tail.c2
-rwxr-xr-xtests/wrapper-compiler-errors15
5 files changed, 48 insertions, 6 deletions
diff --git a/clang-plugin/assertion-extracter.cpp b/clang-plugin/assertion-extracter.cpp
index 61ec110..257e91e 100644
--- a/clang-plugin/assertion-extracter.cpp
+++ b/clang-plugin/assertion-extracter.cpp
@@ -378,6 +378,19 @@ AssertionExtracter::is_assertion_stmt (Stmt& stmt, const ASTContext& context)
* I ↦ TRUE */
return dyn_cast<Expr> (&stmt);
}
+ case Stmt::StmtClass::ExprWithCleanupsClass: {
+ /* Handle an expression that introduces a cleanup to be run at the end
+ * of evaluation; most likely a C++ temporary object.
+ * Transformations:
+ * S ↦ calc(S) */
+ ExprWithCleanups& expr_cleanup = cast<ExprWithCleanups> (stmt);
+
+ Stmt *sub_expr = expr_cleanup.getSubExpr ();
+ if (sub_expr == NULL)
+ return NULL;
+
+ return is_assertion_stmt (*sub_expr, context);
+ }
case Stmt::StmtClass::ParenExprClass: {
/* Handle a parenthesised expression.
* Transformations:
@@ -471,6 +484,9 @@ AssertionExtracter::is_assertion_stmt (Stmt& stmt, const ASTContext& context)
static Expr*
_simplify_boolean_expr (Expr* expr, const ASTContext& context)
{
+ if (ExprWithCleanups* expr_cleanup = dyn_cast<ExprWithCleanups> (expr))
+ expr = expr_cleanup->getSubExpr ();
+
expr = expr->IgnoreParens ();
DEBUG ("Simplifying boolean expression of type " <<
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 75f069f..87b1713 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,12 +2,14 @@
# compile successfully without Tartan, and which should fail compilation
# with Tartan (and -Werror).
-TEST_EXTENSIONS = .c
+TEST_EXTENSIONS = .c .cpp
AM_TESTS_ENVIRONMENT = export abs_top_builddir=$(abs_top_builddir);
C_LOG_COMPILER = $(top_srcdir)/tests/wrapper-compiler-errors
+CPP_LOG_COMPILER = $(C_LOG_COMPILER)
c_tests = \
assertion-extraction.c \
+ assertion-extraction-cpp.cpp \
assertion-extraction-return.c \
gsignal-connect.c \
gvariant-builder.c \
diff --git a/tests/assertion-extraction-cpp.cpp b/tests/assertion-extraction-cpp.cpp
new file mode 100644
index 0000000..cbf79e1
--- /dev/null
+++ b/tests/assertion-extraction-cpp.cpp
@@ -0,0 +1,17 @@
+/* Template: assertion */
+
+/*
+ * null passed to a callee that requires a non-null argument
+ * assertion_func (NULL, 1, obj);
+ * ~~~~ ^
+ * null passed to a callee that requires a non-null argument
+ * assertion_func (NULL, 3, NULL);
+ * ~~~~ ^
+ */
+{
+ struct Temp {
+ operator bool () { return true; }
+ ~Temp () {}
+ };
+ g_return_if_fail (Temp () && some_str);
+}
diff --git a/tests/assertion.tail.c b/tests/assertion.tail.c
index 4a50091..be5f93e 100644
--- a/tests/assertion.tail.c
+++ b/tests/assertion.tail.c
@@ -4,7 +4,7 @@
int
main (void)
{
- GObject *obj = g_malloc (5);
+ GObject *obj = (GObject *) g_malloc (5);
/* Various NULL and non-NULL calls to the function. */
assertion_func ("str", 0, obj);
diff --git a/tests/wrapper-compiler-errors b/tests/wrapper-compiler-errors
index 941024a..bc9fe3f 100755
--- a/tests/wrapper-compiler-errors
+++ b/tests/wrapper-compiler-errors
@@ -21,6 +21,7 @@
# asserts there’s no error.
input_filename=$1
+input_ext=${input_filename##*.}
temp_dir=`mktemp -d`/${abs_top_builddir}
tests_dir=`dirname $0`
tartan=${tests_dir}/../scripts/tartan
@@ -51,14 +52,14 @@ mkdir -p ${temp_dir}/${srcdir}
tail -n +3 "${input_filename}" > "${temp_dir}/${input_filename}.tail"
csplit --keep-files --elide-empty-files --silent \
--prefix="${temp_dir}/${input_filename}_" \
- --suffix-format='%02d.c' \
+ --suffix-format="%02d${input_ext}" \
"${temp_dir}/${input_filename}.tail" '/^\/\*/' '{*}'
echo ""
num=0
-while [[ -f `printf "${temp_dir}/${input_filename}_%02d.c" ${num}` ]]; do
- section_filename=`printf ${temp_dir}/${input_filename}_%02d.c ${num}`
+while [[ -f `printf "${temp_dir}/${input_filename}_%02d${input_ext}" ${num}` ]]; do
+ section_filename=`printf ${temp_dir}/${input_filename}_%02d${input_ext} ${num}`
expected_error_filename=`printf ${temp_dir}/${input_filename}_%02d.expected ${num}`
actual_error_filename=`printf ${temp_dir}/${input_filename}_%02d.actual ${num}`
@@ -88,6 +89,12 @@ while [[ -f `printf "${temp_dir}/${input_filename}_%02d.c" ${num}` ]]; do
expect_error=true
fi
+ case $input_ext in
+ c) lang_options=-std=c89 ;;
+ cpp) lang_options=-xc++ ;;
+ *) lang_options=
+ esac
+
# Run the compiler.
# e.g. Set
# TARTAN_TEST_OPTIONS="-analyzer-checker=debug.ViewExplodedGraph" to
@@ -95,7 +102,7 @@ while [[ -f `printf "${temp_dir}/${input_filename}_%02d.c" ${num}` ]]; do
TARTAN_PLUGIN=$tartan_plugin \
TARTAN_OPTIONS=--quiet \
$tartan \
- -cc1 -analyze -std=c89 -Wno-visibility $TARTAN_TEST_OPTIONS \
+ -cc1 -analyze $lang_options -Wno-visibility $TARTAN_TEST_OPTIONS \
`pkg-config --cflags glib-2.0` \
$system_includes \
$section_filename > $actual_error_filename 2>&1