Author: Serge Pavlov Date: 2020-07-24T12:04:19+07:00 New Revision: 70e7aa4a4ed36a034c43b249d0842f4f273b44e1
URL: https://github.com/llvm/llvm-project/commit/70e7aa4a4ed36a034c43b249d0842f4f273b44e1 DIFF: https://github.com/llvm/llvm-project/commit/70e7aa4a4ed36a034c43b249d0842f4f273b44e1.diff LOG: [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 Added: clang/test/AST/ast-dump-fpfeatures.cpp Modified: clang/include/clang/AST/Expr.h clang/include/clang/AST/ExprCXX.h clang/include/clang/AST/Stmt.h clang/include/clang/AST/TextNodeDumper.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/Expr.cpp clang/lib/AST/ExprCXX.cpp clang/lib/AST/TextNodeDumper.cpp clang/lib/Analysis/BodyFarm.cpp clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp clang/lib/Frontend/Rewrite/RewriteObjC.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Sema/SemaOpenMP.cpp clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/TreeTransform.h clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 24bface15d3e..96db7bc3be29 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2272,12 +2272,12 @@ class UnaryOperator final /// 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 @@ class CallExpr : public Expr { // // * 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 @@ class CallExpr : public Expr { /// 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 @@ class CallExpr : public Expr { /// allocated for the trailing objects. CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, ArrayRef<Expr *> 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 @@ class CallExpr : public Expr { unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } + /// Return a pointer to the trailing FPOptions + FPOptionsOverride *getTrailingFPFeatures() { + assert(hasStoredFPFeatures()); + return reinterpret_cast<FPOptionsOverride *>( + reinterpret_cast<char *>(this) + CallExprBits.OffsetToTrailingObjects + + getSizeOfTrailingStmts()); + } + const FPOptionsOverride *getTrailingFPFeatures() const { + assert(hasStoredFPFeatures()); + return reinterpret_cast<const FPOptionsOverride *>( + reinterpret_cast<const char *>(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<Expr *> 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 @@ class CallExpr : public Expr { /// 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<Expr>(getTrailingStmts()[FN]); } const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); } @@ -2891,6 +2926,8 @@ class CallExpr : public Expr { } 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 @@ class CallExpr : public Expr { /// 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 index 6f0b68479b9d..3f272c96a2d8 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -84,7 +84,6 @@ class CXXOperatorCallExpr final : public CallExpr { friend class ASTStmtWriter; SourceRange Range; - FPOptionsOverride Overrides; // CXXOperatorCallExpr has some trailing objects belonging // to CallExpr. See CallExpr for the details. @@ -96,7 +95,7 @@ class CXXOperatorCallExpr final : public CallExpr { 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 @@ class CXXOperatorCallExpr final : public CallExpr { 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 @@ class CXXOperatorCallExpr final : public CallExpr { 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 @@ class CXXMemberCallExpr final : public CallExpr { // to CallExpr. See CallExpr for the details. CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> 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<Expr *> 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 @@ class CUDAKernelCallExpr final : public CallExpr { CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> 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<Expr *> 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<CallExpr>(getPreArg(CONFIG)); @@ -619,18 +619,20 @@ class UserDefinedLiteral final : public CallExpr { UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> 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<Expr *> 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 index d3fad58fcf59..13f265223ac1 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -464,8 +464,11 @@ class alignas(void *) Stmt { /// 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 index b4cfb5a380d1..8e8084aec3c1 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -155,6 +155,7 @@ class TextNodeDumper 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 index 3779e0cb872b..fcfaba625a72 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7338,7 +7338,8 @@ ExpectedStmt ASTNodeImporter::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { 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 @@ ExpectedStmt ASTNodeImporter::VisitCallExpr(CallExpr *E) { } 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 index 213a6d1d1caa..29f96674e174 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1303,8 +1303,8 @@ OverloadedOperatorKind UnaryOperator::getOverloadedOperator(Opcode Opc) { CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, ArrayRef<Expr *> 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<unsigned>(Args.size(), MinNumArgs); unsigned NumPreArgs = PreArgs.size(); @@ -1327,10 +1327,14 @@ CallExpr::CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, 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 @@ CallExpr::CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, CallExprBits.OffsetToTrailingObjects = OffsetToTrailingObjects; assert((CallExprBits.OffsetToTrailingObjects == OffsetToTrailingObjects) && "OffsetToTrailingObjects overflow!"); + CallExprBits.HasFPFeatures = HasFPFeatures; } CallExpr *CallExpr::Create(const ASTContext &Ctx, Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, - SourceLocation RParenLoc, unsigned MinNumArgs, + SourceLocation RParenLoc, + FPOptionsOverride FPFeatures, unsigned MinNumArgs, ADLCallKind UsesADL) { unsigned NumArgs = std::max<unsigned>(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 @@ CallExpr *CallExpr::CreateTemporary(void *Mem, Expr *Fn, QualType Ty, assert(!(reinterpret_cast<uintptr_t>(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 index 5d99f61c579f..3d61496f30e2 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -528,17 +528,18 @@ CXXOperatorCallExpr::CXXOperatorCallExpr(OverloadedOperatorKind OpKind, 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<unsigned>(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 @@ CXXOperatorCallExpr::Create(const ASTContext &Ctx, 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::Create(const ASTContext &Ctx, 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 @@ SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const { CXXMemberCallExpr::CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> 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<Expr *> Args, QualType Ty, ExprValueKind VK, SourceLocation RP, + FPOptionsOverride FPFeatures, unsigned MinNumArgs) { // Allocate storage for the trailing objects of CallExpr. unsigned NumArgs = std::max<unsigned>(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 @@ SourceLocation CXXFunctionalCastExpr::getEndLoc() const { UserDefinedLiteral::UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> 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<Expr *> 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 @@ TypeTraitExpr *TypeTraitExpr::CreateDeserialized(const ASTContext &C, CUDAKernelCallExpr::CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> 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<Expr *> 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<unsigned>(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 index 5b0a0ac392c0..91b984820cd2 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -710,6 +710,13 @@ const char *TextNodeDumper::getCommandName(unsigned CommandID) { return "<not a builtin command>"; } +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::VisitConstantExpr(const ConstantExpr *Node) { 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 @@ void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) { << 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::VisitExtVectorElementExpr( 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 index f9f0553d28f0..ad2dc8ec7a60 100644 --- a/clang/lib/Analysis/BodyFarm.cpp +++ b/clang/lib/Analysis/BodyFarm.cpp @@ -267,7 +267,7 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, } 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 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { /*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 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { 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 index e122b10e76d3..8c41e71ef018 100644 --- a/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -2109,8 +2109,9 @@ RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, DRE, nullptr, VK_RValue); const auto *FT = msgSendType->castAs<FunctionType>(); - 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 @@ Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { auto *FT = msgSendType->castAs<FunctionType>(); 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 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { 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 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { const FunctionType *FT = msgSendType->castAs<FunctionType>(); 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 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral // (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 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral CK_BitCast, DictLiteralValueME); // (const id <NSCopying> [])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 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral const FunctionType *FT = msgSendType->castAs<FunctionType>(); 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 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla 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 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 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 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 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 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, const FunctionType *FT = msgSendType->castAs<FunctionType>(); 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 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp 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 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, 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 index 3f320dc57aa6..4ecd6e95de10 100644 --- a/clang/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/clang/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -2027,8 +2027,9 @@ RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, const auto *FT = msgSendType->castAs<FunctionType>(); - 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 @@ CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavo ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); const auto *FT = msgSendType->castAs<FunctionType>(); - 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 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 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 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 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 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, const auto *FT = msgSendType->castAs<FunctionType>(); 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 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 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 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, InitExprs.push_back(FlagExp); } NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, - SourceLocation()); + SourceLocation(), FPOptionsOverride()); NewRep = UnaryOperator::Create( const_cast<ASTContext &>(*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 index ad44302cea45..bb5a07e8079d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6322,7 +6322,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, } 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 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (ExecConfig) { return CUDAKernelCallExpr::Create( Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs, - Context.DependentTy, VK_RValue, RParenLoc); + Context.DependentTy, VK_RValue, RParenLoc, CurFPFeatureOverrides()); } else { tryImplicitlyCaptureThisIfImplicitMemberFunctionAccessWithDependentArgs( @@ -6344,7 +6344,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, Fn->getBeginLoc()); return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, - VK_RValue, RParenLoc); + VK_RValue, RParenLoc, CurFPFeatureOverrides()); } } @@ -6373,7 +6373,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, 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<UnresolvedLookupExpr>(ovl)) return BuildOverloadedCallExpr( @@ -6564,12 +6564,13 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Config) { assert(UsesADL == ADLCallKind::NotADL && "CUDAKernelCallExpr should not use ADL"); - TheCall = - CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(Config), Args, - ResultTy, VK_RValue, RParenLoc, NumParams); + TheCall = CUDAKernelCallExpr::Create(Context, Fn, cast<CallExpr>(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 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Config) TheCall = CUDAKernelCallExpr::Create( Context, Fn, cast<CallExpr>(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<unsigned>(Args.size(), NumParams)); @@ -19086,7 +19088,8 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { 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 index 3d5cd965980d..fe5ba6a5e87f 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7619,7 +7619,8 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, 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<FunctionProtoType>())) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 987d88ce18cb..51609e37e20c 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -15321,7 +15321,8 @@ static bool actOnOMPReductionKindClause( 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 index 7c6acf011d57..5b4e7a2fdafa 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12797,8 +12797,9 @@ bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, // 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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, << (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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (isa<CXXPseudoDestructorExpr>(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 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, assert(Method && "Member call to something that isn't a method?"); const auto *Proto = Method->getType()->castAs<FunctionProtoType>(); - 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 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, 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 index ae0e9f1119b4..0f83431c94cf 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3500,7 +3500,8 @@ class TreeTransform { // 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<CallExpr>(TheCall.get())); @@ -10466,6 +10467,15 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { // 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 index a40c5499a6d7..8a7beed229c8 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -991,12 +991,15 @@ void ASTStmtReader::VisitOMPIteratorExpr(OMPIteratorExpr *E) { 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<CallExpr::ADLCallKind>(Record.readInt())); + if (HasFPFeatures) + E->setStoredFPFeatures(FPOptionsOverride(Record.readInt())); } void ASTStmtReader::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { @@ -1662,7 +1665,6 @@ void ASTStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); E->CXXOperatorCallExprBits.OperatorKind = Record.readInt(); E->Range = Record.readSourceRange(); - E->setFPFeatures(FPOptionsOverride(Record.readInt())); } void ASTStmtReader::VisitCXXRewrittenBinaryOperator( @@ -2977,7 +2979,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { 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 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { 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 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { 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 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { 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 index 0767b3a24bf2..d2e5d6e44d78 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -848,12 +848,15 @@ void ASTStmtWriter::VisitOMPIteratorExpr(OMPIteratorExpr *E) { 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<unsigned>(E->getADLCallKind())); + if (E->hasStoredFPFeatures()) + Record.push_back(E->getFPFeatures().getAsOpaqueInt()); Code = serialization::EXPR_CALL; } @@ -1550,7 +1553,6 @@ void ASTStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { 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 index 000000000000..796b0a028382 --- /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/ <undeserialized declarations>//" -e "s/ imported//" \ +// RUN: | FileCheck --strict-whitespace %s + +float func_01(float x); + +template <typename T> +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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits