[clang] 84f0a36 - [Clang] Do not warn on unused lifetime-extending vars with side effects...
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 5 12:03:09 PDT 2022
Author: Corentin Jabot
Date: 2022-04-05T21:03:02+02:00
New Revision: 84f0a36b14bbd464d65cb1a6135134072b828447
URL: https://github.com/llvm/llvm-project/commit/84f0a36b14bbd464d65cb1a6135134072b828447
DIFF: https://github.com/llvm/llvm-project/commit/84f0a36b14bbd464d65cb1a6135134072b828447.diff
LOG: [Clang] Do not warn on unused lifetime-extending vars with side effects...
const auto & var = ObjectWithSideEffects();
Fixes https://github.com/llvm/llvm-project/issues/54489
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D122661
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaDecl.cpp
clang/test/SemaCXX/warn-unused-variables.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index acc433f2bc86b..86d0a3e7303f1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -110,6 +110,9 @@ Improvements to Clang's diagnostics
<https://github.com/llvm/llvm-project/issues/50794>`_.
- ``-Wunused-but-set-variable`` now also warns if the variable is only used
by unary operators.
+- ``-Wunused-variable`` no longer warn for references extending the lifetime
+ of temporaries with side effects. This fixes `Issue 54489
+ <https://github.com/llvm/llvm-project/issues/54489>`_.
Non-comprehensive list of changes in this release
-------------------------------------------------
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0b5b530bc756c..a2d3722f2efb8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1889,15 +1889,28 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
// Types of valid local variables should be complete, so this should succeed.
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- // White-list anything with an __attribute__((unused)) type.
+ const Expr *Init = VD->getInit();
+ if (const auto *Cleanups = dyn_cast_or_null<ExprWithCleanups>(Init))
+ Init = Cleanups->getSubExpr();
+
const auto *Ty = VD->getType().getTypePtr();
// Only look at the outermost level of typedef.
if (const TypedefType *TT = Ty->getAs<TypedefType>()) {
+ // Allow anything marked with __attribute__((unused)).
if (TT->getDecl()->hasAttr<UnusedAttr>())
return false;
}
+ // Warn for reference variables whose initializtion performs lifetime
+ // extension.
+ if (const auto *MTE = dyn_cast_or_null<MaterializeTemporaryExpr>(Init)) {
+ if (MTE->getExtendingDecl()) {
+ Ty = VD->getType().getNonReferenceType().getTypePtr();
+ Init = MTE->getSubExpr()->IgnoreImplicitAsWritten();
+ }
+ }
+
// If we failed to complete the type for some reason, or if the type is
// dependent, don't diagnose the variable.
if (Ty->isIncompleteType() || Ty->isDependentType())
@@ -1916,10 +1929,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
if (!RD->hasTrivialDestructor() && !RD->hasAttr<WarnUnusedAttr>())
return false;
- if (const Expr *Init = VD->getInit()) {
- if (const ExprWithCleanups *Cleanups =
- dyn_cast<ExprWithCleanups>(Init))
- Init = Cleanups->getSubExpr();
+ if (Init) {
const CXXConstructExpr *Construct =
dyn_cast<CXXConstructExpr>(Init);
if (Construct && !Construct->isElidable()) {
@@ -1931,10 +1941,16 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
// Suppress the warning if we don't know how this is constructed, and
// it could possibly be non-trivial constructor.
- if (Init->isTypeDependent())
+ if (Init->isTypeDependent()) {
for (const CXXConstructorDecl *Ctor : RD->ctors())
if (!Ctor->isTrivial())
return false;
+ }
+
+ // Suppress the warning if the constructor is unresolved because
+ // its arguments are dependent.
+ if (isa<CXXUnresolvedConstructExpr>(Init))
+ return false;
}
}
}
diff --git a/clang/test/SemaCXX/warn-unused-variables.cpp b/clang/test/SemaCXX/warn-unused-variables.cpp
index 2634fb1ec0f7f..4db8bdf12e5de 100644
--- a/clang/test/SemaCXX/warn-unused-variables.cpp
+++ b/clang/test/SemaCXX/warn-unused-variables.cpp
@@ -154,13 +154,13 @@ namespace ctor_with_cleanups {
#include "Inputs/warn-unused-variables.h"
-namespace arrayRecords {
-
class NonTriviallyDestructible {
public:
~NonTriviallyDestructible() {}
};
+namespace arrayRecords {
+
struct Foo {
int x;
Foo(int x) : x(x) {}
@@ -196,7 +196,7 @@ void test() {
bar<2>();
}
-}
+} // namespace arrayRecords
#if __cplusplus >= 201103L
namespace with_constexpr {
@@ -253,3 +253,44 @@ void foo(T &t) {
}
}
#endif
+
+// Ensure we do not warn on lifetime extension
+namespace gh54489 {
+
+void f() {
+ const auto &a = NonTriviallyDestructible();
+ const auto &b = a; // expected-warning {{unused variable 'b'}}
+#if __cplusplus >= 201103L
+ const auto &&c = NonTriviallyDestructible();
+ auto &&d = c; // expected-warning {{unused variable 'd'}}
+#endif
+}
+
+struct S {
+ S() = default;
+ S(const S &) = default;
+ S(int);
+};
+
+template <typename T>
+void foo(T &t) {
+ const auto &extended = S{t};
+}
+
+void test_foo() {
+ int i;
+ foo(i);
+}
+
+struct RAIIWrapper {
+ RAIIWrapper();
+ ~RAIIWrapper();
+};
+
+void RAIIWrapperTest() {
+ auto const guard = RAIIWrapper();
+ auto const &guard2 = RAIIWrapper();
+ auto &&guard3 = RAIIWrapper();
+}
+
+} // namespace gh54489
More information about the cfe-commits
mailing list