[clang] [clang] Skip auto-init on scalar vars that have a non-constant Init and no self-ref (PR #94642)

Jan Voung via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 18 19:30:14 PDT 2024


================
@@ -1972,7 +1972,20 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
   }
 
   if (!constant) {
-    initializeWhatIsTechnicallyUninitialized(Loc);
+    if (trivialAutoVarInit !=
+        LangOptions::TrivialAutoVarInitKind::Uninitialized) {
+      // At this point, we know D has an Init expression, but isn't a constant.
+      // - If D is not a scalar, auto-var-init conservatively (members may be
+      // left uninitialized by constructor Init expressions for example).
+      // - If D is a scalar, we only need to auto-var-init if there is a
+      // self-reference. Otherwise, the Init expression should be sufficient.
+      // It may be that the Init expression uses other uninitialized memory,
+      // but auto-var-init here would not help, as auto-init would get
+      // overwritten by Init.
+      if (!D.getType()->isScalarType() || isAccessedBy(D, Init)) {
----------------
jvoung wrote:

Great question, thank you for reviewing!

I tried that example and it does appear to get auto-init on the "calls" var (`isAccessedBy(D, Init)` is true at the same time that `capturedByInit` is true).

There are some existing test cases that are similar and were passing: https://github.com/llvm/llvm-project/blob/0c0281130ed51fea06cf20a2db37c5bca257ad31/clang/test/CodeGenCXX/trivial-auto-var-init.cpp#L33

However, perhaps it's safer to just check `capturedByInit || isAccessedBy...`. WDYT? The capturedByInit could short-circuit in limited cases to avoid a second recursive pass over the `Init` too.

Also added another test case for stmt exprs (see below).

===

Looking at the implementation of `isCapturedBy` https://github.com/llvm/llvm-project/blob/0c0281130ed51fea06cf20a2db37c5bca257ad31/clang/lib/CodeGen/CGDecl.cpp#L1699 and `isAccessedBy`: https://github.com/llvm/llvm-project/blob/0c0281130ed51fea06cf20a2db37c5bca257ad31/clang/lib/CodeGen/CGDecl.cpp#L685

They are similar (both check BlockDecl captures), but do have some slight differences:
- isCapturedBy checks StmtExprs for VarDecl Inits that might recursively capture
- isAccessedBy checks DeclRefExprs while isCapturedBy does not

https://github.com/llvm/llvm-project/pull/94642


More information about the cfe-commits mailing list