https://github.com/comex updated 
https://github.com/llvm/llvm-project/pull/154034

>From 5a0549b35cd5b3b4ecb8a25bcde1560cf85c094d Mon Sep 17 00:00:00 2001
From: comex <com...@gmail.com>
Date: Sun, 17 Aug 2025 12:41:44 -0700
Subject: [PATCH] [clang] Fix side effects resolving overloads of builtin
 functions (#138651)

When parsing `__builtin_addressof(Value)`, where `Value` is a constexpr
variable of primitive type, we will run through
`rewriteBuiltinFunctionDecl`.

`rewriteBuiltinFunctionDecl` is meant to handle a special case which is
not applicable here.  (It only applies when a builtin function's type
has a parameter with pointer type, which is not true for
`__builtin_addressof`, not even if the actual argument is a pointer.)
Therefore, `rewriteBuiltinFunctionDecl` returns `nullptr` and things go
on as usual.

But `rewriteBuiltinFunctionDecl` accidentally has a side effect.  It
calls `DefaultFunctionArrayLvalueConversion` ->
`DefaultLvalueConversion` -> `CheckLValueToRValueConversionOperand` ->
`rebuildPotentialResultsAsNonOdrUsed` -> `MarkNotOdrUsed`, which removes
the expression from `S.MaybeODRUseExprs`.

This would be correct if `Value` were actually going through an
lvalue-to-rvalue conversion, because it's a constant expression:

https://eel.is/c++draft/basic.def.odr#5.2.2.2

But in this case the conversion is only hypothetical, as part of
`rewriteBuiltinFunctionDecl`'s pseudo-overload-resolution logic.

Avoid the side effect by pushing an `ExpressionEvaluationContext`, like
we do for real overload resolution.

Similarly, push a `SFINAETrap` to suppress diagnostics emitted during
`DefaultFunctionArrayLvalueConversion`.  This fixes a false-positive
compile error when applying `__builtin_addressof` to certain volatile
union variables, and fixes a duplicated compile error when applying
`__builtin_get_vtable_pointer` to an overloaded function name.
---
 clang/docs/ReleaseNotes.rst                   |  2 +
 clang/lib/Sema/SemaExpr.cpp                   | 50 +++++++++++--------
 .../SemaCXX/builtin-get-vtable-pointer.cpp    |  3 --
 .../SemaCXX/builtin-overload-resolution.cpp   |  8 +++
 clang/test/SemaObjC/non-trivial-c-union.m     |  7 +++
 5 files changed, 46 insertions(+), 24 deletions(-)
 create mode 100644 clang/test/SemaCXX/builtin-overload-resolution.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d1ef91b7e7c14..ff217e9272c25 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -349,6 +349,8 @@ Bug Fixes to C++ Support
   authentication enabled. (#GH152601)
 - Fix the check for narrowing int-to-float conversions, so that they are 
detected in
   cases where converting the float back to an integer is undefined behaviour 
(#GH157067).
+- Fix an assertion failure when a ``constexpr`` variable is only referenced 
through
+  ``__builtin_addressof``, and related issues with builtin arguments. 
(#GH154034)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 317b7caec6fb7..9d153f0627bb4 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6313,30 +6313,38 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema 
*Sema, ASTContext &Context,
   unsigned i = 0;
   SmallVector<QualType, 8> OverloadParams;
 
-  for (QualType ParamType : FT->param_types()) {
+  {
+    // The lvalue conversions in this loop are only for type resolution and
+    // don't actually occur.
+    EnterExpressionEvaluationContext Unevaluated(
+        *Sema, Sema::ExpressionEvaluationContext::Unevaluated);
+    Sema::SFINAETrap Trap(*Sema);
 
-    // Convert array arguments to pointer to simplify type lookup.
-    ExprResult ArgRes =
-        Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]);
-    if (ArgRes.isInvalid())
-      return nullptr;
-    Expr *Arg = ArgRes.get();
-    QualType ArgType = Arg->getType();
-    if (!ParamType->isPointerType() ||
-        ParamType->getPointeeType().hasAddressSpace() ||
-        !ArgType->isPointerType() ||
-        !ArgType->getPointeeType().hasAddressSpace() ||
-        isPtrSizeAddressSpace(ArgType->getPointeeType().getAddressSpace())) {
-      OverloadParams.push_back(ParamType);
-      continue;
-    }
+    for (QualType ParamType : FT->param_types()) {
 
-    QualType PointeeType = ParamType->getPointeeType();
-    NeedsNewDecl = true;
-    LangAS AS = ArgType->getPointeeType().getAddressSpace();
+      // Convert array arguments to pointer to simplify type lookup.
+      ExprResult ArgRes =
+          Sema->DefaultFunctionArrayLvalueConversion(ArgExprs[i++]);
+      if (ArgRes.isInvalid())
+        return nullptr;
+      Expr *Arg = ArgRes.get();
+      QualType ArgType = Arg->getType();
+      if (!ParamType->isPointerType() ||
+          ParamType->getPointeeType().hasAddressSpace() ||
+          !ArgType->isPointerType() ||
+          !ArgType->getPointeeType().hasAddressSpace() ||
+          isPtrSizeAddressSpace(ArgType->getPointeeType().getAddressSpace())) {
+        OverloadParams.push_back(ParamType);
+        continue;
+      }
 
-    PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
-    OverloadParams.push_back(Context.getPointerType(PointeeType));
+      QualType PointeeType = ParamType->getPointeeType();
+      NeedsNewDecl = true;
+      LangAS AS = ArgType->getPointeeType().getAddressSpace();
+
+      PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
+      OverloadParams.push_back(Context.getPointerType(PointeeType));
+    }
   }
 
   if (!NeedsNewDecl)
diff --git a/clang/test/SemaCXX/builtin-get-vtable-pointer.cpp 
b/clang/test/SemaCXX/builtin-get-vtable-pointer.cpp
index b04b38d7996eb..b99bbf0e82030 100644
--- a/clang/test/SemaCXX/builtin-get-vtable-pointer.cpp
+++ b/clang/test/SemaCXX/builtin-get-vtable-pointer.cpp
@@ -66,9 +66,7 @@ struct PolymorphicTemplate {
 };
 
 void test_function(int);    // expected-note{{possible target for call}}
-                            // expected-note@-1{{possible target for call}}
 void test_function(double); // expected-note{{possible target for call}}
-                            // expected-note@-1{{possible target for call}}
 
 void getVTablePointer() {
   ForwardDeclaration *fd = nullptr;
@@ -89,7 +87,6 @@ void getVTablePointer() {
   __builtin_get_vtable_pointer(np_array);      // 
expected-error{{__builtin_get_vtable_pointer requires an argument of 
polymorphic class pointer type, but 'NonPolymorphic' has no virtual methods}}
   __builtin_get_vtable_pointer(&np_array);     // 
expected-error{{__builtin_get_vtable_pointer requires an argument of class 
pointer type, but 'NonPolymorphic (*)[1]' was provided}}
   __builtin_get_vtable_pointer(test_function); // expected-error{{reference to 
overloaded function could not be resolved; did you mean to call it?}}
-                                               // expected-error@-1{{reference 
to overloaded function could not be resolved; did you mean to call it?}}
   Foo<double> Food;
   Foo<int> Fooi;
   __builtin_get_vtable_pointer(Food); // 
expected-error{{__builtin_get_vtable_pointer requires an argument of class 
pointer type, but 'Foo<double>' was provided}}
diff --git a/clang/test/SemaCXX/builtin-overload-resolution.cpp 
b/clang/test/SemaCXX/builtin-overload-resolution.cpp
new file mode 100644
index 0000000000000..81d3055a2f7b2
--- /dev/null
+++ b/clang/test/SemaCXX/builtin-overload-resolution.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++20 %s -emit-obj -o /dev/null
+
+const int* test_odr_used() {
+  // This previously crashed due to Value improperly being removed from
+  // MaybeODRUseExprs.
+  static constexpr int Value = 0;
+  return __builtin_addressof(Value);
+}
diff --git a/clang/test/SemaObjC/non-trivial-c-union.m 
b/clang/test/SemaObjC/non-trivial-c-union.m
index 34f1caad59df7..39fbe2d33818e 100644
--- a/clang/test/SemaObjC/non-trivial-c-union.m
+++ b/clang/test/SemaObjC/non-trivial-c-union.m
@@ -87,3 +87,10 @@ void testVolatileLValueToRValue(volatile U0 *a) {
 void unionInSystemHeader0(U0_SystemHeader);
 
 void unionInSystemHeader1(U1_SystemHeader); // expected-error {{cannot use 
type 'U1_SystemHeader' for a function/method parameter since it is a union that 
is non-trivial to destruct}} expected-error {{cannot use type 'U1_SystemHeader' 
for a function/method parameter since it is a union that is non-trivial to 
copy}}
+
+void testAddressof(void) {
+  extern volatile U0 t0;
+  // These don't dereference so they shouldn't cause an error.
+  (void)&t0;
+  (void)__builtin_addressof(t0);
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to