@@ -1344,7 +1344,13 @@ class DeclRefExpr final
13441344
13451345 SourceLocation getLocation () const { return DeclRefExprBits.Loc ; }
13461346 void setLocation (SourceLocation L) { DeclRefExprBits.Loc = L; }
1347- SourceLocation getBeginLoc () const LLVM_READONLY;
1347+
1348+ SourceLocation getBeginLoc () const {
1349+ if (hasQualifier ())
1350+ return getQualifierLoc ().getBeginLoc ();
1351+ return DeclRefExprBits.Loc ;
1352+ }
1353+
13481354 SourceLocation getEndLoc () const LLVM_READONLY;
13491355
13501356 // / Determine whether this declaration reference was preceded by a
@@ -2901,34 +2907,43 @@ class CallExpr : public Expr {
29012907 //
29022908 // * An optional of type FPOptionsOverride.
29032909 //
2904- // Note that we store the offset in bytes from the this pointer to the start
2905- // of the trailing objects. It would be perfectly possible to compute it
2906- // based on the dynamic kind of the CallExpr. However 1.) we have plenty of
2907- // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to
2908- // compute this once and then load the offset from the bit-fields of Stmt,
2909- // instead of re-computing the offset each time the trailing objects are
2910- // accessed.
2910+ // CallExpr subclasses are asssumed to be 32 bytes or less, and CallExpr
2911+ // itself is 24 bytes. To avoid having to recompute or store the offset of the
2912+ // trailing objects, we put it at 32 bytes (such that it is suitable for all
2913+ // subclasses) We use the 8 bytes gap left for instances of CallExpr to store
2914+ // the begin source location, which has a significant impact on perf as
2915+ // getBeginLoc is assumed to be cheap.
2916+ // The layourt is as follow:
2917+ // CallExpr | Begin | 4 bytes left | Trailing Objects
2918+ // CXXMemberCallExpr | Trailing Objects
2919+ // A bit in CallExprBitfields indicates if source locations are present.
29112920
2921+ protected:
2922+ static constexpr unsigned OffsetToTrailingObjects = 32 ;
2923+ template <typename T>
2924+ static constexpr unsigned
2925+ sizeToAllocateForCallExprSubclass (unsigned SizeOfTrailingObjects) {
2926+ static_assert (sizeof (T) <= CallExpr::OffsetToTrailingObjects);
2927+ return SizeOfTrailingObjects + CallExpr::OffsetToTrailingObjects;
2928+ }
2929+
2930+ private:
29122931 // / Return a pointer to the start of the trailing array of "Stmt *".
29132932 Stmt **getTrailingStmts () {
29142933 return reinterpret_cast <Stmt **>(reinterpret_cast <char *>(this ) +
2915- CallExprBits. OffsetToTrailingObjects );
2934+ OffsetToTrailingObjects);
29162935 }
29172936 Stmt *const *getTrailingStmts () const {
29182937 return const_cast <CallExpr *>(this )->getTrailingStmts ();
29192938 }
29202939
2921- // / Map a statement class to the appropriate offset in bytes from the
2922- // / this pointer to the trailing objects.
2923- static unsigned offsetToTrailingObjects (StmtClass SC);
2924-
29252940 unsigned getSizeOfTrailingStmts () const {
29262941 return (1 + getNumPreArgs () + getNumArgs ()) * sizeof (Stmt *);
29272942 }
29282943
29292944 size_t getOffsetOfTrailingFPFeatures () const {
29302945 assert (hasStoredFPFeatures ());
2931- return CallExprBits. OffsetToTrailingObjects + getSizeOfTrailingStmts ();
2946+ return OffsetToTrailingObjects + getSizeOfTrailingStmts ();
29322947 }
29332948
29342949public:
@@ -2975,14 +2990,14 @@ class CallExpr : public Expr {
29752990 FPOptionsOverride *getTrailingFPFeatures () {
29762991 assert (hasStoredFPFeatures ());
29772992 return reinterpret_cast <FPOptionsOverride *>(
2978- reinterpret_cast <char *>(this ) + CallExprBits. OffsetToTrailingObjects +
2993+ reinterpret_cast <char *>(this ) + OffsetToTrailingObjects +
29792994 getSizeOfTrailingStmts ());
29802995 }
29812996 const FPOptionsOverride *getTrailingFPFeatures () const {
29822997 assert (hasStoredFPFeatures ());
29832998 return reinterpret_cast <const FPOptionsOverride *>(
2984- reinterpret_cast <const char *>(this ) +
2985- CallExprBits. OffsetToTrailingObjects + getSizeOfTrailingStmts ());
2999+ reinterpret_cast <const char *>(this ) + OffsetToTrailingObjects +
3000+ getSizeOfTrailingStmts ());
29863001 }
29873002
29883003public:
@@ -3028,6 +3043,19 @@ class CallExpr : public Expr {
30283043
30293044 bool hasStoredFPFeatures () const { return CallExprBits.HasFPFeatures ; }
30303045
3046+ bool usesMemberSyntax () const {
3047+ return CallExprBits.ExplicitObjectMemFunUsingMemberSyntax ;
3048+ }
3049+ void setUsesMemberSyntax (bool V = true ) {
3050+ CallExprBits.ExplicitObjectMemFunUsingMemberSyntax = V;
3051+ // Because the source location may be different for explicit
3052+ // member, we reset the cached values.
3053+ if (CallExprBits.HasTrailingSourceLoc ) {
3054+ CallExprBits.HasTrailingSourceLoc = false ;
3055+ updateTrailingSourceLoc ();
3056+ }
3057+ }
3058+
30313059 bool isCoroElideSafe () const { return CallExprBits.IsCoroElideSafe ; }
30323060 void setCoroElideSafe (bool V = true ) { CallExprBits.IsCoroElideSafe = V; }
30333061
@@ -3187,9 +3215,48 @@ class CallExpr : public Expr {
31873215 SourceLocation getRParenLoc () const { return RParenLoc; }
31883216 void setRParenLoc (SourceLocation L) { RParenLoc = L; }
31893217
3190- SourceLocation getBeginLoc () const LLVM_READONLY;
3191- SourceLocation getEndLoc () const LLVM_READONLY;
3218+ SourceLocation getBeginLoc () const {
3219+ if (CallExprBits.HasTrailingSourceLoc ) {
3220+ static_assert (sizeof (CallExpr) <=
3221+ OffsetToTrailingObjects + sizeof (SourceLocation));
3222+ return *reinterpret_cast <const SourceLocation *>(
3223+ reinterpret_cast <const char *>(this + 1 ));
3224+ }
3225+
3226+ if (usesMemberSyntax ())
3227+ if (auto FirstArgLoc = getArg (0 )->getBeginLoc (); FirstArgLoc.isValid ())
3228+ return FirstArgLoc;
3229+
3230+ // FIXME: Some builtins have no callee begin location
3231+ SourceLocation begin = getCallee ()->getBeginLoc ();
3232+ if (begin.isInvalid () && getNumArgs () > 0 && getArg (0 ))
3233+ begin = getArg (0 )->getBeginLoc ();
3234+ return begin;
3235+ }
3236+
3237+ SourceLocation getEndLoc () const { return getRParenLoc (); }
31923238
3239+ private:
3240+ friend class ASTStmtReader ;
3241+ bool hasTrailingSourceLoc () const {
3242+ return CallExprBits.HasTrailingSourceLoc ;
3243+ }
3244+
3245+ void updateTrailingSourceLoc () {
3246+ assert (!CallExprBits.HasTrailingSourceLoc &&
3247+ " Trailing source loc already set?" );
3248+ assert (getStmtClass () == CallExprClass &&
3249+ " Calling setTrailingSourceLocs on a subclass of CallExpr" );
3250+ static_assert (sizeof (CallExpr) <=
3251+ OffsetToTrailingObjects + sizeof (SourceLocation));
3252+
3253+ SourceLocation *Locs =
3254+ reinterpret_cast <SourceLocation *>(reinterpret_cast <char *>(this + 1 ));
3255+ new (Locs) SourceLocation (getBeginLoc ());
3256+ CallExprBits.HasTrailingSourceLoc = true ;
3257+ }
3258+
3259+ public:
31933260 // / Return true if this is a call to __assume() or __builtin_assume() with
31943261 // / a non-value-dependent constant parameter evaluating as false.
31953262 bool isBuiltinAssumeFalse (const ASTContext &Ctx) const ;
0 commit comments