summaryrefslogtreecommitdiff
path: root/compilerplugins/clang
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2018-03-29 13:49:19 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2018-04-02 08:58:08 +0200
commite075ee967d0c030a22b7699ee54b5cbd49c07c17 (patch)
tree0f4dc5636aec2e8e77e84839d1ec433f11854811 /compilerplugins/clang
parent5092305fa80f1900d7229df75a30204ecb53daf0 (diff)
give DBG_UNHANDLED_EXCEPTION_WHEN an area parameter
and rename it to DBG_UNHANDLED_EXCEPTION, to make it more like the SAL_WARN-type macros. Use some macro magic to deal with different numbers of arguments. Update the sallogareas plugin to check the area parameter of DBG_UNHANDLED_EXCEPTION. Change-Id: Ie790223244c3484f41acb3679c043fb9b438e7c4 Reviewed-on: https://gerrit.libreoffice.org/52073 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins/clang')
-rw-r--r--compilerplugins/clang/sallogareas.cxx107
-rw-r--r--compilerplugins/clang/test/sallogareas.cxx58
2 files changed, 121 insertions, 44 deletions
diff --git a/compilerplugins/clang/sallogareas.cxx b/compilerplugins/clang/sallogareas.cxx
index 98cafb596fd5..1095302d9ada 100644
--- a/compilerplugins/clang/sallogareas.cxx
+++ b/compilerplugins/clang/sallogareas.cxx
@@ -49,54 +49,73 @@ bool SalLogAreas::VisitCallExpr( const CallExpr* call )
{
if( ignoreLocation( call ))
return true;
- if( const FunctionDecl* func = call->getDirectCallee())
+ const FunctionDecl* func = call->getDirectCallee();
+ if( !func )
+ return true;
+
+ if( !( func->getNumParams() == 5 && func->getIdentifier() != NULL
+ && ( func->getName() == "sal_detail_log" || func->getName() == "log" || func->getName() == "DbgUnhandledException")) )
+ return true;
+
+ auto tc = loplugin::DeclCheck(func);
+ enum class LogCallKind { Sal, DbgUnhandledException};
+ LogCallKind kind;
+ int areaArgIndex;
+ if( tc.Function("sal_detail_log") || tc.Function("log").Namespace("detail").Namespace("sal").GlobalNamespace() )
+ {
+ kind = LogCallKind::Sal; // fine
+ areaArgIndex = 1;
+ }
+ else if( tc.Function("DbgUnhandledException").GlobalNamespace() )
+ {
+ kind = LogCallKind::DbgUnhandledException; // ok
+ areaArgIndex = 3;
+ }
+ else
+ return true;
+
+ // The SAL_DETAIL_LOG_STREAM macro expands to two calls to sal::detail::log(),
+ // so do not warn repeatedly about the same macro (the area->getLocStart() of all the calls
+ // from the same macro should be the same).
+ if( kind == LogCallKind::Sal )
+ {
+ SourceLocation expansionLocation = compiler.getSourceManager().getExpansionLoc( call->getLocStart());
+ if( expansionLocation == lastSalDetailLogStreamMacro )
+ return true;
+ lastSalDetailLogStreamMacro = expansionLocation;
+ };
+ if( const clang::StringLiteral* area = dyn_cast< clang::StringLiteral >( call->getArg( areaArgIndex )->IgnoreParenImpCasts()))
{
- if( func->getNumParams() == 5 && func->getIdentifier() != NULL
- && ( func->getName() == "sal_detail_log" || func->getName() == "log" ))
+ if( area->getKind() == clang::StringLiteral::Ascii )
+ checkArea( area->getBytes(), area->getExprLoc());
+ else
+ report( DiagnosticsEngine::Warning, "unsupported string literal kind (plugin needs fixing?)",
+ area->getLocStart());
+ return true;
+ }
+ if( kind == LogCallKind::DbgUnhandledException ) // below checks don't apply
+ return true;
+ if( loplugin::DeclCheck(inFunction).Function("log").Namespace("detail").Namespace("sal").GlobalNamespace()
+ || loplugin::DeclCheck(inFunction).Function("sal_detail_logFormat").GlobalNamespace() )
+ return true; // These functions only forward to sal_detail_log, so ok.
+ if( call->getArg( areaArgIndex )->isNullPointerConstant( compiler.getASTContext(),
+ Expr::NPC_ValueDependentIsNotNull ) != Expr::NPCK_NotNull )
+ { // If the area argument is a null pointer, that is allowed only for SAL_DEBUG.
+ const SourceManager& source = compiler.getSourceManager();
+ for( SourceLocation loc = call->getLocStart();
+ loc.isMacroID();
+ loc = source.getImmediateExpansionRange( loc ).first )
{
- auto tc = loplugin::DeclCheck(func);
- if( tc.Function("sal_detail_log") || tc.Function("log").Namespace("detail").Namespace("sal").GlobalNamespace() )
- {
- // The SAL_DETAIL_LOG_STREAM macro expands to two calls to sal::detail::log(),
- // so do not warn repeatedly about the same macro (the area->getLocStart() of all the calls
- // from the same macro should be the same).
- SourceLocation expansionLocation = compiler.getSourceManager().getExpansionLoc( call->getLocStart());
- if( expansionLocation == lastSalDetailLogStreamMacro )
- return true;
- lastSalDetailLogStreamMacro = expansionLocation;
- if( const clang::StringLiteral* area = dyn_cast< clang::StringLiteral >( call->getArg( 1 )->IgnoreParenImpCasts()))
- {
- if( area->getKind() == clang::StringLiteral::Ascii )
- checkArea( area->getBytes(), area->getExprLoc());
- else
- report( DiagnosticsEngine::Warning, "unsupported string literal kind (plugin needs fixing?)",
- area->getLocStart());
- return true;
- }
- if( loplugin::DeclCheck(inFunction).Function("log").Namespace("detail").Namespace("sal").GlobalNamespace()
- || loplugin::DeclCheck(inFunction).Function("sal_detail_logFormat").GlobalNamespace() )
- return true; // These functions only forward to sal_detail_log, so ok.
- if( call->getArg( 1 )->isNullPointerConstant( compiler.getASTContext(),
- Expr::NPC_ValueDependentIsNotNull ) != Expr::NPCK_NotNull )
- { // If the area argument is a null pointer, that is allowed only for SAL_DEBUG.
- const SourceManager& source = compiler.getSourceManager();
- for( SourceLocation loc = call->getLocStart();
- loc.isMacroID();
- loc = source.getImmediateExpansionRange( loc ).first )
- {
- StringRef inMacro = Lexer::getImmediateMacroName( loc, source, compiler.getLangOpts());
- if( inMacro == "SAL_DEBUG" || inMacro == "SAL_DEBUG_BACKTRACE" )
- return true; // ok
- }
- report( DiagnosticsEngine::Warning, "missing log area",
- call->getArg( 1 )->IgnoreParenImpCasts()->getLocStart());
- return true;
- }
- report( DiagnosticsEngine::Warning, "cannot analyse log area argument (plugin needs fixing?)",
- call->getLocStart());
- }
+ StringRef inMacro = Lexer::getImmediateMacroName( loc, source, compiler.getLangOpts());
+ if( inMacro == "SAL_DEBUG" || inMacro == "SAL_DEBUG_BACKTRACE" )
+ return true; // ok
}
+ report( DiagnosticsEngine::Warning, "missing log area",
+ call->getArg( 1 )->IgnoreParenImpCasts()->getLocStart());
+ return true;
}
+ report( DiagnosticsEngine::Warning, "cannot analyse log area argument (plugin needs fixing?)",
+ call->getLocStart());
return true;
}
diff --git a/compilerplugins/clang/test/sallogareas.cxx b/compilerplugins/clang/test/sallogareas.cxx
new file mode 100644
index 000000000000..6a9035a05f30
--- /dev/null
+++ b/compilerplugins/clang/test/sallogareas.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <tools/diagnose_ex.h>
+
+void func1();
+
+int main()
+{
+ SAL_WARN(
+ "bob.none",
+ "message"); // expected-error@-2 {{unknown log area 'bob.none' (check or extend include/sal/log-areas.dox) [loplugin:sallogareas]}}
+
+ SAL_WARN("xmloff", "message");
+
+ try
+ {
+ func1();
+ }
+ catch (std::exception const&)
+ {
+ DBG_UNHANDLED_EXCEPTION(
+ "bob.none",
+ "message"); // expected-error@-2 {{unknown log area 'bob.none' (check or extend include/sal/log-areas.dox) [loplugin:sallogareas]}}
+ }
+ try
+ {
+ func1();
+ }
+ catch (std::exception const&)
+ {
+ DBG_UNHANDLED_EXCEPTION("xmloff", "message");
+ }
+ try
+ {
+ func1();
+ }
+ catch (std::exception const&)
+ {
+ DBG_UNHANDLED_EXCEPTION("xmloff");
+ }
+ try
+ {
+ func1();
+ }
+ catch (std::exception const&)
+ {
+ DBG_UNHANDLED_EXCEPTION();
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */