diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2018-10-08 14:48:39 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2018-10-10 13:46:22 +0200 |
commit | 0bf61855164af5751e78ca8626c10d604b1ab13b (patch) | |
tree | 4a6ef2e62a3737e0976db45c5249744765e63be9 | |
parent | d4938dfcaf4f5fbcb5a576fe9425b6d62584122f (diff) |
Fix failure of loplugin:useuniqueptr with older compilers
...where CompilerTest_compilerplugins_clang failed in
compilerplugins/clang/test/useuniqueptr.cxx due to Foo24's
HTMLAttrs::const_iterator it = m_aSetAttrTab.begin();
and either the old compiler lacked Clang's recent
<https://reviews.llvm.org/D50666> "Fix Stmt::ignoreImplicit" (and the above
initialization expression happens to include a CXXBindTemporaryExpr, at least
with libstdc++), or an even older compiler was used in pre-C++17 mode, so the
above initialization expression happens to include an elidable CXXConstructExpr
copy constructor call.
Change-Id: I757a9ad76829e399b4fe2da1c82863909b8c9657
Reviewed-on: https://gerrit.libreoffice.org/61531
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
-rw-r--r-- | compilerplugins/clang/compat.hxx | 39 | ||||
-rw-r--r-- | compilerplugins/clang/test/useuniqueptr.cxx | 2 | ||||
-rw-r--r-- | compilerplugins/clang/useuniqueptr.cxx | 8 |
3 files changed, 45 insertions, 4 deletions
diff --git a/compilerplugins/clang/compat.hxx b/compilerplugins/clang/compat.hxx index a83ed8688278..f2a8e2f10fe0 100644 --- a/compilerplugins/clang/compat.hxx +++ b/compilerplugins/clang/compat.hxx @@ -193,6 +193,45 @@ inline llvm::StringRef getImmediateMacroNameForDiagnostics( #endif } +inline clang::Expr const * IgnoreImplicit(clang::Expr const * expr) { +#if CLANG_VERSION >= 80000 + return expr->IgnoreImplicit(); +#else + using namespace clang; + // Copy from Clang's lib/AST/Stmt.cpp, including <https://reviews.llvm.org/D50666> "Fix + // Stmt::ignoreImplicit": + Stmt const *s = expr; + + Stmt const *lasts = nullptr; + + while (s != lasts) { + lasts = s; + + if (auto *ewc = dyn_cast<ExprWithCleanups>(s)) + s = ewc->getSubExpr(); + + if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s)) + s = mte->GetTemporaryExpr(); + + if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s)) + s = bte->getSubExpr(); + + if (auto *ice = dyn_cast<ImplicitCastExpr>(s)) + s = ice->getSubExpr(); + } + + return static_cast<Expr const *>(s); +#endif +} + +inline bool CPlusPlus17(clang::LangOptions const & opts) { +#if CLANG_VERSION >= 60000 + return opts.CPlusPlus17; +#else + return opts.CPlusPlus1z; +#endif +} + // Work around <http://reviews.llvm.org/D22128>: // // SfxErrorHandler::GetClassString (svtools/source/misc/ehdl.cxx): diff --git a/compilerplugins/clang/test/useuniqueptr.cxx b/compilerplugins/clang/test/useuniqueptr.cxx index f246fc5ae147..c8f67b46fa85 100644 --- a/compilerplugins/clang/test/useuniqueptr.cxx +++ b/compilerplugins/clang/test/useuniqueptr.cxx @@ -278,7 +278,6 @@ class Foo23 } }; -#if CLANG_VERSION >= 60000 class Foo24 { typedef std::vector<int*> HTMLAttrs; @@ -289,7 +288,6 @@ class Foo24 delete *it; // expected-error {{rather manage with std::some_container<std::unique_ptr<T>> [loplugin:useuniqueptr]}} } }; -#endif // ------------------------------------------------------------------------------------------------ // tests for passing owning pointers to constructors diff --git a/compilerplugins/clang/useuniqueptr.cxx b/compilerplugins/clang/useuniqueptr.cxx index 869e368cc318..ac55e2878c9b 100644 --- a/compilerplugins/clang/useuniqueptr.cxx +++ b/compilerplugins/clang/useuniqueptr.cxx @@ -495,12 +495,16 @@ void UseUniquePtr::CheckLoopDelete(const FunctionDecl* functionDecl, const CXXDe auto init = iterVarDecl->getInit(); if (init) { - init = init->IgnoreImplicit(); + init = compat::IgnoreImplicit(init); + if (!compat::CPlusPlus17(compiler.getLangOpts())) + if (auto x = dyn_cast<CXXConstructExpr>(init)) + if (x->isElidable()) + init = compat::IgnoreImplicit(x->getArg(0)); if (auto x = dyn_cast<CXXConstructExpr>(init)) if (x->getNumArgs() == 1 || (x->getNumArgs() >= 2 && isa<CXXDefaultArgExpr>(x->getArg(1)))) { - init = x->getArg(0)->IgnoreImplicit(); + init = compat::IgnoreImplicit(x->getArg(0)); } if (auto x = dyn_cast<CXXMemberCallExpr>(init)) init = x->getImplicitObjectArgument(); |