[llvm-branch-commits] [clang] e1d0501 - Fix lifetimebound for field access (#100197)
Tobias Hieta via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 29 01:06:24 PDT 2024
Author: Utkarsh Saxena
Date: 2024-07-29T10:06:03+02:00
New Revision: e1d05010c3277ffb1f71fbb7bfad66704dcfc4cf
URL: https://github.com/llvm/llvm-project/commit/e1d05010c3277ffb1f71fbb7bfad66704dcfc4cf
DIFF: https://github.com/llvm/llvm-project/commit/e1d05010c3277ffb1f71fbb7bfad66704dcfc4cf.diff
LOG: Fix lifetimebound for field access (#100197)
Fixes: https://github.com/llvm/llvm-project/issues/81589
There is no way to switch this off without `-Wno-dangling`.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/CheckExprLifetime.cpp
clang/test/SemaCXX/attr-lifetimebound.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 549da6812740f..71d615553c613 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -767,6 +767,9 @@ Improvements to Clang's diagnostics
- Clang now diagnoses undefined behavior in constant expressions more consistently. This includes invalid shifts, and signed overflow in arithmetic.
+- Clang now diagnoses dangling references to fields of temporary objects. Fixes #GH81589.
+
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp b/clang/lib/Sema/CheckExprLifetime.cpp
index 5c8ef564f30aa..112cf3d081822 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "CheckExprLifetime.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Sema/Initialization.h"
@@ -548,6 +549,14 @@ static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
EnableLifetimeWarnings);
}
+ if (auto *M = dyn_cast<MemberExpr>(Init)) {
+ // Lifetime of a non-reference type field is same as base object.
+ if (auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
+ F && !F->getType()->isReferenceType())
+ visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
+ EnableLifetimeWarnings);
+ }
+
if (isa<CallExpr>(Init)) {
if (EnableLifetimeWarnings)
handleGslAnnotatedTypes(Path, Init, Visit);
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp b/clang/test/SemaCXX/attr-lifetimebound.cpp
index 70bc545c07bd9..7db0a4d64d259 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -47,6 +47,31 @@ namespace usage_ok {
q = A(); // expected-warning {{object backing the pointer q will be destroyed at the end of the full-expression}}
r = A(1); // expected-warning {{object backing the pointer r will be destroyed at the end of the full-expression}}
}
+
+ struct FieldCheck {
+ struct Set {
+ int a;
+ };
+ struct Pair {
+ const int& a;
+ int b;
+ Set c;
+ int * d;
+ };
+ Pair p;
+ FieldCheck(const int& a): p(a){}
+ Pair& getR() [[clang::lifetimebound]] { return p; }
+ Pair* getP() [[clang::lifetimebound]] { return &p; }
+ Pair* getNoLB() { return &p; }
+ };
+ void test_field_access() {
+ int x = 0;
+ const int& a = FieldCheck{x}.getR().a;
+ const int& b = FieldCheck{x}.getP()->b; // expected-warning {{temporary bound to local reference 'b' will be destroyed at the end of the full-expression}}
+ const int& c = FieldCheck{x}.getP()->c.a; // expected-warning {{temporary bound to local reference 'c' will be destroyed at the end of the full-expression}}
+ const int& d = FieldCheck{x}.getNoLB()->c.a;
+ const int* e = FieldCheck{x}.getR().d;
+ }
}
# 1 "<std>" 1 3
@@ -239,3 +264,4 @@ namespace move_forward_et_al_examples {
S X;
S *AddressOfOk = std::addressof(X);
} // namespace move_forward_et_al_examples
+
More information about the llvm-branch-commits
mailing list