https://github.com/cor3ntin created 
https://github.com/llvm/llvm-project/pull/141058

The bulk of the changes are in `CallExpr`

We cache Begin/End source locs in the trailing objects, in the space left by 
making the offset to the trailing objects static.
We also set a flag to indicate that we are calling an explicit object member 
function, further reducing the cost of getBeginLoc.

Fixes #140876 

>From 381c2219e346acfbf5b61e93fcc3233af6b7c3a7 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Wed, 21 May 2025 23:09:00 +0200
Subject: [PATCH 1/8] try optimize

---
 clang/lib/AST/Expr.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index fe874ccd7b60f..1906e46042cad 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1544,7 +1544,16 @@ unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) 
{
 }
 
 Decl *Expr::getReferencedDeclOfCallee() {
-  Expr *CEE = IgnoreParenImpCasts();
+
+  // Optimize for the common case first
+  // (simple function or member function call)
+  // then try more exotic possibilities
+  Expr *CEE = IgnoreImpCasts();
+  if (auto *DRE = dyn_cast<DeclRefExpr>(CEE))
+    return DRE->getDecl();
+
+  if (auto *ME = dyn_cast<MemberExpr>(CEE))
+    return ME->getMemberDecl();
 
   while (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE))
     CEE = NTTP->getReplacement()->IgnoreParenImpCasts();

>From 16077ed74794645452434c9ec761d642789e09ac Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 00:28:05 +0200
Subject: [PATCH 2/8] remove call to getCalleeDecl

---
 clang/include/clang/AST/Expr.h            |  5 +++++
 clang/include/clang/AST/Stmt.h            |  5 +++--
 clang/lib/AST/Expr.cpp                    | 21 ++++++++++-----------
 clang/lib/Sema/SemaOpenCL.cpp             |  2 +-
 clang/lib/Sema/SemaOverload.cpp           |  2 ++
 clang/lib/Serialization/ASTReaderStmt.cpp |  2 ++
 clang/lib/Serialization/ASTWriterStmt.cpp |  2 ++
 7 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index e9c3c16c87598..a8bfae2e7efda 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3028,6 +3028,9 @@ class CallExpr : public Expr {
 
   bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
 
+  bool usesMemberSyntax() const { return 
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax; }
+  void setUsesMemberSyntax(bool V = true) { 
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V; }
+
   bool isCoroElideSafe() const { return CallExprBits.IsCoroElideSafe; }
   void setCoroElideSafe(bool V = true) { CallExprBits.IsCoroElideSafe = V; }
 
@@ -3220,6 +3223,8 @@ class CallExpr : public Expr {
   }
 };
 
+static_assert(sizeof(CallExpr) == 24);
+
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 336eb6d3df7e1..b3ad285ca73fd 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -563,10 +563,11 @@ class alignas(void *) Stmt {
     unsigned HasFPFeatures : 1;
 
     /// True if the call expression is a must-elide call to a coroutine.
+    LLVM_PREFERRED_TYPE(bool)
     unsigned IsCoroElideSafe : 1;
 
-    /// Padding used to align OffsetToTrailingObjects to a byte multiple.
-    unsigned : 24 - 4 - NumExprBits;
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned ExplicitObjectMemFunUsingMemberSyntax : 1;
 
     /// The offset in bytes from the this pointer to the start of the
     /// trailing objects belonging to CallExpr. Intentionally byte sized
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1906e46042cad..e6ccd0904eefd 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1484,6 +1484,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr 
*> PreArgs,
 
   CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
   CallExprBits.IsCoroElideSafe = false;
+  CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
+
   if (hasStoredFPFeatures())
     setStoredFPFeatures(FPFeatures);
 }
@@ -1549,12 +1551,15 @@ Decl *Expr::getReferencedDeclOfCallee() {
   // (simple function or member function call)
   // then try more exotic possibilities
   Expr *CEE = IgnoreImpCasts();
+
   if (auto *DRE = dyn_cast<DeclRefExpr>(CEE))
     return DRE->getDecl();
 
   if (auto *ME = dyn_cast<MemberExpr>(CEE))
     return ME->getMemberDecl();
 
+  CEE = CEE->IgnoreParens();
+
   while (auto *NTTP = dyn_cast<SubstNonTypeTemplateParmExpr>(CEE))
     CEE = NTTP->getReplacement()->IgnoreParenImpCasts();
 
@@ -1658,20 +1663,14 @@ SourceLocation CallExpr::getBeginLoc() const {
   // begin location should come from the first argument.
   // This does not apply to dependent calls, which are modelled with `o.f`
   // being the callee.
-  if (!isTypeDependent()) {
-    if (const auto *Method =
-            dyn_cast_if_present<const CXXMethodDecl>(getCalleeDecl());
-        Method && Method->isExplicitObjectMemberFunction()) {
-      if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
-        return FirstArgLoc;
-      }
+  // Because this check is expennsive, we cache the result.
+  if (usesMemberSyntax()) {
+    if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
+      return FirstArgLoc;
     }
   }
 
-  SourceLocation begin = getCallee()->getBeginLoc();
-  if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
-    begin = getArg(0)->getBeginLoc();
-  return begin;
+  return getCallee()->getBeginLoc();
 }
 
 SourceLocation CallExpr::getEndLoc() const {
diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index 9f746fffd34d0..865c57ae7c158 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -542,7 +542,7 @@ bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, 
CallExpr *Call) {
   auto RT = Call->getArg(0)->getType();
   if (!RT->isPointerType() ||
       RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
-    Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg)
+    Diag(Call->getArg(0)->getBeginLoc(), 
diag::err_opencl_builtin_to_addr_invalid_arg)
         << Call->getArg(0) << Call->getDirectCallee() << 
Call->getSourceRange();
     return true;
   }
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 23304e12f8c31..69768dd3a7212 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -14832,6 +14832,7 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, 
NamedDecl *FoundDecl,
     CE = CallExpr::Create(Context, FnExpr.get(), MultiExprArg(&ObjectParam, 1),
                           ResultType, VK, Exp.get()->getEndLoc(),
                           CurFPFeatureOverrides());
+    CE->setUsesMemberSyntax(true);
   } else {
     MemberExpr *ME =
         BuildMemberExpr(Exp.get(), /*IsArrow=*/false, SourceLocation(),
@@ -16159,6 +16160,7 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, 
Expr *MemExprE,
     TheCall =
         CallExpr::Create(Context, FnExpr.get(), Args, ResultType, VK, 
RParenLoc,
                          CurFPFeatureOverrides(), Proto->getNumParams());
+    TheCall->setUsesMemberSyntax(true);
   } else {
     // Convert the object argument (for a non-static member function call).
     ExprResult ObjectArg = PerformImplicitObjectArgumentInitialization(
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index 0ba0378754eb4..a4bb9f2da5547 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1036,6 +1036,8 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) {
   E->setADLCallKind(
       static_cast<CallExpr::ADLCallKind>(CurrentUnpackingBits->getNextBit()));
   bool HasFPFeatures = CurrentUnpackingBits->getNextBit();
+  E->setCoroElideSafe(CurrentUnpackingBits->getNextBit());
+  E->setUsesMemberSyntax(CurrentUnpackingBits->getNextBit());
   assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!");
   E->setRParenLoc(readSourceLocation());
   E->setCallee(Record.readSubExpr());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp 
b/clang/lib/Serialization/ASTWriterStmt.cpp
index b9eabd5ddb64c..0401be33e8930 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -959,6 +959,8 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
   CurrentPackingBits.updateBits();
   CurrentPackingBits.addBit(static_cast<bool>(E->getADLCallKind()));
   CurrentPackingBits.addBit(E->hasStoredFPFeatures());
+  CurrentPackingBits.addBit(E->isCoroElideSafe());
+  CurrentPackingBits.addBit(E->usesMemberSyntax());
 
   Record.AddSourceLocation(E->getRParenLoc());
   Record.AddStmt(E->getCallee());

>From fb437b0a22f6e45ccec1ed20fa244afb998b4531 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 01:29:19 +0200
Subject: [PATCH 3/8] Optimize another getBeginLoc

---
 clang/include/clang/AST/Expr.h | 8 +++++++-
 clang/lib/AST/Expr.cpp         | 5 -----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index a8bfae2e7efda..c45e9b7e3c47f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1344,7 +1344,13 @@ class DeclRefExpr final
 
   SourceLocation getLocation() const { return DeclRefExprBits.Loc; }
   void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; }
-  SourceLocation getBeginLoc() const LLVM_READONLY;
+
+  SourceLocation getBeginLoc() const {
+    if (hasQualifier())
+      return getQualifierLoc().getBeginLoc();
+    return DeclRefExprBits.Loc;
+  }
+
   SourceLocation getEndLoc() const LLVM_READONLY;
 
   /// Determine whether this declaration reference was preceded by a
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index e6ccd0904eefd..7dbdb35148c5a 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -547,11 +547,6 @@ void DeclRefExpr::setDecl(ValueDecl *NewD) {
   setDependence(computeDependence(this, NewD->getASTContext()));
 }
 
-SourceLocation DeclRefExpr::getBeginLoc() const {
-  if (hasQualifier())
-    return getQualifierLoc().getBeginLoc();
-  return getNameInfo().getBeginLoc();
-}
 SourceLocation DeclRefExpr::getEndLoc() const {
   if (hasExplicitTemplateArgs())
     return getRAngleLoc();

>From dc33c5a616f03e4e568d1a7b424ca7f218786571 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 09:40:01 +0200
Subject: [PATCH 4/8] Try more optimizations

---
 clang/include/clang/AST/Expr.h | 44 +++++++++++++++++++++-------
 clang/include/clang/AST/Stmt.h |  8 ++---
 clang/lib/AST/Expr.cpp         | 53 ++--------------------------------
 clang/lib/AST/ExprCXX.cpp      | 16 +++++-----
 4 files changed, 46 insertions(+), 75 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index c45e9b7e3c47f..b5fdd44f95939 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2915,26 +2915,31 @@ class CallExpr : public Expr {
   // instead of re-computing the offset each time the trailing objects are
   // accessed.
 
+protected:
+  static constexpr unsigned offsetToTrailingObjects = 32;
+
+  template <typename T>
+  static constexpr unsigned sizeToAllocateForCallExprSubclass(unsigned 
SizeOfTrailingObjects) {
+    static_assert(sizeof(T) <= CallExpr::offsetToTrailingObjects);
+    return SizeOfTrailingObjects + CallExpr::offsetToTrailingObjects;
+  }
+private:
   /// Return a pointer to the start of the trailing array of "Stmt *".
   Stmt **getTrailingStmts() {
     return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) +
-                                     CallExprBits.OffsetToTrailingObjects);
+                                     offsetToTrailingObjects);
   }
   Stmt *const *getTrailingStmts() const {
     return const_cast<CallExpr *>(this)->getTrailingStmts();
   }
 
-  /// Map a statement class to the appropriate offset in bytes from the
-  /// this pointer to the trailing objects.
-  static unsigned offsetToTrailingObjects(StmtClass SC);
-
   unsigned getSizeOfTrailingStmts() const {
     return (1 + getNumPreArgs() + getNumArgs()) * sizeof(Stmt *);
   }
 
   size_t getOffsetOfTrailingFPFeatures() const {
     assert(hasStoredFPFeatures());
-    return CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts();
+    return offsetToTrailingObjects + getSizeOfTrailingStmts();
   }
 
 public:
@@ -2981,14 +2986,14 @@ class CallExpr : public Expr {
   FPOptionsOverride *getTrailingFPFeatures() {
     assert(hasStoredFPFeatures());
     return reinterpret_cast<FPOptionsOverride *>(
-        reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects +
+        reinterpret_cast<char *>(this) + offsetToTrailingObjects +
         getSizeOfTrailingStmts());
   }
   const FPOptionsOverride *getTrailingFPFeatures() const {
     assert(hasStoredFPFeatures());
     return reinterpret_cast<const FPOptionsOverride *>(
         reinterpret_cast<const char *>(this) +
-        CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts());
+        offsetToTrailingObjects + getSizeOfTrailingStmts());
   }
 
 public:
@@ -3196,7 +3201,26 @@ class CallExpr : public Expr {
   SourceLocation getRParenLoc() const { return RParenLoc; }
   void setRParenLoc(SourceLocation L) { RParenLoc = L; }
 
-  SourceLocation getBeginLoc() const LLVM_READONLY;
+  SourceLocation getBeginLoc() const {
+    //if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
+    //    return OCE->getBeginLoc();
+
+    // A non-dependent call to a member function with an explicit object 
parameter
+    // is modelled with the object expression being the first argument, e.g. in
+    // `o.f(x)`, the callee will be just `f`, and `o` will be the first 
argument.
+    // Since the first argument is written before the callee, the expression's
+    // begin location should come from the first argument.
+    // This does not apply to dependent calls, which are modelled with `o.f`
+    // being the callee.
+    // Because this check is expennsive, we cache the result.
+    if (usesMemberSyntax()) {
+      if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
+        return FirstArgLoc;
+      }
+    }
+    return getCallee()->getBeginLoc();
+  }
+
   SourceLocation getEndLoc() const LLVM_READONLY;
 
   /// Return true if this is a call to __assume() or __builtin_assume() with
@@ -3229,8 +3253,6 @@ class CallExpr : public Expr {
   }
 };
 
