[clang] [Clang] Optimize some `getBeginLoc` implementations (PR #141058)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 22 06:01:20 PDT 2025
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/141058
>From 381c2219e346acfbf5b61e93fcc3233af6b7c3a7 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 21 May 2025 23:09:00 +0200
Subject: [PATCH 1/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 00:28:05 +0200
Subject: [PATCH 2/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 01:29:19 +0200
Subject: [PATCH 3/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 09:40:01 +0200
Subject: [PATCH 4/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 10:34:24 +0200
Subject: [PATCH 5/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 12:36:32 +0200
Subject: [PATCH 6/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 13:33:23 +0200
Subject: [PATCH 7/9] 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 <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 14:20:39 +0200
Subject: [PATCH 8/9] 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) {
>From 63a8b545ce7c892409c4799648813807f7ff7e43 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 22 May 2025 15:00:57 +0200
Subject: [PATCH 9/9] Storing the endloc is not necessary (and was done
incorrectly)
---
clang/include/clang/AST/Expr.h | 50 +++++++++--------------
clang/include/clang/AST/Stmt.h | 2 +-
clang/lib/AST/Expr.cpp | 6 +--
clang/lib/Serialization/ASTReaderStmt.cpp | 2 +-
4 files changed, 24 insertions(+), 36 deletions(-)
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2a1b5a838d794..613a6e1e0d833 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -2911,11 +2911,10 @@ class CallExpr : public Expr {
// 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 begin source location, which has a significant impact on perf as
+ // getBeginLoc is assumed to be cheap.
// The layourt is as follow:
- // CallExpr | Begin | End | Trailing Objects
+ // CallExpr | Begin | 4 bytes left | Trailing Objects
// CXXMemberCallExpr | Trailing Objects
// A bit in CallExprBitfields indicates if source locations are presents.
@@ -3051,9 +3050,9 @@ class CallExpr : public Expr {
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();
+ if (CallExprBits.HasTrailingSourceLoc) {
+ CallExprBits.HasTrailingSourceLoc = false;
+ updateTrailingSourceLoc();
}
}
@@ -3216,19 +3215,14 @@ 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.HasTrailingSourceLocs)
- return getTrailingSourceLoc<0>();
+ if (CallExprBits.HasTrailingSourceLoc) {
+ assert(CallExprBits.HasTrailingSourceLoc && "No trailing source loc");
+ static_assert(sizeof(CallExpr) <=
+ offsetToTrailingObjects + sizeof(SourceLocation));
+ return *reinterpret_cast<const SourceLocation *>(
+ reinterpret_cast<const char *>(this) + sizeof(CallExpr));
+ }
if (usesMemberSyntax()) {
if (auto FirstArgLoc = getArg(0)->getBeginLoc(); FirstArgLoc.isValid()) {
@@ -3239,22 +3233,17 @@ class CallExpr : public Expr {
}
SourceLocation getEndLoc() const {
- if (CallExprBits.HasTrailingSourceLocs)
- return getTrailingSourceLoc<0>();
-
- SourceLocation end = getRParenLoc();
- if (end.isInvalid() && getNumArgs() > 0 && getArg(getNumArgs() - 1))
- end = getArg(getNumArgs() - 1)->getEndLoc();
- return end;
+ return getRParenLoc();
}
private:
+ friend class ASTStmtReader;
bool hasTrailingSourceLoc() const {
- return CallExprBits.HasTrailingSourceLocs;
+ return CallExprBits.HasTrailingSourceLoc;
}
- void updateTrailingSourceLocs() {
- assert(!CallExprBits.HasTrailingSourceLocs &&
+ void updateTrailingSourceLoc() {
+ assert(!CallExprBits.HasTrailingSourceLoc &&
"Trailing source loc already set?");
assert(getStmtClass() == CallExprClass &&
"Calling setTrailingSourceLocs on a subclass of CallExpr");
@@ -3264,8 +3253,7 @@ class CallExpr : public Expr {
SourceLocation *Locs = reinterpret_cast<SourceLocation *>(
reinterpret_cast<char *>(this) + sizeof(CallExpr));
new (Locs) SourceLocation(getBeginLoc());
- new (Locs + 1) SourceLocation(getEndLoc());
- CallExprBits.HasTrailingSourceLocs = true;
+ CallExprBits.HasTrailingSourceLoc = true;
}
public:
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index e233f04b2405d..f7a2c6cce3795 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -574,7 +574,7 @@ class alignas(void *) Stmt {
/// Indicates that SourceLocations are cached as
/// Trailing objects. See the definition of CallExpr.
LLVM_PREFERRED_TYPE(bool)
- unsigned HasTrailingSourceLocs : 1;
+ unsigned HasTrailingSourceLoc : 1;
};
enum { NumCallExprBits = 25 };
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 7f768665b3157..6463b2225f1ac 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1494,7 +1494,7 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
CallExprBits.IsCoroElideSafe = false;
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
- CallExprBits.HasTrailingSourceLocs = false;
+ CallExprBits.HasTrailingSourceLoc = false;
if (hasStoredFPFeatures())
setStoredFPFeatures(FPFeatures);
@@ -1508,7 +1508,7 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
CallExprBits.HasFPFeatures = HasFPFeatures;
CallExprBits.IsCoroElideSafe = false;
CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = false;
- CallExprBits.HasTrailingSourceLocs = false;
+ CallExprBits.HasTrailingSourceLoc = false;
}
CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
@@ -1525,7 +1525,7 @@ CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
CallExpr *E =
new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
RParenLoc, FPFeatures, MinNumArgs, UsesADL);
- E->updateTrailingSourceLocs();
+ E->updateTrailingSourceLoc();
return E;
}
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 5827799d91e1b..f327a7b355868 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1049,7 +1049,7 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) {
FPOptionsOverride::getFromOpaqueInt(Record.readInt()));
if (E->getStmtClass() == Stmt::CallExprClass)
- E->updateTrailingSourceLocs();
+ E->updateTrailingSourceLoc();
}
void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
More information about the cfe-commits
mailing list