Skip to content

Commit 70e7aa4

Browse files
committed
[AST][FPEnv] Keep FP options in trailing storage of CallExpr
This change allow a CallExpr to have optional FPOptionsOverride object, stored in trailing storage. The implementaion is made similar to the way used in BinaryOperator. Differential Revision: https://reviews.llvm.org/D84343
1 parent 367d0d4 commit 70e7aa4

19 files changed

+338
-156
lines changed

clang/include/clang/AST/Expr.h

+79-17
Original file line numberDiff line numberDiff line change
@@ -2272,12 +2272,12 @@ class UnaryOperator final
22722272
/// Is FPFeatures in Trailing Storage?
22732273
bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; }
22742274

2275-
protected:
2276-
/// Get FPFeatures from trailing storage
2275+
/// Get FPFeatures from trailing storage.
22772276
FPOptionsOverride getStoredFPFeatures() const {
22782277
return getTrailingFPFeatures();
22792278
}
22802279

2280+
protected:
22812281
/// Set FPFeatures in trailing storage, used only by Serialization
22822282
void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; }
22832283

@@ -2787,6 +2787,8 @@ class CallExpr : public Expr {
27872787
//
27882788
// * An array of getNumArgs() "Stmt *" for the argument expressions.
27892789
//
2790+
// * An optional of type FPOptionsOverride.
2791+
//
27902792
// Note that we store the offset in bytes from the this pointer to the start
27912793
// of the trailing objects. It would be perfectly possible to compute it
27922794
// based on the dynamic kind of the CallExpr. However 1.) we have plenty of
@@ -2808,6 +2810,15 @@ class CallExpr : public Expr {
28082810
/// this pointer to the trailing objects.
28092811
static unsigned offsetToTrailingObjects(StmtClass SC);
28102812

2813+
unsigned getSizeOfTrailingStmts() const {
2814+
return (1 + getNumPreArgs() + getNumArgs()) * sizeof(Stmt *);
2815+
}
2816+
2817+
size_t getOffsetOfTrailingFPFeatures() const {
2818+
assert(hasStoredFPFeatures());
2819+
return CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts();
2820+
}
2821+
28112822
public:
28122823
enum class ADLCallKind : bool { NotADL, UsesADL };
28132824
static constexpr ADLCallKind NotADL = ADLCallKind::NotADL;
@@ -2818,16 +2829,19 @@ class CallExpr : public Expr {
28182829
/// allocated for the trailing objects.
28192830
CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
28202831
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
2821-
SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL);
2832+
SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
2833+
unsigned MinNumArgs, ADLCallKind UsesADL);
28222834

28232835
/// Build an empty call expression, for deserialization.
28242836
CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
2825-
EmptyShell Empty);
2837+
bool hasFPFeatures, EmptyShell Empty);
28262838

28272839
/// Return the size in bytes needed for the trailing objects.
28282840
/// Used by the derived classes to allocate the right amount of storage.
2829-
static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) {
2830-
return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *);
2841+
static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs,
2842+
bool HasFPFeatures) {
2843+
return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *) +
2844+
HasFPFeatures * sizeof(FPOptionsOverride);
28312845
}
28322846

28332847
Stmt *getPreArg(unsigned I) {
@@ -2845,22 +2859,43 @@ class CallExpr : public Expr {
28452859

28462860
unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; }
28472861

2862+
/// Return a pointer to the trailing FPOptions
2863+
FPOptionsOverride *getTrailingFPFeatures() {
2864+
assert(hasStoredFPFeatures());
2865+
return reinterpret_cast<FPOptionsOverride *>(
2866+
reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects +
2867+
getSizeOfTrailingStmts());
2868+
}
2869+
const FPOptionsOverride *getTrailingFPFeatures() const {
2870+
assert(hasStoredFPFeatures());
2871+
return reinterpret_cast<const FPOptionsOverride *>(
2872+
reinterpret_cast<const char *>(this) +
2873+
CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts());
2874+
}
2875+
28482876
public:
2849-
/// Create a call expression. Fn is the callee expression, Args is the
2850-
/// argument array, Ty is the type of the call expression (which is *not*
2851-
/// the return type in general), VK is the value kind of the call expression
2852-
/// (lvalue, rvalue, ...), and RParenLoc is the location of the right
2853-
/// parenthese in the call expression. MinNumArgs specifies the minimum
2854-
/// number of arguments. The actual number of arguments will be the greater
2855-
/// of Args.size() and MinNumArgs. This is used in a few places to allocate
2856-
/// enough storage for the default arguments. UsesADL specifies whether the
2857-
/// callee was found through argument-dependent lookup.
2877+
/// Create a call expression.
2878+
/// \param Fn The callee expression,
2879+
/// \param Args The argument array,
2880+
/// \param Ty The type of the call expression (which is *not* the return
2881+
/// type in general),
2882+
/// \param VK The value kind of the call expression (lvalue, rvalue, ...),
2883+
/// \param RParenLoc The location of the right parenthesis in the call
2884+
/// expression.
2885+
/// \param FPFeatures Floating-point features associated with the call,
2886+
/// \param MinNumArgs Specifies the minimum number of arguments. The actual
2887+
/// number of arguments will be the greater of Args.size()
2888+
/// and MinNumArgs. This is used in a few places to allocate
2889+
/// enough storage for the default arguments.
2890+
/// \param UsesADL Specifies whether the callee was found through
2891+
/// argument-dependent lookup.
28582892
///
28592893
/// Note that you can use CreateTemporary if you need a temporary call
28602894
/// expression on the stack.
28612895
static CallExpr *Create(const ASTContext &Ctx, Expr *Fn,
28622896
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
2863-
SourceLocation RParenLoc, unsigned MinNumArgs = 0,
2897+
SourceLocation RParenLoc,
2898+
FPOptionsOverride FPFeatures, unsigned MinNumArgs = 0,
28642899
ADLCallKind UsesADL = NotADL);
28652900

28662901
/// Create a temporary call expression with no arguments in the memory
@@ -2877,7 +2912,7 @@ class CallExpr : public Expr {
28772912

28782913
/// Create an empty call expression, for deserialization.
28792914
static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
2880-
EmptyShell Empty);
2915+
bool HasFPFeatures, EmptyShell Empty);
28812916

28822917
Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); }
28832918
const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); }
@@ -2891,6 +2926,8 @@ class CallExpr : public Expr {
28912926
}
28922927
bool usesADL() const { return getADLCallKind() == UsesADL; }
28932928

2929+
bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; }
2930+
28942931
Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); }
28952932
const Decl *getCalleeDecl() const {
28962933
return getCallee()->getReferencedDeclOfCallee();
@@ -2983,6 +3020,31 @@ class CallExpr : public Expr {
29833020
/// this function call.
29843021
unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; }
29853022

3023+
/// Get FPOptionsOverride from trailing storage.
3024+
FPOptionsOverride getStoredFPFeatures() const {
3025+
assert(hasStoredFPFeatures());
3026+
return *getTrailingFPFeatures();
3027+
}
3028+
/// Set FPOptionsOverride in trailing storage. Used only by Serialization.
3029+
void setStoredFPFeatures(FPOptionsOverride F) {
3030+
assert(hasStoredFPFeatures());
3031+
*getTrailingFPFeatures() = F;
3032+
}
3033+
3034+
// Get the FP features status of this operator. Only meaningful for
3035+
// operations on floating point types.
3036+
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const {
3037+
if (hasStoredFPFeatures())
3038+
return getStoredFPFeatures().applyOverrides(LO);
3039+
return FPOptions::defaultWithoutTrailingStorage(LO);
3040+
}
3041+
3042+
FPOptionsOverride getFPFeatures() const {
3043+
if (hasStoredFPFeatures())
3044+
return getStoredFPFeatures();
3045+
return FPOptionsOverride();
3046+
}
3047+
29863048
/// getBuiltinCallee - If this is a call to a builtin, return the builtin ID
29873049
/// of the callee. If not, return 0.
29883050
unsigned getBuiltinCallee() const;

clang/include/clang/AST/ExprCXX.h

+21-19
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ class CXXOperatorCallExpr final : public CallExpr {
8484
friend class ASTStmtWriter;
8585

8686
SourceRange Range;
87-
FPOptionsOverride Overrides;
8887

8988
// CXXOperatorCallExpr has some trailing objects belonging
9089
// to CallExpr. See CallExpr for the details.
@@ -96,7 +95,7 @@ class CXXOperatorCallExpr final : public CallExpr {
9695
SourceLocation OperatorLoc, FPOptionsOverride FPFeatures,
9796
ADLCallKind UsesADL);
9897

99-
CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty);
98+
CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
10099

101100
public:
102101
static CXXOperatorCallExpr *
@@ -106,7 +105,8 @@ class CXXOperatorCallExpr final : public CallExpr {
106105
ADLCallKind UsesADL = NotADL);
107106

108107
static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx,
109-
unsigned NumArgs, EmptyShell Empty);
108+
unsigned NumArgs, bool HasFPFeatures,
109+
EmptyShell Empty);
110110

111111
/// Returns the kind of overloaded operator that this expression refers to.
112112
OverloadedOperatorKind getOperator() const {
@@ -164,11 +164,6 @@ class CXXOperatorCallExpr final : public CallExpr {
164164
static bool classof(const Stmt *T) {
165165
return T->getStmtClass() == CXXOperatorCallExprClass;
166166
}
167-
168-
// Set the FPFeatures status of this operator. Only meaningful for
169-
// operations on floating point types.
170-
void setFPFeatures(FPOptionsOverride F) { Overrides = F; }
171-
FPOptionsOverride getFPFeatures() const { return Overrides; }
172167
};
173168

174169
/// Represents a call to a member function that
@@ -184,18 +179,20 @@ class CXXMemberCallExpr final : public CallExpr {
184179
// to CallExpr. See CallExpr for the details.
185180

186181
CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
187-
ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs);
182+
ExprValueKind VK, SourceLocation RP,
183+
FPOptionsOverride FPOptions, unsigned MinNumArgs);
188184

189-
CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty);
185+
CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
190186

191187
public:
192188
static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
193189
ArrayRef<Expr *> Args, QualType Ty,
194190
ExprValueKind VK, SourceLocation RP,
191+
FPOptionsOverride FPFeatures,
195192
unsigned MinNumArgs = 0);
196193

197194
static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
198-
EmptyShell Empty);
195+
bool HasFPFeatures, EmptyShell Empty);
199196

200197
/// Retrieve the implicit object argument for the member call.
201198
///
@@ -242,18 +239,21 @@ class CUDAKernelCallExpr final : public CallExpr {
242239

243240
CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args,
244241
QualType Ty, ExprValueKind VK, SourceLocation RP,
245-
unsigned MinNumArgs);
242+
FPOptionsOverride FPFeatures, unsigned MinNumArgs);
246243

247-
CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty);
244+
CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
248245

249246
public:
250247
static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn,
251248
CallExpr *Config, ArrayRef<Expr *> Args,
252249
QualType Ty, ExprValueKind VK,
253-
SourceLocation RP, unsigned MinNumArgs = 0);
250+
SourceLocation RP,
251+
FPOptionsOverride FPFeatures,
252+
unsigned MinNumArgs = 0);
254253

255254
static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx,
256-
unsigned NumArgs, EmptyShell Empty);
255+
unsigned NumArgs, bool HasFPFeatures,
256+
EmptyShell Empty);
257257

258258
const CallExpr *getConfig() const {
259259
return cast_or_null<CallExpr>(getPreArg(CONFIG));
@@ -619,18 +619,20 @@ class UserDefinedLiteral final : public CallExpr {
619619

620620
UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty,
621621
ExprValueKind VK, SourceLocation LitEndLoc,
622-
SourceLocation SuffixLoc);
622+
SourceLocation SuffixLoc, FPOptionsOverride FPFeatures);
623623

624-
UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty);
624+
UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty);
625625

626626
public:
627627
static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn,
628628
ArrayRef<Expr *> Args, QualType Ty,
629629
ExprValueKind VK, SourceLocation LitEndLoc,
630-
SourceLocation SuffixLoc);
630+
SourceLocation SuffixLoc,
631+
FPOptionsOverride FPFeatures);
631632

632633
static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx,
633-
unsigned NumArgs, EmptyShell Empty);
634+
unsigned NumArgs, bool HasFPOptions,
635+
EmptyShell Empty);
634636

635637
/// The kind of literal operator which is invoked.
636638
enum LiteralOperatorKind {

clang/include/clang/AST/Stmt.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,11 @@ class alignas(void *) Stmt {
464464
/// True if the callee of the call expression was found using ADL.
465465
unsigned UsesADL : 1;
466466

467+
/// True if the call expression has some floating-point features.
468+
unsigned HasFPFeatures : 1;
469+
467470
/// Padding used to align OffsetToTrailingObjects to a byte multiple.
468-
unsigned : 24 - 2 - NumExprBits;
471+
unsigned : 24 - 3 - NumExprBits;
469472

470473
/// The offset in bytes from the this pointer to the start of the
471474
/// trailing objects belonging to CallExpr. Intentionally byte sized

clang/include/clang/AST/TextNodeDumper.h

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class TextNodeDumper
155155
const comments::CommandTraits *Traits = nullptr;
156156

157157
const char *getCommandName(unsigned CommandID);
158+
void printFPOptions(FPOptionsOverride FPO);
158159

159160
void dumpAPValueChildren(const APValue &Value, QualType Ty,
160161
const APValue &(*IdxToChildFun)(const APValue &,

clang/lib/AST/ASTImporter.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -7338,7 +7338,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
73387338
return std::move(Err);
73397339

73407340
return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs,
7341-
ToType, E->getValueKind(), ToRParenLoc);
7341+
ToType, E->getValueKind(), ToRParenLoc,
7342+
E->getFPFeatures());
73427343
}
73437344

73447345
ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) {
@@ -7648,8 +7649,8 @@ ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) {
76487649
}
76497650

76507651
return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType,
7651-
E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0,
7652-
E->getADLCallKind());
7652+
E->getValueKind(), ToRParenLoc, E->getFPFeatures(),
7653+
/*MinNumArgs=*/0, E->getADLCallKind());
76537654
}
76547655

76557656
ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {

clang/lib/AST/Expr.cpp

+18-11
Original file line numberDiff line numberDiff line change
@@ -1303,8 +1303,8 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) {
13031303

13041304
CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
13051305
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
1306-
SourceLocation RParenLoc, unsigned MinNumArgs,
1307-
ADLCallKind UsesADL)
1306+
SourceLocation RParenLoc, FPOptionsOverride FPFeatures,
1307+
unsigned MinNumArgs, ADLCallKind UsesADL)
13081308
: Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) {
13091309
NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
13101310
unsigned NumPreArgs = PreArgs.size();
@@ -1327,10 +1327,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs,
13271327
setArg(I, nullptr);
13281328

13291329
setDependence(computeDependence(this, PreArgs));
1330+
1331+
CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
1332+
if (hasStoredFPFeatures())
1333+
setStoredFPFeatures(FPFeatures);
13301334
}
13311335

13321336
CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
1333-
EmptyShell Empty)
1337+
bool HasFPFeatures, EmptyShell Empty)
13341338
: Expr(SC, Empty), NumArgs(NumArgs) {
13351339
CallExprBits.NumPreArgs = NumPreArgs;
13361340
assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!");
@@ -1339,19 +1343,21 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs,
13391343
CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects;
13401344
assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) &&
13411345
"OffsetToTrailingObjects overflow!");
1346+
CallExprBits.HasFPFeatures = HasFPFeatures;
13421347
}
13431348

13441349
CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn,
13451350
ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK,
1346-
SourceLocation RParenLoc, unsigned MinNumArgs,
1351+
SourceLocation RParenLoc,
1352+
FPOptionsOverride FPFeatures, unsigned MinNumArgs,
13471353
ADLCallKind UsesADL) {
13481354
unsigned NumArgs = std::max<unsigned>(Args.size(), MinNumArgs);
1349-
unsigned SizeOfTrailingObjects =
1350-
CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
1355+
unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects(
1356+
/*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage());
13511357
void *Mem =
13521358
Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
13531359
return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK,
1354-
RParenLoc, MinNumArgs, UsesADL);
1360+
RParenLoc, FPFeatures, MinNumArgs, UsesADL);
13551361
}
13561362

13571363
CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
@@ -1360,17 +1366,18 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty,
13601366
assert(!(reinterpret_cast<uintptr_t>(Mem) % alignof(CallExpr)) &&
13611367
"Misaligned memory in CallExpr::CreateTemporary!");
13621368
return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty,
1363-
VK, RParenLoc,
1369+
VK, RParenLoc, FPOptionsOverride(),
13641370
/*MinNumArgs=*/0, UsesADL);
13651371
}
13661372

13671373
CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs,
1368-
EmptyShell Empty) {
1374+
bool HasFPFeatures, EmptyShell Empty) {
13691375
unsigned SizeOfTrailingObjects =
1370-
CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs);
1376+
CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures);
13711377
void *Mem =
13721378
Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr));
1373-
return new (Mem) CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty);
1379+
return new (Mem)
1380+
CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, Empty);
13741381
}
13751382

13761383
unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) {

0 commit comments

Comments
 (0)