-static_assert(sizeof(CallExpr) == 24);
-
 /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.
 ///
 class MemberExpr final
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index b3ad285ca73fd..3c2dc293b3a1e 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -568,13 +568,9 @@ class alignas(void *) Stmt {
 
     LLVM_PREFERRED_TYPE(bool)
     unsigned ExplicitObjectMemFunUsingMemberSyntax : 1;
-
-    /// The offset in bytes from the this pointer to the start of the
-    /// trailing objects belonging to CallExpr. Intentionally byte sized
-    /// for faster access.
-    unsigned OffsetToTrailingObjects : 8;
   };
-  enum { NumCallExprBits = 32 };
+
+  enum { NumCallExprBits = 24 };
 
   class MemberExprBitfields {
     friend class ASTStmtReader;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 7dbdb35148c5a..1696ea42a7fa3 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1460,11 +1460,6 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr 
*> PreArgs,
   CallExprBits.NumPreArgs = NumPreArgs;
   assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
 
-  unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC);
-  CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
-  assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
-         "OffsetToTrailingObjects overflow!");
-
   CallExprBits.UsesADL = static_cast<bool>(UsesADL);
 
   setCallee(Fn);
@@ -1490,11 +1485,6 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, 
unsigned NumArgs,
     : Expr(SC, Empty), NumArgs(NumArgs) {
   CallExprBits.NumPreArgs = NumPreArgs;
   assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
-
-  unsigned OffsetToTrailingObjects = offsetToTrailingObjects(SC);
-  CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
-  assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
-         "OffsetToTrailingObjects overflow!");
   CallExprBits.HasFPFeatures = HasFPFeatures;
   CallExprBits.IsCoroElideSafe = false;
 }
@@ -1508,7 +1498,8 @@ CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr 
*Fn,
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
   void *Mem =
-      Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, 
alignof(CallExpr));
+      
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
+                   alignof(CallExpr));
   return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
                             RParenLoc, FPFeatures, MinNumArgs, UsesADL);
 }
@@ -1518,28 +1509,11 @@ CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, 
unsigned NumArgs,
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
   void *Mem =
-      Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, 
alignof(CallExpr));
+      
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
 alignof(CallExpr));
   return new (Mem)
       CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, Empty);
 }
 
-unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) {
-  switch (SC) {
-  case CallExprClass:
-    return sizeof(CallExpr);
-  case CXXOperatorCallExprClass:
-    return sizeof(CXXOperatorCallExpr);
-  case CXXMemberCallExprClass:
-    return sizeof(CXXMemberCallExpr);
-  case UserDefinedLiteralClass:
-    return sizeof(UserDefinedLiteral);
-  case CUDAKernelCallExprClass:
-    return sizeof(CUDAKernelCallExpr);
-  default:
-    llvm_unreachable("unexpected class deriving from CallExpr!");
-  }
-}
-
 Decl *Expr::getReferencedDeclOfCallee() {
 
   // Optimize for the common case first
@@ -1647,27 +1621,6 @@ CallExpr::getUnusedResultAttr(const ASTContext &Ctx) 
const {
   return {nullptr, nullptr};
 }
 
-SourceLocation CallExpr::getBeginLoc() const {
-  if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
-    return OCE->getBeginLoc();
-
-  // A non-dependent call to a member function with an explicit object 
parameter
-  // is modelled with the object expression being the first argument, e.g. in
-  // `o.f(x)`, the callee will be just `f`, and `o` will be the first argument.
-  // Since the first argument is written before the callee, the expression's
-  // begin location should come from the first argument.
-  // This does not apply to dependent calls, which are modelled with `o.f`
-  // being the callee.
-  // Because this check is expennsive, we cache the result.
-  if (usesMemberSyntax()) {
-    if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
-      return FirstArgLoc;
-    }
-  }
-
-  return getCallee()->getBeginLoc();
-}
-
 SourceLocation CallExpr::getEndLoc() const {
   if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
     return OCE->getEndLoc();
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index 00bddce3a1ee2..c10fae156bef8 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -619,7 +619,7 @@ CXXOperatorCallExpr::Create(const ASTContext &Ctx,
   unsigned NumArgs = Args.size();
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(SizeOfTrailingObjects),
                            alignof(CXXOperatorCallExpr));
   return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc,
                                        FPFeatures, UsesADL);
@@ -632,7 +632,7 @@ CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
-  void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(SizeOfTrailingObjects),
                            alignof(CXXOperatorCallExpr));
   return new (Mem) CXXOperatorCallExpr(NumArgs, HasFPFeatures, Empty);
 }
@@ -684,7 +684,7 @@ CXXMemberCallExpr *CXXMemberCallExpr::Create(const 
ASTContext &Ctx, Expr *Fn,
   unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(SizeOfTrailingObjects),
                            alignof(CXXMemberCallExpr));
   return new (Mem)
       CXXMemberCallExpr(Fn, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
@@ -697,7 +697,7 @@ CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
-  void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(SizeOfTrailingObjects),
                            alignof(CXXMemberCallExpr));
   return new (Mem) CXXMemberCallExpr(NumArgs, HasFPFeatures, Empty);
 }
@@ -958,7 +958,7 @@ UserDefinedLiteral *UserDefinedLiteral::Create(const 
ASTContext &Ctx, Expr *Fn,
   unsigned NumArgs = Args.size();
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(SizeOfTrailingObjects),
                            alignof(UserDefinedLiteral));
   return new (Mem)
       UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc, FPFeatures);
@@ -971,7 +971,7 @@ UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPOptions);
-  void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(SizeOfTrailingObjects),
                            alignof(UserDefinedLiteral));
   return new (Mem) UserDefinedLiteral(NumArgs, HasFPOptions, Empty);
 }
@@ -1946,7 +1946,7 @@ CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr 
*Fn, CallExpr *Config,
   unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/END_PREARG, NumArgs, 
FPFeatures.requiresTrailingStorage());
-  void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(SizeOfTrailingObjects),
                            alignof(CUDAKernelCallExpr));
   return new (Mem)
       CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
@@ -1959,7 +1959,7 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/END_PREARG, NumArgs, HasFPFeatures);
-  void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects,
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(SizeOfTrailingObjects),
                            alignof(CUDAKernelCallExpr));
   return new (Mem) CUDAKernelCallExpr(NumArgs, HasFPFeatures, Empty);
 }

>From 21cf4b443185bd3accf7b074c79d54f2277c8b5d Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 10:34:24 +0200
Subject: [PATCH 5/8] cache begin in callexpr

