summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-12-13 16:52:41 +0100
committerStephan Bergmann <sbergman@redhat.com>2016-12-14 09:34:01 +0000
commitc826ddfc2c213ae61918793eefe0c6593ce9bb17 (patch)
tree8bdc80a87fefdc35e2a6a45ad340a7a3e35f0386
parent876de03290ce0e9393134d722e5b15025e32a341 (diff)
Check that VclPtr is only instantiated with appropriate types
...deriving from VclReferenceBase. Complicated by the fact that the argument type may be incomplete at the time of template instantiation. So this approach may be less precise than the change to loplugin:vclwidgets from cbf5b21f2a65bbb342295200f6ad93a00f90733e "Catch some misuses of VclPtr construction" when the argument type becomes complete later in the comilation unit. However, this approach would also catch the two misuses in UnoControls found by cbf5b21f2a65bbb342295200f6ad93a00f90733e, so go with this approach for now and revert the change to loplugin:vclwdigets. Change-Id: I7888f23d2b9e2db81ae2ce4bf4c8277912317685 Reviewed-on: https://gerrit.libreoffice.org/31966 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
-rw-r--r--compilerplugins/clang/vclwidgets.cxx19
-rw-r--r--include/vcl/vclptr.hxx25
2 files changed, 25 insertions, 19 deletions
diff --git a/compilerplugins/clang/vclwidgets.cxx b/compilerplugins/clang/vclwidgets.cxx
index e90e40fe6e39..8a5ac72b97d2 100644
--- a/compilerplugins/clang/vclwidgets.cxx
+++ b/compilerplugins/clang/vclwidgets.cxx
@@ -838,25 +838,6 @@ bool VCLWidgets::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr )
"Calling constructor of a VclReferenceBase-derived type directly; all such creation should go via VclPtr<>::Create",
constructExpr->getExprLoc());
}
- } else if (auto d = dyn_cast<ClassTemplateSpecializationDecl>(recordDecl)) {
- if (d->getTemplateArgs().size() == 1) {
- auto check = loplugin::DeclCheck(recordDecl);
- if ((check.Class("ScopedVclPtr").GlobalNamespace()
- || check.Class("ScopedVclPtrInstance").GlobalNamespace()
- || check.Class("VclPtr").GlobalNamespace()
- || check.Class("VclPtrInstance").GlobalNamespace()))
- {
- auto t = d->getTemplateArgs()[0].getAsType();
- if (!containsVclReferenceBaseSubclass(t)) {
- report(
- DiagnosticsEngine::Warning,
- ("constructing an instance of %0 where the argument"
- " type %1 is not derived from VclReferenceBase"),
- constructExpr->getExprLoc())
- << recordDecl << t << constructExpr->getSourceRange();
- }
- }
- }
}
return true;
}
diff --git a/include/vcl/vclptr.hxx b/include/vcl/vclptr.hxx
index c022d8b5352c..22679e69ed3d 100644
--- a/include/vcl/vclptr.hxx
+++ b/include/vcl/vclptr.hxx
@@ -20,7 +20,12 @@
#ifndef INCLUDED_VCL_PTR_HXX
#define INCLUDED_VCL_PTR_HXX
+#include <sal/config.h>
+
+#include <config_global.h>
#include <rtl/ref.hxx>
+#include <vcl/vclreferencebase.hxx>
+
#include <utility>
#include <type_traits>
@@ -60,6 +65,17 @@ public:
typedef typename C< value, void *, void >::t t;
};
+#if HAVE_CXX11_CONSTEXPR
+
+template<typename>
+constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
+
+template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
+ int (*)[sizeof(T)])
+{ return std::is_base_of<VclReferenceBase, T>::value; }
+
+#endif
+
}; }; // namespace detail, namespace vcl
/// @endcond
@@ -71,9 +87,18 @@ public:
*
* @param reference_type must be a subclass of vcl::Window
*/
+namespace detail {
+}
template <class reference_type>
class VclPtr
{
+#if HAVE_CXX11_CONSTEXPR
+ static_assert(
+ vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
+ nullptr),
+ "template argument type must be derived from VclReferenceBase");
+#endif
+
::rtl::Reference<reference_type> m_rInnerRef;
public: