@@ -1344,7 +1344,13 @@ class DeclRefExpr final
1344
1344
1345
1345
SourceLocation getLocation () const { return DeclRefExprBits.Loc ; }
1346
1346
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
+
1348
1354
SourceLocation getEndLoc () const LLVM_READONLY;
1349
1355
1350
1356
// / Determine whether this declaration reference was preceded by a
@@ -2901,34 +2907,43 @@ class CallExpr : public Expr {
2901
2907
//
2902
2908
// * An optional of type FPOptionsOverride.
2903
2909
//
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.
2911
2920
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:
2912
2931
// / Return a pointer to the start of the trailing array of "Stmt *".
2913
2932
Stmt **getTrailingStmts () {
2914
2933
return reinterpret_cast <Stmt **>(reinterpret_cast <char *>(this ) +
2915
- CallExprBits. OffsetToTrailingObjects );
2934
+ OffsetToTrailingObjects);
2916
2935
}
2917
2936
Stmt *const *getTrailingStmts () const {
2918
2937
return const_cast <CallExpr *>(this )->getTrailingStmts ();
2919
2938
}
2920
2939
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
-
2925
2940
unsigned getSizeOfTrailingStmts () const {
2926
2941
return (1 + getNumPreArgs () + getNumArgs ()) * sizeof (Stmt *);
2927
2942
}
2928
2943
2929
2944
size_t getOffsetOfTrailingFPFeatures () const {
2930
2945
assert (hasStoredFPFeatures ());
2931
- return CallExprBits. OffsetToTrailingObjects + getSizeOfTrailingStmts ();
2946
+ return OffsetToTrailingObjects + getSizeOfTrailingStmts ();
2932
2947
}
2933
2948
2934
2949
public:
@@ -2975,14 +2990,14 @@ class CallExpr : public Expr {
2975
2990
FPOptionsOverride *getTrailingFPFeatures () {
2976
2991
assert (hasStoredFPFeatures ());
2977
2992
return reinterpret_cast <FPOptionsOverride *>(
2978
- reinterpret_cast <char *>(this ) + CallExprBits. OffsetToTrailingObjects +
2993
+ reinterpret_cast <char *>(this ) + OffsetToTrailingObjects +
2979
2994
getSizeOfTrailingStmts ());
2980
2995
}
2981
2996
const FPOptionsOverride *getTrailingFPFeatures () const {
2982
2997
assert (hasStoredFPFeatures ());
2983
2998
return reinterpret_cast <const FPOptionsOverride *>(
2984
- reinterpret_cast <const char *>(this ) +
2985
- CallExprBits. OffsetToTrailingObjects + getSizeOfTrailingStmts ());
2999
+ reinterpret_cast <const char *>(this ) + OffsetToTrailingObjects +
3000
+ getSizeOfTrailingStmts ());
2986
3001
}
2987
3002
2988
3003
public:
@@ -3028,6 +3043,19 @@ class CallExpr : public Expr {
3028
3043
3029
3044
bool hasStoredFPFeatures () const { return CallExprBits.HasFPFeatures ; }
3030
3045
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
+
3031
3059
bool isCoroElideSafe () const { return CallExprBits.IsCoroElideSafe ; }
3032
3060
void setCoroElideSafe (bool V = true ) { CallExprBits.IsCoroElideSafe = V; }
3033
3061
@@ -3187,9 +3215,48 @@ class CallExpr : public Expr {
3187
3215
SourceLocation getRParenLoc () const { return RParenLoc; }
3188
3216
void setRParenLoc (SourceLocation L) { RParenLoc = L; }
3189
3217
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 (); }
3192
3238
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:
3193
3260
// / Return true if this is a call to __assume() or __builtin_assume() with
3194
3261
// / a non-value-dependent constant parameter evaluating as false.
3195
3262
bool isBuiltinAssumeFalse (const ASTContext &Ctx) const ;
0 commit comments