summaryrefslogtreecommitdiff
path: root/lib/Sema/TreeTransform.h
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-02-15 00:27:53 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-02-15 00:27:53 +0000
commitd1f4353f6e59e74948fb8442a8fda9b0bf379700 (patch)
tree757834eaede0e8913ca27f0c43fd1c8de7d3f2be /lib/Sema/TreeTransform.h
parent7ff8f050d264a0ed5d52063d500216eb36021fe5 (diff)
downloadclang-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.h58
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();