llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: None (comex)

<details>
<summary>Changes</summary>

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` -&gt;
`DefaultLvalueConversion` -&gt; `CheckLValueToRValueConversionOperand` -&gt; 
`rebuildPotentialResultsAsNonOdrUsed` -&gt; `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.

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

---
Full diff: https://github.com/llvm/llvm-project/pull/154034.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaExpr.cpp (+27-21) 
- (added) clang/test/SemaCXX/builtin-overload-resolution.cpp (+8) 


``````````diff
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 237c068f59283..c00de2d4ed17b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6312,30 +6312,36 @@ static FunctionDecl *rewriteBuiltinFunctionDecl(Sema 
*Sema, ASTContext &Context,
   unsigned i = 0;
   SmallVector<QualType, 8> OverloadParams;
 
-  for (QualType ParamType : FT->param_types()) {
+  {
+    // Push an evaluation context since the lvalue conversions in this loop
+    // are only for type resolution and don't actually occur.
+    EnterExpressionEvaluationContext Unevaluated(
+        *Sema, Sema::ExpressionEvaluationContext::Unevaluated);
+    for (QualType ParamType : FT->param_types()) {
 
-    // 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;
-    }
+      // 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;
+      }
 
-    QualType PointeeType = ParamType->getPointeeType();
-    NeedsNewDecl = true;
-    LangAS AS = ArgType->getPointeeType().getAddressSpace();
+      QualType PointeeType = ParamType->getPointeeType();
+      NeedsNewDecl = true;
+      LangAS AS = ArgType->getPointeeType().getAddressSpace();
 
-    PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
-    OverloadParams.push_back(Context.getPointerType(PointeeType));
+      PointeeType = Context.getAddrSpaceQualType(PointeeType, AS);
+      OverloadParams.push_back(Context.getPointerType(PointeeType));
+    }
   }
 
   if (!NeedsNewDecl)
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);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/154034
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to