diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2272,12 +2272,12 @@ /// Is FPFeatures in Trailing Storage? bool hasStoredFPFeatures() const { return UnaryOperatorBits.HasFPFeatures; } -protected: - /// Get FPFeatures from trailing storage + /// Get FPFeatures from trailing storage. FPOptionsOverride getStoredFPFeatures() const { return getTrailingFPFeatures(); } +protected: /// Set FPFeatures in trailing storage, used only by Serialization void setStoredFPFeatures(FPOptionsOverride F) { getTrailingFPFeatures() = F; } @@ -2787,6 +2787,8 @@ // // * An array of getNumArgs() "Stmt *" for the argument expressions. // + // * 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 @@ -2808,6 +2810,15 @@ /// 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(); + } + public: enum class ADLCallKind : bool { NotADL, UsesADL }; static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; @@ -2818,16 +2829,19 @@ /// allocated for the trailing objects. CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL); + SourceLocation RParenLoc, FPOptionsOverride FPFeatures, + unsigned MinNumArgs, ADLCallKind UsesADL); /// Build an empty call expression, for deserialization. CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, - EmptyShell Empty); + bool hasFPFeatures, EmptyShell Empty); /// Return the size in bytes needed for the trailing objects. /// Used by the derived classes to allocate the right amount of storage. - static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) { - return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *); + static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs, + bool HasFPFeatures) { + return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *) + + HasFPFeatures * sizeof(FPOptionsOverride); } Stmt *getPreArg(unsigned I) { @@ -2845,22 +2859,43 @@ unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } + /// Return a pointer to the trailing FPOptions + FPOptionsOverride *getTrailingFPFeatures() { + assert(hasStoredFPFeatures()); + return reinterpret_cast( + reinterpret_cast(this) + CallExprBits.OffsetToTrailingObjects + + getSizeOfTrailingStmts()); + } + const FPOptionsOverride *getTrailingFPFeatures() const { + assert(hasStoredFPFeatures()); + return reinterpret_cast( + reinterpret_cast(this) + + CallExprBits.OffsetToTrailingObjects + getSizeOfTrailingStmts()); + } + public: - /// Create a call expression. Fn is the callee expression, Args is the - /// argument array, Ty is the type of the call expression (which is *not* - /// the return type in general), VK is the value kind of the call expression - /// (lvalue, rvalue, ...), and RParenLoc is the location of the right - /// parenthese in the call expression. MinNumArgs specifies the minimum - /// number of arguments. The actual number of arguments will be the greater - /// of Args.size() and MinNumArgs. This is used in a few places to allocate - /// enough storage for the default arguments. UsesADL specifies whether the - /// callee was found through argument-dependent lookup. + /// Create a call expression. + /// \param Fn The callee expression, + /// \param Args The argument array, + /// \param Ty The type of the call expression (which is *not* the return + /// type in general), + /// \param VK The value kind of the call expression (lvalue, rvalue, ...), + /// \param RParenLoc The location of the right parenthesis in the call + /// expression. + /// \param FPFeatures Floating-point features associated with the call, + /// \param MinNumArgs Specifies the minimum number of arguments. The actual + /// number of arguments will be the greater of Args.size() + /// and MinNumArgs. This is used in a few places to allocate + /// enough storage for the default arguments. + /// \param UsesADL Specifies whether the callee was found through + /// argument-dependent lookup. /// /// Note that you can use CreateTemporary if you need a temporary call /// expression on the stack. static CallExpr *Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs = 0, + SourceLocation RParenLoc, + FPOptionsOverride FPFeatures, unsigned MinNumArgs = 0, ADLCallKind UsesADL = NotADL); /// Create a temporary call expression with no arguments in the memory @@ -2877,7 +2912,7 @@ /// Create an empty call expression, for deserialization. static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, - EmptyShell Empty); + bool HasFPFeatures, EmptyShell Empty); Expr *getCallee() { return cast(getTrailingStmts()[FN]); } const Expr *getCallee() const { return cast(getTrailingStmts()[FN]); } @@ -2891,6 +2926,8 @@ } bool usesADL() const { return getADLCallKind() == UsesADL; } + bool hasStoredFPFeatures() const { return CallExprBits.HasFPFeatures; } + Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); } const Decl *getCalleeDecl() const { return getCallee()->getReferencedDeclOfCallee(); @@ -2983,6 +3020,31 @@ /// this function call. unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 1 : 0; } + /// Get FPOptionsOverride from trailing storage. + FPOptionsOverride getStoredFPFeatures() const { + assert(hasStoredFPFeatures()); + return *getTrailingFPFeatures(); + } + /// Set FPOptionsOverride in trailing storage. Used only by Serialization. + void setStoredFPFeatures(FPOptionsOverride F) { + assert(hasStoredFPFeatures()); + *getTrailingFPFeatures() = F; + } + + // Get the FP features status of this operator. Only meaningful for + // operations on floating point types. + FPOptions getFPFeaturesInEffect(const LangOptions &LO) const { + if (hasStoredFPFeatures()) + return getStoredFPFeatures().applyOverrides(LO); + return FPOptions::defaultWithoutTrailingStorage(LO); + } + + FPOptionsOverride getFPFeatures() const { + if (hasStoredFPFeatures()) + return getStoredFPFeatures(); + return FPOptionsOverride(); + } + /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID /// of the callee. If not, return 0. unsigned getBuiltinCallee() const; diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -84,7 +84,6 @@ friend class ASTStmtWriter; SourceRange Range; - FPOptionsOverride Overrides; // CXXOperatorCallExpr has some trailing objects belonging // to CallExpr. See CallExpr for the details. @@ -96,7 +95,7 @@ SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, ADLCallKind UsesADL); - CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty); + CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); public: static CXXOperatorCallExpr * @@ -106,7 +105,8 @@ ADLCallKind UsesADL = NotADL); static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, - unsigned NumArgs, EmptyShell Empty); + unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty); /// Returns the kind of overloaded operator that this expression refers to. OverloadedOperatorKind getOperator() const { @@ -164,11 +164,6 @@ static bool classof(const Stmt *T) { return T->getStmtClass() == CXXOperatorCallExprClass; } - - // Set the FPFeatures status of this operator. Only meaningful for - // operations on floating point types. - void setFPFeatures(FPOptionsOverride F) { Overrides = F; } - FPOptionsOverride getFPFeatures() const { return Overrides; } }; /// Represents a call to a member function that @@ -184,18 +179,20 @@ // to CallExpr. See CallExpr for the details. CXXMemberCallExpr(Expr *Fn, ArrayRef Args, QualType Ty, - ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs); + ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPOptions, unsigned MinNumArgs); - CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty); + CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); public: static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, unsigned MinNumArgs = 0); static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, - EmptyShell Empty); + bool HasFPFeatures, EmptyShell Empty); /// Retrieve the implicit object argument for the member call. /// @@ -242,18 +239,21 @@ CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation RP, - unsigned MinNumArgs); + FPOptionsOverride FPFeatures, unsigned MinNumArgs); - CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty); + CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); public: static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RP, unsigned MinNumArgs = 0); + SourceLocation RP, + FPOptionsOverride FPFeatures, + unsigned MinNumArgs = 0); static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx, - unsigned NumArgs, EmptyShell Empty); + unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty); const CallExpr *getConfig() const { return cast_or_null(getPreArg(CONFIG)); @@ -619,18 +619,20 @@ UserDefinedLiteral(Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc); + SourceLocation SuffixLoc, FPOptionsOverride FPFeatures); - UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty); + UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); public: static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc); + SourceLocation SuffixLoc, + FPOptionsOverride FPFeatures); static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx, - unsigned NumArgs, EmptyShell Empty); + unsigned NumArgs, bool HasFPOptions, + EmptyShell Empty); /// The kind of literal operator which is invoked. enum LiteralOperatorKind { diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -464,8 +464,11 @@ /// True if the callee of the call expression was found using ADL. unsigned UsesADL : 1; + /// True if the call expression has some floating-point features. + unsigned HasFPFeatures : 1; + /// Padding used to align OffsetToTrailingObjects to a byte multiple. - unsigned : 24 - 2 - NumExprBits; + unsigned : 24 - 3 - NumExprBits; /// 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/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -155,6 +155,7 @@ const comments::CommandTraits *Traits = nullptr; const char *getCommandName(unsigned CommandID); + void printFPOptions(FPOptionsOverride FPO); void dumpAPValueChildren(const APValue &Value, QualType Ty, const APValue &(*IdxToChildFun)(const APValue &, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7338,7 +7338,8 @@ return std::move(Err); return CXXMemberCallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, - ToType, E->getValueKind(), ToRParenLoc); + ToType, E->getValueKind(), ToRParenLoc, + E->getFPFeatures()); } ExpectedStmt ASTNodeImporter::VisitCXXThisExpr(CXXThisExpr *E) { @@ -7648,8 +7649,8 @@ } return CallExpr::Create(Importer.getToContext(), ToCallee, ToArgs, ToType, - E->getValueKind(), ToRParenLoc, /*MinNumArgs=*/0, - E->getADLCallKind()); + E->getValueKind(), ToRParenLoc, E->getFPFeatures(), + /*MinNumArgs=*/0, E->getADLCallKind()); } ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1303,8 +1303,8 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef PreArgs, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, - ADLCallKind UsesADL) + SourceLocation RParenLoc, FPOptionsOverride FPFeatures, + unsigned MinNumArgs, ADLCallKind UsesADL) : Expr(SC, Ty, VK, OK_Ordinary), RParenLoc(RParenLoc) { NumArgs = std::max(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); @@ -1327,10 +1327,14 @@ setArg(I, nullptr); setDependence(computeDependence(this, PreArgs)); + + CallExprBits.HasFPFeatures = FPFeatures.requiresTrailingStorage(); + if (hasStoredFPFeatures()) + setStoredFPFeatures(FPFeatures); } CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, - EmptyShell Empty) + bool HasFPFeatures, EmptyShell Empty) : Expr(SC, Empty), NumArgs(NumArgs) { CallExprBits.NumPreArgs = NumPreArgs; assert((NumPreArgs == getNumPreArgs()) && "NumPreArgs overflow!"); @@ -1339,19 +1343,21 @@ CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects; assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) && "OffsetToTrailingObjects overflow!"); + CallExprBits.HasFPFeatures = HasFPFeatures; } CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, + SourceLocation RParenLoc, + FPOptionsOverride FPFeatures, unsigned MinNumArgs, ADLCallKind UsesADL) { unsigned NumArgs = std::max(Args.size(), MinNumArgs); - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage()); void *Mem = Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr)); return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - RParenLoc, MinNumArgs, UsesADL); + RParenLoc, FPFeatures, MinNumArgs, UsesADL); } CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty, @@ -1360,17 +1366,18 @@ assert(!(reinterpret_cast(Mem) % alignof(CallExpr)) && "Misaligned memory in CallExpr::CreateTemporary!"); return new (Mem) CallExpr(CallExprClass, Fn, /*PreArgs=*/{}, /*Args=*/{}, Ty, - VK, RParenLoc, + VK, RParenLoc, FPOptionsOverride(), /*MinNumArgs=*/0, UsesADL); } CallExpr *CallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, - EmptyShell Empty) { + bool HasFPFeatures, EmptyShell Empty) { unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures); void *Mem = Ctx.Allocate(sizeof(CallExpr) + SizeOfTrailingObjects, alignof(CallExpr)); - return new (Mem) CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, Empty); + return new (Mem) + CallExpr(CallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, Empty); } unsigned CallExpr::offsetToTrailingObjects(StmtClass SC) { diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -528,17 +528,18 @@ FPOptionsOverride FPFeatures, ADLCallKind UsesADL) : CallExpr(CXXOperatorCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - OperatorLoc, /*MinNumArgs=*/0, UsesADL) { + OperatorLoc, FPFeatures, /*MinNumArgs=*/0, UsesADL) { CXXOperatorCallExprBits.OperatorKind = OpKind; assert( (CXXOperatorCallExprBits.OperatorKind == static_cast(OpKind)) && "OperatorKind overflow!"); Range = getSourceRangeImpl(); - Overrides = FPFeatures; } -CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty) - : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} +CXXOperatorCallExpr::CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty) + : CallExpr(CXXOperatorCallExprClass, /*NumPreArgs=*/0, NumArgs, + HasFPFeatures, Empty) {} CXXOperatorCallExpr * CXXOperatorCallExpr::Create(const ASTContext &Ctx, @@ -548,8 +549,8 @@ FPOptionsOverride FPFeatures, ADLCallKind UsesADL) { // Allocate storage for the trailing objects of CallExpr. unsigned NumArgs = Args.size(); - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage()); void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects, alignof(CXXOperatorCallExpr)); return new (Mem) CXXOperatorCallExpr(OpKind, Fn, Args, Ty, VK, OperatorLoc, @@ -558,13 +559,14 @@ CXXOperatorCallExpr *CXXOperatorCallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + bool HasFPFeatures, EmptyShell Empty) { // Allocate storage for the trailing objects of CallExpr. unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures); void *Mem = Ctx.Allocate(sizeof(CXXOperatorCallExpr) + SizeOfTrailingObjects, alignof(CXXOperatorCallExpr)); - return new (Mem) CXXOperatorCallExpr(NumArgs, Empty); + return new (Mem) CXXOperatorCallExpr(NumArgs, HasFPFeatures, Empty); } SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const { @@ -593,36 +595,43 @@ CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RP, unsigned MinNumArgs) + SourceLocation RP, + FPOptionsOverride FPOptions, + unsigned MinNumArgs) : CallExpr(CXXMemberCallExprClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, RP, - MinNumArgs, NotADL) {} + FPOptions, MinNumArgs, NotADL) {} -CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty) - : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, Empty) {} +CXXMemberCallExpr::CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty) + : CallExpr(CXXMemberCallExprClass, /*NumPreArgs=*/0, NumArgs, HasFPFeatures, + Empty) {} CXXMemberCallExpr *CXXMemberCallExpr::Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, unsigned MinNumArgs) { // Allocate storage for the trailing objects of CallExpr. unsigned NumArgs = std::max(Args.size(), MinNumArgs); - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage()); void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects, alignof(CXXMemberCallExpr)); - return new (Mem) CXXMemberCallExpr(Fn, Args, Ty, VK, RP, MinNumArgs); + return new (Mem) + CXXMemberCallExpr(Fn, Args, Ty, VK, RP, FPFeatures, MinNumArgs); } CXXMemberCallExpr *CXXMemberCallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + bool HasFPFeatures, EmptyShell Empty) { // Allocate storage for the trailing objects of CallExpr. unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPFeatures); void *Mem = Ctx.Allocate(sizeof(CXXMemberCallExpr) + SizeOfTrailingObjects, alignof(CXXMemberCallExpr)); - return new (Mem) CXXMemberCallExpr(NumArgs, Empty); + return new (Mem) CXXMemberCallExpr(NumArgs, HasFPFeatures, Empty); } Expr *CXXMemberCallExpr::getImplicitObjectArgument() const { @@ -846,37 +855,43 @@ UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc) + SourceLocation SuffixLoc, + FPOptionsOverride FPFeatures) : CallExpr(UserDefinedLiteralClass, Fn, /*PreArgs=*/{}, Args, Ty, VK, - LitEndLoc, /*MinNumArgs=*/0, NotADL), + LitEndLoc, FPFeatures, /*MinNumArgs=*/0, NotADL), UDSuffixLoc(SuffixLoc) {} -UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty) - : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, Empty) {} +UserDefinedLiteral::UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty) + : CallExpr(UserDefinedLiteralClass, /*NumPreArgs=*/0, NumArgs, + HasFPFeatures, Empty) {} UserDefinedLiteral *UserDefinedLiteral::Create(const ASTContext &Ctx, Expr *Fn, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc) { + SourceLocation SuffixLoc, + FPOptionsOverride FPFeatures) { // Allocate storage for the trailing objects of CallExpr. unsigned NumArgs = Args.size(); - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/0, NumArgs, FPFeatures.requiresTrailingStorage()); void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects, alignof(UserDefinedLiteral)); - return new (Mem) UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc); + return new (Mem) + UserDefinedLiteral(Fn, Args, Ty, VK, LitEndLoc, SuffixLoc, FPFeatures); } UserDefinedLiteral *UserDefinedLiteral::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + bool HasFPOptions, EmptyShell Empty) { // Allocate storage for the trailing objects of CallExpr. unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs); + CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/0, NumArgs, HasFPOptions); void *Mem = Ctx.Allocate(sizeof(UserDefinedLiteral) + SizeOfTrailingObjects, alignof(UserDefinedLiteral)); - return new (Mem) UserDefinedLiteral(NumArgs, Empty); + return new (Mem) UserDefinedLiteral(NumArgs, HasFPOptions, Empty); } UserDefinedLiteral::LiteralOperatorKind @@ -1643,34 +1658,39 @@ CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef Args, QualType Ty, ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, unsigned MinNumArgs) : CallExpr(CUDAKernelCallExprClass, Fn, /*PreArgs=*/Config, Args, Ty, VK, - RP, MinNumArgs, NotADL) {} + RP, FPFeatures, MinNumArgs, NotADL) {} -CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty) +CUDAKernelCallExpr::CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, + EmptyShell Empty) : CallExpr(CUDAKernelCallExprClass, /*NumPreArgs=*/END_PREARG, NumArgs, - Empty) {} + HasFPFeatures, Empty) {} CUDAKernelCallExpr * CUDAKernelCallExpr::Create(const ASTContext &Ctx, Expr *Fn, CallExpr *Config, ArrayRef Args, QualType Ty, ExprValueKind VK, - SourceLocation RP, unsigned MinNumArgs) { + SourceLocation RP, FPOptionsOverride FPFeatures, + unsigned MinNumArgs) { // Allocate storage for the trailing objects of CallExpr. unsigned NumArgs = std::max(Args.size(), MinNumArgs); - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/END_PREARG, NumArgs, FPFeatures.requiresTrailingStorage()); void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects, alignof(CUDAKernelCallExpr)); - return new (Mem) CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, MinNumArgs); + return new (Mem) + CUDAKernelCallExpr(Fn, Config, Args, Ty, VK, RP, FPFeatures, MinNumArgs); } CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + bool HasFPFeatures, EmptyShell Empty) { // Allocate storage for the trailing objects of CallExpr. - unsigned SizeOfTrailingObjects = - CallExpr::sizeOfTrailingObjects(/*NumPreArgs=*/END_PREARG, NumArgs); + unsigned SizeOfTrailingObjects = CallExpr::sizeOfTrailingObjects( + /*NumPreArgs=*/END_PREARG, NumArgs, HasFPFeatures); void *Mem = Ctx.Allocate(sizeof(CUDAKernelCallExpr) + SizeOfTrailingObjects, alignof(CUDAKernelCallExpr)); - return new (Mem) CUDAKernelCallExpr(NumArgs, Empty); + return new (Mem) CUDAKernelCallExpr(NumArgs, HasFPFeatures, Empty); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -710,6 +710,13 @@ return ""; } +void TextNodeDumper::printFPOptions(FPOptionsOverride FPO) { +#define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ + if (FPO.has##NAME##Override()) \ + OS << " " #NAME "=" << FPO.get##NAME##Override(); +#include "clang/Basic/FPOptions.def" +} + void TextNodeDumper::visitTextComment(const comments::TextComment *C, const comments::FullComment *) { OS << " Text=\"" << C->getText() << "\""; @@ -937,6 +944,8 @@ void TextNodeDumper::VisitCallExpr(const CallExpr *Node) { if (Node->usesADL()) OS << " adl"; + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getFPFeatures()); } void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) { @@ -1053,6 +1062,8 @@ << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; if (!Node->canOverflow()) OS << " cannot overflow"; + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getStoredFPFeatures()); } void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr( @@ -1081,6 +1092,8 @@ void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) { OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'"; + if (Node->hasStoredFPFeatures()) + printFPOptions(Node->getStoredFPFeatures()); } void TextNodeDumper::VisitCompoundAssignOperator( diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -267,7 +267,7 @@ } return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); } static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, @@ -514,7 +514,7 @@ /*Args=*/None, /*QualType=*/C.VoidTy, /*ExprValueType=*/VK_RValue, - /*SourceLocation=*/SourceLocation()); + /*SourceLocation=*/SourceLocation(), FPOptionsOverride()); // (2) Create the assignment to the predicate. Expr *DoneValue = @@ -578,8 +578,8 @@ ASTMaker M(C); DeclRefExpr *DR = M.makeDeclRefExpr(PV); ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); - CallExpr *CE = - CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, SourceLocation()); + CallExpr *CE = CallExpr::Create(C, ICE, None, C.VoidTy, VK_RValue, + SourceLocation(), FPOptionsOverride()); return CE; } diff --git a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -2109,8 +2109,9 @@ DRE, nullptr, VK_RValue); const auto *FT = msgSendType->castAs(); - CallExpr *Exp = CallExpr::Create( - *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc); + CallExpr *Exp = + CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), + VK_RValue, EndLoc, FPOptionsOverride()); return Exp; } @@ -2692,7 +2693,7 @@ auto *FT = msgSendType->castAs(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptionsOverride()); ReplaceStmt(Exp, CE); return CE; } @@ -2732,7 +2733,7 @@ InitExprs.push_back(Exp->getElement(i)); Expr *NSArrayCallExpr = CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -2813,7 +2814,7 @@ const FunctionType *FT = msgSendType->castAs(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptionsOverride()); ReplaceStmt(Exp, CE); return CE; } @@ -2861,7 +2862,7 @@ // (const id [])objects Expr *NSValueCallExpr = CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -2879,8 +2880,9 @@ CK_BitCast, DictLiteralValueME); // (const id [])keys - Expr *NSKeyCallExpr = CallExpr::Create( - *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation()); + Expr *NSKeyCallExpr = + CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, + SourceLocation(), FPOptionsOverride()); MemberExpr *DictLiteralKeyME = MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, @@ -2964,7 +2966,7 @@ const FunctionType *FT = msgSendType->castAs(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptionsOverride()); ReplaceStmt(Exp, CE); return CE; } @@ -3175,8 +3177,9 @@ ID, FuncType, nullptr, SC_Extern, false, false); DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, castType, VK_RValue, SourceLocation()); - CallExpr *STCE = CallExpr::Create(*Context, DRE, MsgExprs, castType, - VK_LValue, SourceLocation()); + CallExpr *STCE = + CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue, + SourceLocation(), FPOptionsOverride()); FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -3276,8 +3279,9 @@ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); - SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + SuperRep = + CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, + SourceLocation(), FPOptionsOverride()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -3371,8 +3375,9 @@ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); - SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + SuperRep = + CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, + SourceLocation(), FPOptionsOverride()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -3537,7 +3542,7 @@ const FunctionType *FT = msgSendType->castAs(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptionsOverride()); Stmt *ReplacingStmt = CE; if (MsgSendStretFlavor) { // We have the method which returns a struct/union. Must also generate @@ -4647,8 +4652,9 @@ E = Exp->arg_end(); I != E; ++I) { BlkExprs.push_back(*I); } - CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), - VK_RValue, SourceLocation()); + CallExpr *CE = + CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue, + SourceLocation(), FPOptionsOverride()); return CE; } @@ -5391,7 +5397,7 @@ InitExprs.push_back(FlagExp); } NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); if (GlobalBlockExpr) { assert (!GlobalConstructionExp && diff --git a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2027,8 +2027,9 @@ const auto *FT = msgSendType->castAs(); - CallExpr *Exp = CallExpr::Create( - *Context, ICE, Args, FT->getCallResultType(*Context), VK_RValue, EndLoc); + CallExpr *Exp = + CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), + VK_RValue, EndLoc, FPOptionsOverride()); return Exp; } @@ -2614,8 +2615,9 @@ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); const auto *FT = msgSendType->castAs(); - CallExpr *STCE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, SourceLocation()); + CallExpr *STCE = + CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_RValue, + SourceLocation(), FPOptionsOverride()); return STCE; } @@ -2707,8 +2709,9 @@ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); - SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + SuperRep = + CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, + SourceLocation(), FPOptionsOverride()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -2802,8 +2805,9 @@ DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, VK_LValue, SourceLocation()); - SuperRep = CallExpr::Create(*Context, DRE, InitExprs, superType, - VK_LValue, SourceLocation()); + SuperRep = + CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, + SourceLocation(), FPOptionsOverride()); // The code for super is a little tricky to prevent collision with // the structure definition in the header. The rewriter has it's own // internal definition (__rw_objc_super) that is uses. This is why @@ -2968,7 +2972,7 @@ const auto *FT = msgSendType->castAs(); CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), - VK_RValue, EndLoc); + VK_RValue, EndLoc, FPOptionsOverride()); Stmt *ReplacingStmt = CE; if (MsgSendStretFlavor) { // We have the method which returns a struct/union. Must also generate @@ -3817,8 +3821,9 @@ E = Exp->arg_end(); I != E; ++I) { BlkExprs.push_back(*I); } - CallExpr *CE = CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), - VK_RValue, SourceLocation()); + CallExpr *CE = + CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_RValue, + SourceLocation(), FPOptionsOverride()); return CE; } @@ -4530,7 +4535,7 @@ InitExprs.push_back(FlagExp); } NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); NewRep = UnaryOperator::Create( const_cast(*Context), NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), VK_RValue, OK_Ordinary, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6322,7 +6322,7 @@ } return CallExpr::Create(Context, Fn, /*Args=*/{}, Context.VoidTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); } if (Fn->getType() == Context.PseudoObjectTy) { ExprResult result = CheckPlaceholderExpr(Fn); @@ -6336,7 +6336,7 @@ if (ExecConfig) { return CUDAKernelCallExpr::Create( Context, Fn, cast(ExecConfig), ArgExprs, - Context.DependentTy, VK_RValue, RParenLoc); + Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides()); } else { tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( @@ -6344,7 +6344,7 @@ Fn->getBeginLoc()); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); } } @@ -6373,7 +6373,7 @@ if (!find.HasFormOfMemberPointer) { if (Expr::hasAnyTypeDependentArguments(ArgExprs)) return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); OverloadExpr *ovl = find.Expression; if (UnresolvedLookupExpr *ULE = dyn_cast(ovl)) return BuildOverloadedCallExpr( @@ -6564,12 +6564,13 @@ if (Config) { assert(UsesADL == ADLCallKind::NotADL && "CUDAKernelCallExpr should not use ADL"); - TheCall = - CUDAKernelCallExpr::Create(Context, Fn, cast(Config), Args, - ResultTy, VK_RValue, RParenLoc, NumParams); + TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast(Config), + Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams); } else { - TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + TheCall = + CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams, UsesADL); } if (!getLangOpts().CPlusPlus) { @@ -6596,10 +6597,11 @@ if (Config) TheCall = CUDAKernelCallExpr::Create( Context, Fn, cast(Config), Args, ResultTy, VK_RValue, - RParenLoc, NumParams); + RParenLoc, CurFPFeatureOverrides(), NumParams); else - TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, - RParenLoc, NumParams, UsesADL); + TheCall = + CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, RParenLoc, + CurFPFeatureOverrides(), NumParams, UsesADL); } // We can now handle the nulled arguments for the default arguments. TheCall->setNumArgsUnsafe(std::max(Args.size(), NumParams)); @@ -19086,7 +19088,8 @@ CK_BuiltinFnToFnPtr) .get(); return CallExpr::Create(Context, E, /*Args=*/{}, Context.IntTy, - VK_RValue, SourceLocation()); + VK_RValue, SourceLocation(), + FPOptionsOverride()); } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7619,7 +7619,8 @@ ResultType = ResultType.getNonLValueExprType(Context); CXXMemberCallExpr *CE = CXXMemberCallExpr::Create( - Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc()); + Context, ME, /*Args=*/{}, ResultType, VK, Exp.get()->getEndLoc(), + CurFPFeatureOverrides()); if (CheckFunctionCall(Method, CE, Method->getType()->castAs())) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15321,7 +15321,8 @@ S.DefaultLvalueConversion(DeclareReductionRef.get()).get()); Expr *Args[] = {LHS.get(), RHS.get()}; ReductionOp = - CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc); + CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_RValue, ELoc, + S.CurFPFeatureOverrides()); } else { ReductionOp = S.BuildBinOp( Stack->getCurScope(), ReductionId.getBeginLoc(), BOK, LHSDRE, RHSDRE); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12797,8 +12797,9 @@ // then create a type dependent CallExpr. The goal is to postpone name // lookup to instantiation time to be able to search into type dependent // base classes. - CallExpr *CE = CallExpr::Create(Context, Fn, Args, Context.DependentTy, - VK_RValue, RParenLoc); + CallExpr *CE = + CallExpr::Create(Context, Fn, Args, Context.DependentTy, VK_RValue, + RParenLoc, CurFPFeatureOverrides()); CE->markDependentForPostponedNameLookup(); *Result = CE; return true; @@ -13978,9 +13979,9 @@ << (qualsString.find(' ') == std::string::npos ? 1 : 2); } - CXXMemberCallExpr *call = - CXXMemberCallExpr::Create(Context, MemExprE, Args, resultType, - valueKind, RParenLoc, proto->getNumParams()); + CXXMemberCallExpr *call = CXXMemberCallExpr::Create( + Context, MemExprE, Args, resultType, valueKind, RParenLoc, + CurFPFeatureOverrides(), proto->getNumParams()); if (CheckCallReturnType(proto->getReturnType(), op->getRHS()->getBeginLoc(), call, nullptr)) @@ -13997,7 +13998,7 @@ if (isa(NakedMemExpr)) return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue, - RParenLoc); + RParenLoc, CurFPFeatureOverrides()); UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) @@ -14135,9 +14136,9 @@ assert(Method && "Member call to something that isn't a method?"); const auto *Proto = Method->getType()->castAs(); - CXXMemberCallExpr *TheCall = - CXXMemberCallExpr::Create(Context, MemExprE, Args, ResultType, VK, - RParenLoc, Proto->getNumParams()); + CXXMemberCallExpr *TheCall = CXXMemberCallExpr::Create( + Context, MemExprE, Args, ResultType, VK, RParenLoc, + CurFPFeatureOverrides(), Proto->getNumParams()); // Check for a valid return type. if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(), @@ -14680,7 +14681,7 @@ UserDefinedLiteral *UDL = UserDefinedLiteral::Create( Context, Fn.get(), llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy, - VK, LitEndLoc, UDSuffixLoc); + VK, LitEndLoc, UDSuffixLoc, CurFPFeatureOverrides()); if (CheckCallReturnType(FD->getReturnType(), UDSuffixLoc, UDL, FD)) return ExprError(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3500,7 +3500,8 @@ // Build the CallExpr ExprResult TheCall = CallExpr::Create( SemaRef.Context, Callee, SubExprs, Builtin->getCallResultType(), - Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc); + Expr::getValueKindForType(Builtin->getReturnType()), RParenLoc, + FPOptionsOverride()); // Type-check the __builtin_shufflevector expression. return SemaRef.SemaBuiltinShuffleVector(cast(TheCall.get())); @@ -10466,6 +10467,15 @@ // FIXME: Wrong source location information for the '('. SourceLocation FakeLParenLoc = ((Expr *)Callee.get())->getSourceRange().getBegin(); + + Sema::FPFeaturesStateRAII FPFeaturesState(getSema()); + if (E->hasStoredFPFeatures()) { + FPOptionsOverride NewOverrides = E->getFPFeatures(); + getSema().CurFPFeatures = + NewOverrides.applyOverrides(getSema().getLangOpts()); + getSema().FpPragmaStack.CurrentValue = NewOverrides.getAsOpaqueInt(); + } + return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, Args, E->getRParenLoc()); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -991,12 +991,15 @@ void ASTStmtReader::VisitCallExpr(CallExpr *E) { VisitExpr(E); unsigned NumArgs = Record.readInt(); + bool HasFPFeatures = Record.readInt(); assert((NumArgs == E->getNumArgs()) && "Wrong NumArgs!"); E->setRParenLoc(readSourceLocation()); E->setCallee(Record.readSubExpr()); for (unsigned I = 0; I != NumArgs; ++I) E->setArg(I, Record.readSubExpr()); E->setADLCallKind(static_cast(Record.readInt())); + if (HasFPFeatures) + E->setStoredFPFeatures(FPOptionsOverride(Record.readInt())); } void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { @@ -1662,7 +1665,6 @@ VisitCallExpr(E); E->CXXOperatorCallExprBits.OperatorKind = Record.readInt(); E->Range = Record.readSourceRange(); - E->setFPFeatures(FPOptionsOverride(Record.readInt())); } void ASTStmtReader::VisitCXXRewrittenBinaryOperator( @@ -2977,7 +2979,8 @@ case EXPR_CALL: S = CallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); + Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); break; case EXPR_RECOVERY: @@ -3585,12 +3588,14 @@ case EXPR_CXX_OPERATOR_CALL: S = CXXOperatorCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); + Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); break; case EXPR_CXX_MEMBER_CALL: S = CXXMemberCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); + Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); break; case EXPR_CXX_REWRITTEN_BINARY_OPERATOR: @@ -3648,7 +3653,8 @@ case EXPR_USER_DEFINED_LITERAL: S = UserDefinedLiteral::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); + Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); break; case EXPR_CXX_STD_INITIALIZER_LIST: @@ -3831,7 +3837,8 @@ case EXPR_CUDA_KERNEL_CALL: S = CUDAKernelCallExpr::CreateEmpty( - Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty); + Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], + /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty); break; case EXPR_ASTYPE: diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -848,12 +848,15 @@ void ASTStmtWriter::VisitCallExpr(CallExpr *E) { VisitExpr(E); Record.push_back(E->getNumArgs()); + Record.push_back(E->hasStoredFPFeatures()); Record.AddSourceLocation(E->getRParenLoc()); Record.AddStmt(E->getCallee()); for (CallExpr::arg_iterator Arg = E->arg_begin(), ArgEnd = E->arg_end(); Arg != ArgEnd; ++Arg) Record.AddStmt(*Arg); Record.push_back(static_cast(E->getADLCallKind())); + if (E->hasStoredFPFeatures()) + Record.push_back(E->getFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CALL; } @@ -1550,7 +1553,6 @@ VisitCallExpr(E); Record.push_back(E->getOperator()); Record.AddSourceRange(E->Range); - Record.push_back(E->getFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CXX_OPERATOR_CALL; } diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp b/clang/test/AST/ast-dump-fpfeatures.cpp new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-fpfeatures.cpp @@ -0,0 +1,37 @@ +// Test without serialization: +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-pc-linux -std=c++11 -ast-dump %s \ +// RUN: | FileCheck --strict-whitespace %s + +// Test with serialization: +// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -triple x86_64-pc-linux -include-pch %t -ast-dump-all /dev/null \ +// RUN: | sed -e "s/ //" -e "s/ imported//" \ +// RUN: | FileCheck --strict-whitespace %s + +float func_01(float x); + +template +T func_02(T x) { +#pragma STDC FP_CONTRACT ON + return func_01(x); +} + +float func_03(float x) { +#pragma STDC FP_CONTRACT OFF + return func_02(x); +} + +// CHECK: FunctionTemplateDecl {{.*}} func_02 +// CHECK: FunctionDecl {{.*}} func_02 'float (float)' +// CHECK-NEXT: TemplateArgument type 'float' +// CHECK-NEXT: BuiltinType {{.*}} 'float' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'float' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CallExpr {{.*}} FPContractMode=1 + +// CHECK: FunctionDecl {{.*}} func_03 'float (float)' +// CHECK-NEXT: ParmVarDecl {{.*}} x 'float' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: ReturnStmt +// CHECK-NEXT: CallExpr {{.*}} FPContractMode=0 \ No newline at end of file