diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-02-15 00:27:53 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-02-15 00:27:53 +0000 |
commit | d1f4353f6e59e74948fb8442a8fda9b0bf379700 (patch) | |
tree | 757834eaede0e8913ca27f0c43fd1c8de7d3f2be /lib/Sema/TreeTransform.h | |
parent | 7ff8f050d264a0ed5d52063d500216eb36021fe5 (diff) | |
download | clang-d1f4353f6e59e74948fb8442a8fda9b0bf379700.tar.gz |
PR40642: Fix determination of whether the final statement of a statement
expression is a discarded-value expression.
Summary:
We used to get this wrong in three ways:
1) During parsing, an expression-statement followed by the }) ending a
statement expression was always treated as producing the value of the
statement expression. That's wrong for ({ if (1) expr; })
2) During template instantiation, various kinds of statement (most
statements not appearing directly in a compound-statement) were not
treated as discarded-value expressions, resulting in missing volatile
loads (etc).
3) In all contexts, an expression-statement with attributes was not
treated as producing the value of the statement expression, eg
({ [[attr]] expr; }).
Also fix incorrect enforcement of OpenMP rule that directives can "only
be placed in the program at a position where ignoring or deleting the
directive would result in a program with correct syntax". In particular,
a label (be it goto, case, or default) should not affect whether
directives are permitted.
Reviewers: aaron.ballman, rjmccall
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D57984
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@354090 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/TreeTransform.h')
-rw-r--r-- | lib/Sema/TreeTransform.h | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index e411a2ad47..ff33028ebb 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -318,6 +318,13 @@ public: TypeSourceInfo *TransformTypeWithDeducedTST(TypeSourceInfo *DI); /// @} + /// The reason why the value of a statement is not discarded, if any. + enum StmtDiscardKind { + SDK_Discarded, + SDK_NotDiscarded, + SDK_StmtExprResult, + }; + /// Transform the given statement. /// /// By default, this routine transforms a statement by delegating to the @@ -327,7 +334,7 @@ public: /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); + StmtResult TransformStmt(Stmt *S, StmtDiscardKind SDK = SDK_Discarded); /// Transform the given statement. /// @@ -672,6 +679,9 @@ public: #define STMT(Node, Parent) \ LLVM_ATTRIBUTE_NOINLINE \ StmtResult Transform##Node(Node *S); +#define VALUESTMT(Node, Parent) \ + LLVM_ATTRIBUTE_NOINLINE \ + StmtResult Transform##Node(Node *S, StmtDiscardKind SDK); #define EXPR(Node, Parent) \ LLVM_ATTRIBUTE_NOINLINE \ ExprResult Transform##Node(Node *E); @@ -3270,7 +3280,7 @@ private: }; template <typename Derived> -StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { +StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, StmtDiscardKind SDK) { if (!S) return S; @@ -3278,8 +3288,12 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { case Stmt::NoStmtClass: break; // Transform individual statement nodes + // Pass SDK into statements that can produce a value #define STMT(Node, Parent) \ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S)); +#define VALUESTMT(Node, Parent) \ + case Stmt::Node##Class: \ + return getDerived().Transform##Node(cast<Node>(S), SDK); #define ABSTRACT_STMT(Node) #define EXPR(Node, Parent) #include "clang/AST/StmtNodes.inc" @@ -3291,10 +3305,10 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S, bool DiscardedValue) { #include "clang/AST/StmtNodes.inc" { ExprResult E = getDerived().TransformExpr(cast<Expr>(S)); - if (E.isInvalid()) - return StmtError(); - return getSema().ActOnExprStmt(E, DiscardedValue); + if (SDK == SDK_StmtExprResult) + E = getSema().ActOnStmtExprResult(E); + return getSema().ActOnExprStmt(E, SDK == SDK_Discarded); } } @@ -6522,8 +6536,9 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool SubStmtChanged = false; SmallVector<Stmt*, 8> Statements; for (auto *B : S->body()) { - StmtResult Result = - getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); + StmtResult Result = getDerived().TransformStmt( + B, + IsStmtExpr && B == S->body_back() ? SDK_StmtExprResult : SDK_Discarded); if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very @@ -6586,7 +6601,8 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { return StmtError(); // Transform the statement following the case - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = + getDerived().TransformStmt(S->getSubStmt()); if (SubStmt.isInvalid()) return StmtError(); @@ -6594,11 +6610,11 @@ TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get()); } -template<typename Derived> -StmtResult -TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { // Transform the statement following the default case - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = + getDerived().TransformStmt(S->getSubStmt()); if (SubStmt.isInvalid()) return StmtError(); @@ -6609,8 +6625,8 @@ TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { template<typename Derived> StmtResult -TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); +TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S, StmtDiscardKind SDK) { + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); if (SubStmt.isInvalid()) return StmtError(); @@ -6619,6 +6635,11 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { if (!LD) return StmtError(); + // If we're transforming "in-place" (we're not creating new local + // declarations), assume we're replacing the old label statement + // and clear out the reference to it. + if (LD == S->getDecl()) + S->getDecl()->setStmt(nullptr); // FIXME: Pass the real colon location in. return getDerived().RebuildLabelStmt(S->getIdentLoc(), @@ -6644,7 +6665,9 @@ const Attr *TreeTransform<Derived>::TransformAttr(const Attr *R) { } template <typename Derived> -StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) { +StmtResult +TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S, + StmtDiscardKind SDK) { bool AttrsChanged = false; SmallVector<const Attr *, 1> Attrs; @@ -6655,7 +6678,7 @@ StmtResult TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) { Attrs.push_back(R); } - StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt(), SDK); if (SubStmt.isInvalid()) return StmtError(); @@ -7360,7 +7383,8 @@ StmtResult TreeTransform<Derived>::TransformObjCForCollectionStmt( ObjCForCollectionStmt *S) { // Transform the element statement. - StmtResult Element = getDerived().TransformStmt(S->getElement()); + StmtResult Element = + getDerived().TransformStmt(S->getElement(), SDK_NotDiscarded); if (Element.isInvalid()) return StmtError(); |