---
 clang/include/clang/AST/Expr.h            | 23 +++++++++++++++++++++++
 clang/include/clang/AST/Stmt.h            |  5 ++++-
 clang/lib/AST/Expr.cpp                    |  8 +++++++-
 clang/lib/Serialization/ASTReaderStmt.cpp |  3 +++
 4 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index b5fdd44f95939..30717c3e2fb92 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3202,6 +3202,12 @@ class CallExpr : public Expr {
   void setRParenLoc(SourceLocation L) { RParenLoc = L; }
 
   SourceLocation getBeginLoc() const {
+    if(CallExprBits.HasTrailingSourceLoc) {
+        static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
+        return *reinterpret_cast<const SourceLocation*>(reinterpret_cast<const 
char *>(this) +
+                                                        sizeof(CallExpr));
+    }
+
     //if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
     //    return OCE->getBeginLoc();
 
@@ -3223,6 +3229,23 @@ class CallExpr : public Expr {
 
   SourceLocation getEndLoc() const LLVM_READONLY;
 
+private:
+  friend class ASTStmtReader;
+  bool hasTrailingSourceLoc() const {
+      return CallExprBits.HasTrailingSourceLoc;
+  }
+  void setTrailingSourceLocs() {
+      assert(!CallExprBits.HasTrailingSourceLoc);
+      static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
+      SourceLocation* Locs = 
reinterpret_cast<SourceLocation*>(reinterpret_cast<char *>(this) +
+                                                               
sizeof(CallExpr));
+      Locs[0] = getBeginLoc();
+      Locs[1] = getEndLoc();
+      CallExprBits.HasTrailingSourceLoc = true;
+  }
+
+public:
+
   /// Return true if this is a call to __assume() or __builtin_assume() with
   /// a non-value-dependent constant parameter evaluating as false.
   bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 3c2dc293b3a1e..2889fedb4d221 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -568,9 +568,12 @@ class alignas(void *) Stmt {
 
     LLVM_PREFERRED_TYPE(bool)
     unsigned ExplicitObjectMemFunUsingMemberSyntax : 1;
+
+    LLVM_PREFERRED_TYPE(bool)
+    unsigned HasTrailingSourceLoc : 1;
   };
 
-  enum { NumCallExprBits = 24 };
+  enum { NumCallExprBits = 25 };
 
   class MemberExprBitfields {
     friend class ASTStmtReader;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1696ea42a7fa3..ace1221bbc439 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1475,6 +1475,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr 
*> PreArgs,
   CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
   CallExprBits.IsCoroElideSafe = false;
   CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
+  CallExprBits.HasTrailingSourceLoc = false;
 
   if (hasStoredFPFeatures())
     setStoredFPFeatures(FPFeatures);
@@ -1487,6 +1488,9 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, 
unsigned NumArgs,
   assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
   CallExprBits.HasFPFeatures = HasFPFeatures;
   CallExprBits.IsCoroElideSafe = false;
+  CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
+  CallExprBits.HasTrailingSourceLoc = false;
+
 }
 
 CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
@@ -1500,8 +1504,10 @@ CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr 
*Fn,
   void *Mem =
       
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
                    alignof(CallExpr));
-  return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+  CallExpr* E = new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, 
Ty, VK,
                             RParenLoc, FPFeatures, MinNumArgs, UsesADL);
+  E->setTrailingSourceLocs();
+  return E;
 }
 
 CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index a4bb9f2da5547..a07bc0854e25d 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1047,6 +1047,9 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) {
   if (HasFPFeatures)
     E->setStoredFPFeatures(
         FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
+
+  if(E->getStmtClass() == Stmt::CallExprClass)
+    E->setTrailingSourceLocs();
 }
 
 void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {

>From 7472299d253cdf8341846171be2e8b77f87aad74 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 12:36:32 +0200
Subject: [PATCH 6/8] revert changes to explicit object member functions

---
 clang/include/clang/AST/Expr.h                | 18 +++++++++++++++---
 clang/include/clang/AST/NestedNameSpecifier.h | 14 +++++++++++---
 clang/lib/AST/Expr.cpp                        |  9 ---------
 clang/lib/AST/NestedNameSpecifier.cpp         | 12 ------------
 4 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 30717c3e2fb92..24d8896fb996a 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3227,7 +3227,19 @@ class CallExpr : public Expr {
     return getCallee()->getBeginLoc();
   }
 
-  SourceLocation getEndLoc() const LLVM_READONLY;
+  SourceLocation getEndLoc() const {
+      if(CallExprBits.HasTrailingSourceLoc) {
+          static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
+          return *reinterpret_cast<const 
SourceLocation*>(reinterpret_cast<const char *>(this) +
+                                                          sizeof(CallExpr) + 
sizeof(SourceLocation));
+      }
+
+    SourceLocation end = getRParenLoc();
+    if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
+      end = getArg(getNumArgs() - 1)->getEndLoc();
+    return end;
+  }
+
 
 private:
   friend class ASTStmtReader;
@@ -3239,8 +3251,8 @@ class CallExpr : public Expr {
       static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
       SourceLocation* Locs = 
reinterpret_cast<SourceLocation*>(reinterpret_cast<char *>(this) +
                                                                
sizeof(CallExpr));
-      Locs[0] = getBeginLoc();
-      Locs[1] = getEndLoc();
+      new (Locs) SourceLocation(getBeginLoc());
+      new (Locs+1) SourceLocation(getEndLoc());
       CallExprBits.HasTrailingSourceLoc = true;
   }
 
diff --git a/clang/include/clang/AST/NestedNameSpecifier.h 
b/clang/include/clang/AST/NestedNameSpecifier.h
index d7da3272d0943..83237b788ec18 100644
--- a/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/clang/include/clang/AST/NestedNameSpecifier.h
@@ -283,7 +283,9 @@ class NestedNameSpecifierLoc {
   /// For example, if this instance refers to a nested-name-specifier
   /// \c \::std::vector<int>::, the returned source range would cover
   /// from the initial '::' to the last '::'.
-  SourceRange getSourceRange() const LLVM_READONLY;
+  SourceRange getSourceRange() const LLVM_READONLY {
+    return SourceRange(getBeginLoc(), getEndLoc());
+  }
 
   /// Retrieve the source range covering just the last part of
   /// this nested-name-specifier, not including the prefix.
@@ -296,13 +298,19 @@ class NestedNameSpecifierLoc {
   /// Retrieve the location of the beginning of this
   /// nested-name-specifier.
   SourceLocation getBeginLoc() const {
-    return getSourceRange().getBegin();
+    if (!Qualifier)
+      return SourceLocation();
+
+    NestedNameSpecifierLoc First = *this;
+    while (NestedNameSpecifierLoc Prefix = First.getPrefix())
+      First = Prefix;
+    return First.getLocalSourceRange().getBegin();
   }
 
   /// Retrieve the location of the end of this
   /// nested-name-specifier.
   SourceLocation getEndLoc() const {
-    return getSourceRange().getEnd();
+    return getLocalSourceRange().getEnd();
   }
 
   /// Retrieve the location of the beginning of this
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ace1221bbc439..e1d2b2956a5a0 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1627,15 +1627,6 @@ CallExpr::getUnusedResultAttr(const ASTContext &Ctx) 
const {
   return {nullptr, nullptr};
 }
 
-SourceLocation CallExpr::getEndLoc() const {
-  if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
-    return OCE->getEndLoc();
-
-  SourceLocation end = getRParenLoc();
-  if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
-    end = getArg(getNumArgs() - 1)->getEndLoc();
-  return end;
-}
 
 OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
                                    SourceLocation OperatorLoc,
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp 
b/clang/lib/AST/NestedNameSpecifier.cpp
index bd0fe36d781da..db1ad89565189 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -407,18 +407,6 @@ static void *LoadPointer(void *Data, unsigned Offset) {
   return Result;
 }
 
-SourceRange NestedNameSpecifierLoc::getSourceRange() const {
-  if (!Qualifier)
-    return SourceRange();
-
-  NestedNameSpecifierLoc First = *this;
-  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
-    First = Prefix;
-
-  return SourceRange(First.getLocalSourceRange().getBegin(),
-                     getLocalSourceRange().getEnd());
-}
-
 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
   if (!Qualifier)
     return SourceRange();

>From 99d11a55c0222e8ed64aa35a068a3f08673baaba Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 13:33:23 +0200
Subject: [PATCH 7/8] reset the cache when setting deducing this functions

---
 clang/include/clang/AST/Expr.h | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 24d8896fb996a..0089c2d49a645 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3040,7 +3040,15 @@ class CallExpr : public Expr {
   bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
 
   bool usesMemberSyntax() const { return 
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax; }
-  void setUsesMemberSyntax(bool V = true) { 
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V; }
+  void setUsesMemberSyntax(bool V = true) {
+      CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V;
+      // Because the source location may be different for explicit
+      // member, we reset the cached values.
+      if(CallExprBits.HasTrailingSourceLoc) {
+          CallExprBits.HasTrailingSourceLoc = false;
+          setTrailingSourceLocs();
+      }
+  }
 
   bool isCoroElideSafe() const { return CallExprBits.IsCoroElideSafe; }
   void setCoroElideSafe(bool V = true) { CallExprBits.IsCoroElideSafe = V; }

>From fd4aaf504142aa733ff03c335f3ffcc2e9e889e7 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 22 May 2025 14:20:39 +0200
Subject: [PATCH 8/8] cleanups

---
 clang/include/clang/AST/Expr.h                | 107 +++++++++---------
 clang/include/clang/AST/NestedNameSpecifier.h |   4 +-
 clang/include/clang/AST/Stmt.h                |   6 +-
 clang/lib/AST/Expr.cpp                        |  43 +++++--
 clang/lib/AST/ExprCXX.cpp                     |  42 ++++---
 clang/lib/Sema/SemaOpenCL.cpp                 |   3 +-
 clang/lib/Serialization/ASTReaderStmt.cpp     |   4 +-
 7 files changed, 124 insertions(+), 85 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 0089c2d49a645..2a1b5a838d794 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2907,22 +2907,27 @@ class CallExpr : public Expr {
   //
   // * An optional of type FPOptionsOverride.
   //
-  // Note that we store the offset in bytes from the this pointer to the start
-  // of the trailing objects. It would be perfectly possible to compute it
-  // based on the dynamic kind of the CallExpr. However 1.) we have plenty of
-  // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to
-  // compute this once and then load the offset from the bit-fields of Stmt,
-  // instead of re-computing the offset each time the trailing objects are
-  // accessed.
+  // CallExpr subclasses are asssumed to be 32 bytes or less, and CallExpr
+  // itself is 24 bytes. To avoid having to recompute or store the offset of 
the
+  // trailing objects, we put it at 32 bytes (such that it is suitable for all
+  // subclasses) We use the 8 bytes gap left for instances of CallExpr to store
+  // the begin and end source locations. Caching the begin source location in
+  // particular as a significant impact on perf as getBeginLoc is assumed to be
+  // cheap.
+  // The layourt is as follow:
+  // CallExpr | Begin | End | Trailing Objects
+  // CXXMemberCallExpr | Trailing Objects
+  // A bit in CallExprBitfields indicates if source locations are presents.
 
 protected:
   static constexpr unsigned offsetToTrailingObjects = 32;
-
   template <typename T>
-  static constexpr unsigned sizeToAllocateForCallExprSubclass(unsigned 
SizeOfTrailingObjects) {
+  static constexpr unsigned
+  sizeToAllocateForCallExprSubclass(unsigned SizeOfTrailingObjects) {
     static_assert(sizeof(T) <= CallExpr::offsetToTrailingObjects);
     return SizeOfTrailingObjects + CallExpr::offsetToTrailingObjects;
   }
+
 private:
   /// Return a pointer to the start of the trailing array of "Stmt *".
   Stmt **getTrailingStmts() {
@@ -2992,8 +2997,8 @@ class CallExpr : public Expr {
   const FPOptionsOverride *getTrailingFPFeatures() const {
     assert(hasStoredFPFeatures());
     return reinterpret_cast<const FPOptionsOverride *>(
-        reinterpret_cast<const char *>(this) +
-        offsetToTrailingObjects + getSizeOfTrailingStmts());
+        reinterpret_cast<const char *>(this) + offsetToTrailingObjects +
+        getSizeOfTrailingStmts());
   }
 
 public:
@@ -3039,15 +3044,17 @@ class CallExpr : public Expr {
 
   bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
 
-  bool usesMemberSyntax() const { return 
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax; }
+  bool usesMemberSyntax() const {
+    return CallExprBits.ExplicitObjectMemFunUsingMemberSyntax;
+  }
   void setUsesMemberSyntax(bool V = true) {
-      CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V;
-      // Because the source location may be different for explicit
-      // member, we reset the cached values.
-      if(CallExprBits.HasTrailingSourceLoc) {
-          CallExprBits.HasTrailingSourceLoc = false;
-          setTrailingSourceLocs();
-      }
+    CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V;
+    // Because the source location may be different for explicit
+    // member, we reset the cached values.
+    if (CallExprBits.HasTrailingSourceLocs) {
+      CallExprBits.HasTrailingSourceLocs = false;
+      updateTrailingSourceLocs();
+    }
   }
 
   bool isCoroElideSafe() const { return CallExprBits.IsCoroElideSafe; }
@@ -3209,24 +3216,20 @@ class CallExpr : public Expr {
   SourceLocation getRParenLoc() const { return RParenLoc; }
   void setRParenLoc(SourceLocation L) { RParenLoc = L; }
 
+  template <unsigned N> SourceLocation getTrailingSourceLoc() const {
+    static_assert(N <= 1);
+    assert(CallExprBits.HasTrailingSourceLocs && "No trailing source loc");
+    static_assert(sizeof(CallExpr) <=
+                  offsetToTrailingObjects + 2 * sizeof(SourceLocation));
+    return *reinterpret_cast<const SourceLocation *>(
+        reinterpret_cast<const char *>(this) + sizeof(CallExpr) +
+        sizeof(SourceLocation) * N);
+  }
+
   SourceLocation getBeginLoc() const {
-    if(CallExprBits.HasTrailingSourceLoc) {
-        static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
-        return *reinterpret_cast<const SourceLocation*>(reinterpret_cast<const 
char *>(this) +
-                                                        sizeof(CallExpr));
-    }
+    if (CallExprBits.HasTrailingSourceLocs)
+      return getTrailingSourceLoc<0>();
 
-    //if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
-    //    return OCE->getBeginLoc();
-
-    // A non-dependent call to a member function with an explicit object 
parameter
-    // is modelled with the object expression being the first argument, e.g. in
-    // `o.f(x)`, the callee will be just `f`, and `o` will be the first 
argument.
-    // Since the first argument is written before the callee, the expression's
-    // begin location should come from the first argument.
-    // This does not apply to dependent calls, which are modelled with `o.f`
-    // being the callee.
-    // Because this check is expennsive, we cache the result.
     if (usesMemberSyntax()) {
       if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
         return FirstArgLoc;
@@ -3236,11 +3239,8 @@ class CallExpr : public Expr {
   }
 
   SourceLocation getEndLoc() const {
-      if(CallExprBits.HasTrailingSourceLoc) {
-          static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
-          return *reinterpret_cast<const 
SourceLocation*>(reinterpret_cast<const char *>(this) +
-                                                          sizeof(CallExpr) + 
sizeof(SourceLocation));
-      }
+    if (CallExprBits.HasTrailingSourceLocs)
+      return getTrailingSourceLoc<0>();
 
     SourceLocation end = getRParenLoc();
     if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
@@ -3248,24 +3248,27 @@ class CallExpr : public Expr {
     return end;
   }
 
-
 private:
-  friend class ASTStmtReader;
   bool hasTrailingSourceLoc() const {
-      return CallExprBits.HasTrailingSourceLoc;
+    return CallExprBits.HasTrailingSourceLocs;
   }
-  void setTrailingSourceLocs() {
-      assert(!CallExprBits.HasTrailingSourceLoc);
-      static_assert(sizeof(CallExpr) <= offsetToTrailingObjects + 2 * 
sizeof(SourceLocation));
-      SourceLocation* Locs = 
reinterpret_cast<SourceLocation*>(reinterpret_cast<char *>(this) +
-                                                               
sizeof(CallExpr));
-      new (Locs) SourceLocation(getBeginLoc());
-      new (Locs+1) SourceLocation(getEndLoc());
-      CallExprBits.HasTrailingSourceLoc = true;
+
+  void updateTrailingSourceLocs() {
+    assert(!CallExprBits.HasTrailingSourceLocs &&
+           "Trailing source loc already set?");
+    assert(getStmtClass() == CallExprClass &&
+           "Calling setTrailingSourceLocs on a subclass of CallExpr");
+    static_assert(sizeof(CallExpr) <=
+                  offsetToTrailingObjects + 2 * sizeof(SourceLocation));
+
+    SourceLocation *Locs = reinterpret_cast<SourceLocation *>(
+        reinterpret_cast<char *>(this) + sizeof(CallExpr));
+    new (Locs) SourceLocation(getBeginLoc());
+    new (Locs + 1) SourceLocation(getEndLoc());
+    CallExprBits.HasTrailingSourceLocs = true;
   }
 
 public:
-
   /// Return true if this is a call to __assume() or __builtin_assume() with
   /// a non-value-dependent constant parameter evaluating as false.
   bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;
diff --git a/clang/include/clang/AST/NestedNameSpecifier.h 
b/clang/include/clang/AST/NestedNameSpecifier.h
index 83237b788ec18..952c79753d10a 100644
--- a/clang/include/clang/AST/NestedNameSpecifier.h
+++ b/clang/include/clang/AST/NestedNameSpecifier.h
@@ -309,9 +309,7 @@ class NestedNameSpecifierLoc {
 
   /// Retrieve the location of the end of this
   /// nested-name-specifier.
-  SourceLocation getEndLoc() const {
-    return getLocalSourceRange().getEnd();
-  }
+  SourceLocation getEndLoc() const { return getLocalSourceRange().getEnd(); }
 
   /// Retrieve the location of the beginning of this
   /// component of the nested-name-specifier.
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index 2889fedb4d221..e233f04b2405d 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -566,11 +566,15 @@ class alignas(void *) Stmt {
     LLVM_PREFERRED_TYPE(bool)
     unsigned IsCoroElideSafe : 1;
 
+    /// Tracks When CallExpr is used to represent an explicit object
+    /// member function, in order to adjust the begin location.
     LLVM_PREFERRED_TYPE(bool)
     unsigned ExplicitObjectMemFunUsingMemberSyntax : 1;
 
+    /// Indicates that SourceLocations are cached as
+    /// Trailing objects. See the definition of CallExpr.
     LLVM_PREFERRED_TYPE(bool)
-    unsigned HasTrailingSourceLoc : 1;
+    unsigned HasTrailingSourceLocs : 1;
   };
 
   enum { NumCallExprBits = 25 };
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index e1d2b2956a5a0..7f768665b3157 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1450,6 +1450,23 @@ OverloadedOperatorKind 
UnaryOperator::getOverloadedOperator(Opcode Opc) {
 // Postfix Operators.
 
//===----------------------------------------------------------------------===//
 
+static unsigned SizeOfCallExprInstance(Expr::StmtClass SC) {
+  switch (SC) {
+  case Expr::CallExprClass:
+    return sizeof(CallExpr);
+  case Expr::CXXOperatorCallExprClass:
+    return sizeof(CXXOperatorCallExpr);
+  case Expr::CXXMemberCallExprClass:
+    return sizeof(CXXMemberCallExpr);
+  case Expr::UserDefinedLiteralClass:
+    return sizeof(UserDefinedLiteral);
+  case Expr::CUDAKernelCallExprClass:
+    return sizeof(CUDAKernelCallExpr);
+  default:
+    llvm_unreachable("unexpected class deriving from CallExpr!");
+  }
+}
+
 CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
                    ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
                    SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
@@ -1459,6 +1476,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr 
*> PreArgs,
   unsigned NumPreArgs = PreArgs.size();
   CallExprBits.NumPreArgs = NumPreArgs;
   assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
+  assert(SizeOfCallExprInstance(SC) <= offsetToTrailingObjects &&
+         "This CallExpr subclass is too big or unsupported");
 
   CallExprBits.UsesADL = static_cast<bool>(UsesADL);
 
@@ -1475,7 +1494,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr 
*> PreArgs,
   CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
   CallExprBits.IsCoroElideSafe = false;
   CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
-  CallExprBits.HasTrailingSourceLoc = false;
+  CallExprBits.HasTrailingSourceLocs = false;
 
   if (hasStoredFPFeatures())
     setStoredFPFeatures(FPFeatures);
@@ -1489,8 +1508,7 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, 
unsigned NumArgs,
   CallExprBits.HasFPFeatures = HasFPFeatures;
   CallExprBits.IsCoroElideSafe = false;
   CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
-  CallExprBits.HasTrailingSourceLoc = false;
-
+  CallExprBits.HasTrailingSourceLocs = false;
 }
 
 CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
@@ -1501,12 +1519,13 @@ CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr 
*Fn,
   unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem =
-      
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
-                   alignof(CallExpr));
-  CallExpr* E = new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, 
Ty, VK,
-                            RParenLoc, FPFeatures, MinNumArgs, UsesADL);
-  E->setTrailingSourceLocs();
+  void *Mem = Ctx.Allocate(
+      sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
+      alignof(CallExpr));
+  CallExpr *E =
+      new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
+                         RParenLoc, FPFeatures, MinNumArgs, UsesADL);
+  E->updateTrailingSourceLocs();
   return E;
 }
 
@@ -1514,8 +1533,9 @@ CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, 
unsigned NumArgs,
                                 bool HasFPFeatures, EmptyShell Empty) {
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
-  void *Mem =
-      
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
 alignof(CallExpr));
+  void *Mem = Ctx.Allocate(
+      sizeToAllocateForCallExprSubclass<CallExpr>(SizeOfTrailingObjects),
+      alignof(CallExpr));
   return new (Mem)
       CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, Empty);
 }
@@ -1627,7 +1647,6 @@ CallExpr::getUnusedResultAttr(const ASTContext &Ctx) 
const {
   return {nullptr, nullptr};
 }
 
-
 OffsetOfExpr *OffsetOfExpr::Create(const ASTContext &C, QualType type,
                                    SourceLocation OperatorLoc,
                                    TypeSourceInfo *tsi,
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index c10fae156bef8..5c712e146e5a8 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -619,8 +619,10 @@ CXXOperatorCallExpr::Create(const ASTContext &Ctx,
   unsigned NumArgs = Args.size();
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(SizeOfTrailingObjects),
-                           alignof(CXXOperatorCallExpr));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(
+                       SizeOfTrailingObjects),
+                   alignof(CXXOperatorCallExpr));
   return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc,
                                        FPFeatures, UsesADL);
 }
@@ -632,8 +634,10 @@ CXXOperatorCallExpr 
*CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(SizeOfTrailingObjects),
-                           alignof(CXXOperatorCallExpr));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXOperatorCallExpr>(
+                       SizeOfTrailingObjects),
+                   alignof(CXXOperatorCallExpr));
   return new (Mem) CXXOperatorCallExpr(NumArgs, HasFPFeatures, Empty);
 }
 
@@ -684,7 +688,8 @@ CXXMemberCallExpr *CXXMemberCallExpr::Create(const 
ASTContext &Ctx, Expr *Fn,
   unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(SizeOfTrailingObjects),
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(
+                               SizeOfTrailingObjects),
                            alignof(CXXMemberCallExpr));
   return new (Mem)
       CXXMemberCallExpr(Fn, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
@@ -697,7 +702,8 @@ CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, 
HasFPFeatures);
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(SizeOfTrailingObjects),
+  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CXXMemberCallExpr>(
+                               SizeOfTrailingObjects),
                            alignof(CXXMemberCallExpr));
   return new (Mem) CXXMemberCallExpr(NumArgs, HasFPFeatures, Empty);
 }
@@ -958,8 +964,10 @@ UserDefinedLiteral *UserDefinedLiteral::Create(const 
ASTContext &Ctx, Expr *Fn,
   unsigned NumArgs = Args.size();
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(SizeOfTrailingObjects),
-                           alignof(UserDefinedLiteral));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(
+                       SizeOfTrailingObjects),
+                   alignof(UserDefinedLiteral));
   return new (Mem)
       UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc, FPFeatures);
 }
