summaryrefslogtreecommitdiffstats
path: root/clang/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang')
-rw-r--r--clang/include/clang/AST/Expr.h6
-rw-r--r--clang/include/clang/AST/Stmt.h35
-rw-r--r--clang/include/clang/Basic/StmtNodes.td10
-rw-r--r--clang/include/clang/Parse/Parser.h68
-rw-r--r--clang/include/clang/Sema/Sema.h3
5 files changed, 80 insertions, 42 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 4fec8efd2dc..95804173c8f 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -105,13 +105,13 @@ struct SubobjectAdjustment {
/// This represents one expression. Note that Expr's are subclasses of Stmt.
/// This allows an expression to be transparently used any place a Stmt is
/// required.
-class Expr : public Stmt {
+class Expr : public ValueStmt {
QualType TR;
protected:
Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK,
bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack)
- : Stmt(SC)
+ : ValueStmt(SC)
{
ExprBits.TypeDependent = TD;
ExprBits.ValueDependent = VD;
@@ -124,7 +124,7 @@ protected:
}
/// Construct an empty expression.
- explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { }
+ explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(SC) { }
public:
QualType getType() const { return TR; }
diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h
index b892d852060..e63354c2631 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -1584,21 +1584,44 @@ Stmt *SwitchCase::getSubStmt() {
llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
}
+/// Represents a statement that could possibly have a value and type. This
+/// covers expression-statements, as well as labels and attributed statements.
+///
+/// Value statements have a special meaning when they are the last non-null
+/// statement in a GNU statement expression, where they determine the value
+/// of the statement expression.
+class ValueStmt : public Stmt {
+protected:
+ using Stmt::Stmt;
+
+public:
+ const Expr *getExprStmt() const;
+ Expr *getExprStmt() {
+ const ValueStmt *ConstThis = this;
+ return const_cast<Expr*>(ConstThis->getExprStmt());
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() >= firstValueStmtConstant &&
+ T->getStmtClass() <= lastValueStmtConstant;
+ }
+};
+
/// LabelStmt - Represents a label, which has a substatement. For example:
/// foo: return;
-class LabelStmt : public Stmt {
+class LabelStmt : public ValueStmt {
LabelDecl *TheDecl;
Stmt *SubStmt;
public:
/// Build a label statement.
LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
- : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) {
+ : ValueStmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) {
setIdentLoc(IL);
}
/// Build an empty label statement.
- explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {}
+ explicit LabelStmt(EmptyShell Empty) : ValueStmt(LabelStmtClass, Empty) {}
SourceLocation getIdentLoc() const { return LabelStmtBits.IdentLoc; }
void setIdentLoc(SourceLocation L) { LabelStmtBits.IdentLoc = L; }
@@ -1627,7 +1650,7 @@ public:
/// Represents an attribute applied to a statement. For example:
/// [[omp::for(...)]] for (...) { ... }
class AttributedStmt final
- : public Stmt,
+ : public ValueStmt,
private llvm::TrailingObjects<AttributedStmt, const Attr *> {
friend class ASTStmtReader;
friend TrailingObjects;
@@ -1636,14 +1659,14 @@ class AttributedStmt final
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr *> Attrs,
Stmt *SubStmt)
- : Stmt(AttributedStmtClass), SubStmt(SubStmt) {
+ : ValueStmt(AttributedStmtClass), SubStmt(SubStmt) {
AttributedStmtBits.NumAttrs = Attrs.size();
AttributedStmtBits.AttrLoc = Loc;
std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr());
}
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
- : Stmt(AttributedStmtClass, Empty) {
+ : ValueStmt(AttributedStmtClass, Empty) {
AttributedStmtBits.NumAttrs = NumAttrs;
AttributedStmtBits.AttrLoc = SourceLocation{};
std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 9054fb11a6f..2dbbee7bbfc 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -11,8 +11,6 @@ class DStmt<Stmt base, bit abstract = 0> : Stmt<abstract> {
// Statements
def NullStmt : Stmt;
def CompoundStmt : Stmt;
-def LabelStmt : Stmt;
-def AttributedStmt : Stmt;
def IfStmt : Stmt;
def SwitchStmt : Stmt;
def WhileStmt : Stmt;
@@ -29,6 +27,12 @@ def CaseStmt : DStmt<SwitchCase>;
def DefaultStmt : DStmt<SwitchCase>;
def CapturedStmt : Stmt;
+// Statements that might produce a value (for example, as the last non-null
+// statement in a GNU statement-expression).
+def ValueStmt : Stmt<1>;
+def LabelStmt : DStmt<ValueStmt>;
+def AttributedStmt : DStmt<ValueStmt>;
+
// Asm statements
def AsmStmt : Stmt<1>;
def GCCAsmStmt : DStmt<AsmStmt>;
@@ -53,7 +57,7 @@ def CoroutineBodyStmt : Stmt;
def CoreturnStmt : Stmt;
// Expressions
-def Expr : Stmt<1>;
+def Expr : DStmt<ValueStmt, 1>;
def PredefinedExpr : DStmt<Expr>;
def DeclRefExpr : DStmt<Expr>;
def IntegerLiteral : DStmt<Expr>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index f5c70e71b8a..db0217324b6 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -363,10 +363,28 @@ class Parser : public CodeCompletionHandler {
/// just a regular sub-expression.
SourceLocation ExprStatementTokLoc;
- /// Tests whether an expression value is discarded based on token lookahead.
- /// It will return true if the lexer is currently processing the })
- /// terminating a GNU statement expression and false otherwise.
- bool isExprValueDiscarded();
+ /// Flags describing a context in which we're parsing a statement.
+ enum class ParsedStmtContext {
+ /// This context permits declarations in language modes where declarations
+ /// are not statements.
+ AllowDeclarationsInC = 0x1,
+ /// This context permits standalone OpenMP directives.
+ AllowStandaloneOpenMPDirectives = 0x2,
+ /// This context is at the top level of a GNU statement expression.
+ InStmtExpr = 0x4,
+
+ /// The context of a regular substatement.
+ SubStmt = 0,
+ /// The context of a compound-statement.
+ Compound = AllowDeclarationsInC | AllowStandaloneOpenMPDirectives,
+
+ LLVM_MARK_AS_BITMASK_ENUM(InStmtExpr)
+ };
+
+ /// Act on an expression statement that might be the last statement in a
+ /// GNU statement expression. Checks whether we are actually at the end of
+ /// a statement expression and builds a suitable expression statement.
+ StmtResult handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx);
public:
Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies);
@@ -1873,29 +1891,24 @@ private:
/// A SmallVector of types.
typedef SmallVector<ParsedType, 12> TypeVector;
- StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
- bool AllowOpenMPStandalone = false);
- enum AllowedConstructsKind {
- /// Allow any declarations, statements, OpenMP directives.
- ACK_Any,
- /// Allow only statements and non-standalone OpenMP directives.
- ACK_StatementsOpenMPNonStandalone,
- /// Allow statements and all executable OpenMP directives
- ACK_StatementsOpenMPAnyExecutable
- };
StmtResult
- ParseStatementOrDeclaration(StmtVector &Stmts, AllowedConstructsKind Allowed,
- SourceLocation *TrailingElseLoc = nullptr);
+ ParseStatement(SourceLocation *TrailingElseLoc = nullptr,
+ ParsedStmtContext StmtCtx = ParsedStmtContext::SubStmt);
+ StmtResult ParseStatementOrDeclaration(
+ StmtVector &Stmts, ParsedStmtContext StmtCtx,
+ SourceLocation *TrailingElseLoc = nullptr);
StmtResult ParseStatementOrDeclarationAfterAttributes(
StmtVector &Stmts,
- AllowedConstructsKind Allowed,
+ ParsedStmtContext StmtCtx,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
- StmtResult ParseExprStatement();
- StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs);
- StmtResult ParseCaseStatement(bool MissingCase = false,
+ StmtResult ParseExprStatement(ParsedStmtContext StmtCtx);
+ StmtResult ParseLabeledStatement(ParsedAttributesWithRange &attrs,
+ ParsedStmtContext StmtCtx);
+ StmtResult ParseCaseStatement(ParsedStmtContext StmtCtx,
+ bool MissingCase = false,
ExprResult Expr = ExprResult());
- StmtResult ParseDefaultStatement();
+ StmtResult ParseDefaultStatement(ParsedStmtContext StmtCtx);
StmtResult ParseCompoundStatement(bool isStmtExpr = false);
StmtResult ParseCompoundStatement(bool isStmtExpr,
unsigned ScopeFlags);
@@ -1918,7 +1931,7 @@ private:
StmtResult ParseAsmStatement(bool &msAsm);
StmtResult ParseMicrosoftAsmStatement(SourceLocation AsmLoc);
StmtResult ParsePragmaLoopHint(StmtVector &Stmts,
- AllowedConstructsKind Allowed,
+ ParsedStmtContext StmtCtx,
SourceLocation *TrailingElseLoc,
ParsedAttributesWithRange &Attrs);
@@ -1984,7 +1997,8 @@ private:
//===--------------------------------------------------------------------===//
// Objective-C Statements
- StmtResult ParseObjCAtStatement(SourceLocation atLoc);
+ StmtResult ParseObjCAtStatement(SourceLocation atLoc,
+ ParsedStmtContext StmtCtx);
StmtResult ParseObjCTryStmt(SourceLocation atLoc);
StmtResult ParseObjCThrowStmt(SourceLocation atLoc);
StmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
@@ -2824,13 +2838,9 @@ private:
bool AllowScopeSpecifier);
/// Parses declarative or executable directive.
///
- /// \param Allowed ACK_Any, if any directives are allowed,
- /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are
- /// allowed, ACK_StatementsOpenMPNonStandalone - if only non-standalone
- /// executable directives are allowed.
- ///
+ /// \param StmtCtx The context in which we're parsing the directive.
StmtResult
- ParseOpenMPDeclarativeOrExecutableDirective(AllowedConstructsKind Allowed);
+ ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx);
/// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0c2479a0207..10eff5333fe 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1403,7 +1403,6 @@ public:
void PopCompoundScope();
sema::CompoundScopeInfo &getCurCompoundScope() const;
- bool isCurCompoundStmtAStmtExpr() const;
bool hasAnyUnrecoverableErrorsInThisFunction() const;
@@ -4533,6 +4532,8 @@ public:
void ActOnStartStmtExpr();
ExprResult ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt,
SourceLocation RPLoc); // "({..})"
+ // Handle the final expression in a statement expression.
+ ExprResult ActOnStmtExprResult(ExprResult E);
void ActOnStmtExprError();
// __builtin_offsetof(type, identifier(.identifier|[expr])*)
OpenPOWER on IntegriCloud