Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] Compute accurate begin location for CallExpr with explicit object parameter #117841

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

HighCommander4
Copy link
Collaborator

The explicit object parameter is written before the callee expression, so the begin location should come from the explicit object parameter.

Fixes #116335

…ject parameter

The explicit object parameter is written before the callee expression,
so the begin location should come from the explicit object parameter.

Fixes llvm#116335
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Nov 27, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 27, 2024

@llvm/pr-subscribers-clang

Author: Nathan Ridge (HighCommander4)

Changes

The explicit object parameter is written before the callee expression, so the begin location should come from the explicit object parameter.

Fixes #116335


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

3 Files Affected:

  • (modified) clang/lib/AST/Expr.cpp (+7)
  • (modified) clang/lib/Sema/SemaOverload.cpp (+1-1)
  • (modified) clang/test/AST/ast-dump-cxx2b-deducing-this.cpp (+2-2)
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index a4fb4d5a1f2ec4..8b10a2609c2ab0 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1639,6 +1639,13 @@ SourceLocation CallExpr::getBeginLoc() const {
   if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
     return OCE->getBeginLoc();
 
+  if (const CXXMethodDecl *Method =
+          dyn_cast_or_null<const CXXMethodDecl>(getCalleeDecl());
+      Method && Method->isExplicitObjectMemberFunction()) {
+    assert(getNumArgs() > 0 && getArg(0));
+    return getArg(0)->getBeginLoc();
+  }
+
   SourceLocation begin = getCallee()->getBeginLoc();
   if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
     begin = getArg(0)->getBeginLoc();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 4c9e37bd286dee..e4bf9aa521224b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -15565,7 +15565,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
     // Build the actual expression node.
     ExprResult FnExpr =
         CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr,
-                              HadMultipleCandidates, MemExpr->getBeginLoc());
+                              HadMultipleCandidates, MemExpr->getExprLoc());
     if (FnExpr.isInvalid())
       return ExprError();
 
diff --git a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
index 04cff07376885a..1b385e0fc33319 100644
--- a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
+++ b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp
@@ -9,7 +9,7 @@ int main() {
   S s;
   int x = s.f();
   // CHECK: CallExpr 0x{{[^ ]*}} <col:11, col:15> 'int
-  // CHECK-NEXT: |-ImplicitCastExpr 0x{{[^ ]*}} <col:11> 'int (*)(S &)' <FunctionToPointerDecay>
-  // CHECK-NEXT: | `-DeclRefExpr 0x{{[^ ]*}} <col:11> 'int (S &)' lvalue CXXMethod 0x{{[^ ]*}} 'f' 'int (S &)'
+  // CHECK-NEXT: |-ImplicitCastExpr 0x{{[^ ]*}} <col:13> 'int (*)(S &)' <FunctionToPointerDecay>
+  // CHECK-NEXT: | `-DeclRefExpr 0x{{[^ ]*}} <col:13> 'int (S &)' lvalue CXXMethod 0x{{[^ ]*}} 'f' 'int (S &)'
 }
 }

@@ -1639,6 +1639,13 @@ SourceLocation CallExpr::getBeginLoc() const {
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
return OCE->getBeginLoc();

if (const CXXMethodDecl *Method =
dyn_cast_or_null<const CXXMethodDecl>(getCalleeDecl());
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
dyn_cast_or_null<const CXXMethodDecl>(getCalleeDecl());
dyn_cast_if_present<const CXXMethodDecl>(getCalleeDecl());

Copy link
Contributor

@zyn0217 zyn0217 left a comment

Choose a reason for hiding this comment

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

I think this also needs a selection tree test to demonstrate the original case works with the current approach.

Besides, If we can't highlight the loci differences (compared to the behavior before the last PR) using simple -ast-dump flags, then perhaps we should reconsider the necessity of clang/test/AST/ast-dump-cxx2b-deducing-this.cpp - removing it might be a good option.

That said, I was still thinking if there's any possibility for us to find a better AST model for such use cases, rather than relying on special-casing it in CallExpr::getBeginLoc

@HighCommander4
Copy link
Collaborator Author

That said, I was still thinking if there's any possibility for us to find a better AST model for such use cases, rather than relying on special-casing it in CallExpr::getBeginLoc

A more general implementation of CallExpr::getBeginLoc that occurs to me is: return the earlier of the callee's begin loc and the first argument's (if present) begin loc.

@@ -1639,6 +1639,13 @@ SourceLocation CallExpr::getBeginLoc() const {
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
return OCE->getBeginLoc();

if (const CXXMethodDecl *Method =
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (const CXXMethodDecl *Method =
if (const auto *Method =

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.

[clangd] Incorrect navigation caused by deducing this
5 participants