@@ -971,8 +979,10 @@ UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const 
ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects =
       CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPOptions);
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(SizeOfTrailingObjects),
-                           alignof(UserDefinedLiteral));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<UserDefinedLiteral>(
+                       SizeOfTrailingObjects),
+                   alignof(UserDefinedLiteral));
   return new (Mem) UserDefinedLiteral(NumArgs, HasFPOptions, Empty);
 }
 
@@ -1946,8 +1956,10 @@ CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr 
*Fn, CallExpr *Config,
   unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/END_PREARG, NumArgs, 
FPFeatures.requiresTrailingStorage());
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(SizeOfTrailingObjects),
-                           alignof(CUDAKernelCallExpr));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(
+                       SizeOfTrailingObjects),
+                   alignof(CUDAKernelCallExpr));
   return new (Mem)
       CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, FPFeatures, MinNumArgs);
 }
@@ -1959,8 +1971,10 @@ CUDAKernelCallExpr 
*CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx,
   // Allocate storage for the trailing objects of CallExpr.
   unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
       /*NumPreArgs=*/END_PREARG, NumArgs, HasFPFeatures);
-  void *Mem = 
Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(SizeOfTrailingObjects),
-                           alignof(CUDAKernelCallExpr));
+  void *Mem =
+      Ctx.Allocate(sizeToAllocateForCallExprSubclass<CUDAKernelCallExpr>(
+                       SizeOfTrailingObjects),
+                   alignof(CUDAKernelCallExpr));
   return new (Mem) CUDAKernelCallExpr(NumArgs, HasFPFeatures, Empty);
 }
 
