Skip to content

Conversation

@HighCommander4
Copy link
Collaborator

There are cases where the assertion legitimately does not hold (e.g. CallExpr::CreateTemporary()), and there's no readily available way to tell such cases apart.

Fixes #130272

@HighCommander4 HighCommander4 requested a review from zyn0217 March 11, 2025 06:37
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 11, 2025

@llvm/pr-subscribers-clang

Author: Nathan Ridge (HighCommander4)

Changes

There are cases where the assertion legitimately does not hold (e.g. CallExpr::CreateTemporary()), and there's no readily available way to tell such cases apart.

Fixes #130272


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

2 Files Affected:

  • (modified) clang/lib/AST/Expr.cpp (+5-3)
  • (modified) clang/test/AST/ast-dump-cxx2b-deducing-this.cpp (+9)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ccfec7fda0cbc..1dde64f193dbd 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1656,9 +1656,11 @@ SourceLocation CallExpr::getBeginLoc() const {
     if (const auto *Method =
             dyn_cast_if_present<const CXXMethodDecl>(getCalleeDecl());
         Method && Method->isExplicitObjectMemberFunction()) {
-      bool HasFirstArg = getNumArgs() > 0 && getArg(0);
-      assert(HasFirstArg);
-      if (HasFirstArg)
+      // Note: while we typically expect the call to have a first argument
+      // here, we can't assert it because in some cases it does not, e.g.
+      // calls created with CallExpr::CreateTemporary() during overload
+      // resolution.
+      if (getNumArgs() > 0 && getArg(0))
         return getArg(0)->getBeginLoc();
     }
   }
diff --git a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
index abe9d6a5b5bc6..fc86aeb3e5ec3 100644
--- a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
+++ b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
@@ -26,3 +26,12 @@ struct S {
   // CHECK-NEXT:   `-DeclRefExpr 0x{{[^ ]*}} <col:5> 'S<T>' lvalue ParmVar 0x{{[^ ]*}} 's' 'S<T>'
 };
 }
+
+namespace GH130272 {
+struct A {};
+struct B {
+  operator A(this B);
+};
+A a = A(B{});
+// CHECK: CallExpr 0x{{[^ ]*}} <col:9, col:11> 'A':'GH130272::A'
+}

@zyn0217 zyn0217 requested a review from cor3ntin March 11, 2025 06:43
@zyn0217
Copy link
Contributor

zyn0217 commented Mar 11, 2025

@cor3ntin I would appreciate it if you can take a look too

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing changelog.

Otherwise, I think it makes sense even if I sort of hate it, as it relies on TryCopyInitialization looking at the location and nothing else.

I wonder if we could get rid of CallExpr::CreateTemporary and instead
create something like an OpaqueValueExpr for the purpose of determining an initialization sequence.

(We should only need some expression with a type, a location, and a value category, afaik)

There are cases where the assertion legitimately does not hold
(e.g. CallExpr::CreateTemporary()), and there's no readily available
way to tell such cases apart.

Fixes llvm#130272
@HighCommander4
Copy link
Collaborator Author

HighCommander4 commented Mar 11, 2025

Missing changelog.

Added.

I wonder if we could get rid of CallExpr::CreateTemporary and instead create something like an OpaqueValueExpr for the purpose of determining an initialization sequence.

(We should only need some expression with a type, a location, and a value category, afaik)

Filed #130824 to track this idea.

@HighCommander4 HighCommander4 merged commit 5f20f9a into llvm:main Mar 12, 2025
12 checks passed
cor3ntin added a commit to cor3ntin/llvm-project that referenced this pull request Mar 12, 2025
`CallExpr::CreateTemporary` was only used to deduce
a conversion sequence from a conversion operator.

We only need a type/value category for that,
so we can use a dummy Expression such as a
`OpaqueValueExpr`.

This simplify the code and avoid partially-formed
`CallExpr` with incorrect invariants (see llvm#130725)

Fixes llvm#130824
cor3ntin added a commit that referenced this pull request Mar 12, 2025
`CallExpr::CreateTemporary` was only used to deduce a conversion
sequence from a conversion operator.

We only need a type/value category for that,
so we can use a dummy Expression such as a
`OpaqueValueExpr`.

This simplify the code and avoid partially-formed
`CallExpr` with incorrect invariants (see #130725)

Fixes #130824
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clang] Assertion hit in CallExpr::getBeginLoc(): assert(HasFirstArg) fails

4 participants