diff --git a/clang/lib/Sema/SemaOpenCL.cpp b/clang/lib/Sema/SemaOpenCL.cpp
index 865c57ae7c158..f11a40e3964ff 100644
--- a/clang/lib/Sema/SemaOpenCL.cpp
+++ b/clang/lib/Sema/SemaOpenCL.cpp
@@ -542,7 +542,8 @@ bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, 
CallExpr *Call) {
   auto RT = Call->getArg(0)->getType();
   if (!RT->isPointerType() ||
       RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
-    Diag(Call->getArg(0)->getBeginLoc(), 
diag::err_opencl_builtin_to_addr_invalid_arg)
+    Diag(Call->getArg(0)->getBeginLoc(),
+         diag::err_opencl_builtin_to_addr_invalid_arg)
         << Call->getArg(0) << Call->getDirectCallee() << 
Call->getSourceRange();
     return true;
   }
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index a07bc0854e25d..5827799d91e1b 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1048,8 +1048,8 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) {
     E->setStoredFPFeatures(
         FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
 
-  if(E->getStmtClass() == Stmt::CallExprClass)
-    E->setTrailingSourceLocs();
+  if (E->getStmtClass() == Stmt::CallExprClass)
+    E->updateTrailingSourceLocs();
 }
 
 void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {

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

Reply via email to