forked from OSchip/llvm-project
Use RAII objects to ensure proper destruction of expression and statement AST nodes in the parser in most cases, even on error.
llvm-svn: 60057
This commit is contained in:
parent
474003763f
commit
511ed55524
|
@ -445,8 +445,9 @@ private:
|
|||
ExprResult ParseSizeofAlignofExpression();
|
||||
ExprResult ParseBuiltinPrimaryExpression();
|
||||
|
||||
typedef llvm::SmallVector<ExprTy*, 8> ExprListTy;
|
||||
typedef llvm::SmallVector<SourceLocation, 8> CommaLocsTy;
|
||||
static const unsigned ExprListSize = 12;
|
||||
typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
|
||||
typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
|
||||
|
||||
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
|
||||
bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs);
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
//===--- AstGuard.h - Parser Ownership Tracking Utilities -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines RAII objects for managing ExprTy* and StmtTy*.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_PARSE_ASTGUARD_H
|
||||
#define LLVM_CLANG_PARSE_ASTGUARD_H
|
||||
|
||||
#include "clang/Parse/Action.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang
|
||||
{
|
||||
/// RAII guard for freeing StmtTys and ExprTys on early exit in the parser.
|
||||
/// Instantiated for statements and expressions (Action::DeleteStmt and
|
||||
/// Action::DeleteExpr).
|
||||
template <void (Action::*Destroyer)(void*)>
|
||||
class ASTGuard {
|
||||
Action &Actions;
|
||||
void *Node;
|
||||
|
||||
void destroy() {
|
||||
if (Node)
|
||||
(Actions.*Destroyer)(Node);
|
||||
}
|
||||
|
||||
ASTGuard(const ASTGuard&); // DO NOT IMPLEMENT
|
||||
// Reference member prevents copy assignment.
|
||||
|
||||
public:
|
||||
explicit ASTGuard(Action &actions) : Actions(actions), Node(0) {}
|
||||
ASTGuard(Action &actions, void *node)
|
||||
: Actions(actions), Node(node) {}
|
||||
template <unsigned N>
|
||||
ASTGuard(Action &actions, const Action::ActionResult<N> &res)
|
||||
: Actions(actions), Node(res.Val) {}
|
||||
~ASTGuard() { destroy(); }
|
||||
|
||||
void reset(void *element) {
|
||||
destroy();
|
||||
Node = element;
|
||||
}
|
||||
template <unsigned N>
|
||||
void reset(const Action::ActionResult<N> &res) {
|
||||
reset(res.Val);
|
||||
}
|
||||
void *take() {
|
||||
void *Temp = Node;
|
||||
Node = 0;
|
||||
return Temp;
|
||||
}
|
||||
void *get() const { return Node; }
|
||||
};
|
||||
|
||||
typedef ASTGuard<&Action::DeleteStmt> StmtGuard;
|
||||
typedef ASTGuard<&Action::DeleteExpr> ExprGuard;
|
||||
|
||||
/// RAII SmallVector wrapper that holds Action::ExprTy* and similar,
|
||||
/// automatically freeing them on destruction unless it's been disowned.
|
||||
/// Instantiated for statements and expressions (Action::DeleteStmt and
|
||||
/// Action::DeleteExpr).
|
||||
template <void (Action::*Destroyer)(void*), unsigned N>
|
||||
class ASTVector : public llvm::SmallVector<void*, N> {
|
||||
private:
|
||||
Action &Actions;
|
||||
bool Owns;
|
||||
|
||||
void destroy() {
|
||||
if (Owns) {
|
||||
while (!this->empty()) {
|
||||
(Actions.*Destroyer)(this->back());
|
||||
this->pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASTVector(const ASTVector&); // DO NOT IMPLEMENT
|
||||
// Reference member prevents copy assignment.
|
||||
|
||||
public:
|
||||
ASTVector(Action &actions) : Actions(actions), Owns(true) {}
|
||||
|
||||
~ASTVector() { destroy(); }
|
||||
|
||||
void **take() {
|
||||
Owns = false;
|
||||
return &(*this)[0];
|
||||
}
|
||||
};
|
||||
|
||||
/// A SmallVector of statements, with stack size 32 (as that is the only one
|
||||
/// used.)
|
||||
typedef ASTVector<&Action::DeleteStmt, 32> StmtVector;
|
||||
/// A SmallVector of expressions, with stack size 12 (the maximum used.)
|
||||
typedef ASTVector<&Action::DeleteExpr, 12> ExprVector;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Parse/Scope.h"
|
||||
#include "ExtensionRAIIObject.h"
|
||||
#include "AstGuard.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
using namespace clang;
|
||||
|
||||
|
@ -122,7 +123,7 @@ AttributeList *Parser::ParseAttributes() {
|
|||
} else if (Tok.is(tok::comma)) {
|
||||
ConsumeToken();
|
||||
// __attribute__(( format(printf, 1, 2) ))
|
||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
||||
ExprVector ArgExprs(Actions);
|
||||
bool ArgExprsOk = true;
|
||||
|
||||
// now parse the non-empty comma separated list of expressions
|
||||
|
@ -142,7 +143,7 @@ AttributeList *Parser::ParseAttributes() {
|
|||
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
||||
ConsumeParen(); // ignore the right paren loc for now
|
||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
|
||||
ParmLoc, &ArgExprs[0], ArgExprs.size(), CurrAttr);
|
||||
ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
|
||||
}
|
||||
}
|
||||
} else { // not an identifier
|
||||
|
@ -154,7 +155,7 @@ AttributeList *Parser::ParseAttributes() {
|
|||
0, SourceLocation(), 0, 0, CurrAttr);
|
||||
} else {
|
||||
// __attribute__(( aligned(16) ))
|
||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
||||
ExprVector ArgExprs(Actions);
|
||||
bool ArgExprsOk = true;
|
||||
|
||||
// now parse the list of expressions
|
||||
|
@ -174,8 +175,8 @@ AttributeList *Parser::ParseAttributes() {
|
|||
// Match the ')'.
|
||||
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
||||
ConsumeParen(); // ignore the right paren loc for now
|
||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
|
||||
SourceLocation(), &ArgExprs[0], ArgExprs.size(),
|
||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
|
||||
SourceLocation(), ArgExprs.take(), ArgExprs.size(),
|
||||
CurrAttr);
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +296,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
|||
} else if (Tok.is(tok::l_paren)) {
|
||||
// Parse C++ direct initializer: '(' expression-list ')'
|
||||
SourceLocation LParenLoc = ConsumeParen();
|
||||
ExprListTy Exprs;
|
||||
ExprVector Exprs(Actions);
|
||||
CommaLocsTy CommaLocs;
|
||||
|
||||
bool InvalidExpr = false;
|
||||
|
@ -310,7 +311,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
|||
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
|
||||
"Unexpected number of commas!");
|
||||
Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
|
||||
&Exprs[0], Exprs.size(),
|
||||
Exprs.take(), Exprs.size(),
|
||||
&CommaLocs[0], RParenLoc);
|
||||
}
|
||||
} else {
|
||||
|
@ -1988,6 +1989,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
|||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||
} else { // we have an expression.
|
||||
ExprResult Result = ParseExpression();
|
||||
ExprGuard ResultGuard(Actions, Result);
|
||||
|
||||
if (Result.isInvalid || Tok.isNot(tok::r_paren)) {
|
||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
|
@ -1997,7 +1999,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
|||
const char *PrevSpec = 0;
|
||||
// Check for duplicate type specifiers (e.g. "int typeof(int)").
|
||||
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
|
||||
Result.Val))
|
||||
ResultGuard.take()))
|
||||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||
}
|
||||
DS.SetRangeEnd(RParenLoc);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "clang/Parse/Scope.h"
|
||||
#include "AstGuard.h"
|
||||
using namespace clang;
|
||||
|
||||
/// ParseNamespace - We know that the current token is a namespace keyword. This
|
||||
|
@ -377,8 +378,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
|
|||
|
||||
// Notify semantic analysis that we have parsed a complete
|
||||
// base-specifier.
|
||||
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
|
||||
BaseLoc);
|
||||
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
|
||||
BaseType, BaseLoc);
|
||||
}
|
||||
|
||||
/// getAccessSpecifierIfPresent - Determine whether the next token is
|
||||
|
@ -747,7 +748,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
|
|||
SourceLocation LParenLoc = ConsumeParen();
|
||||
|
||||
// Parse the optional expression-list.
|
||||
ExprListTy ArgExprs;
|
||||
ExprVector ArgExprs(Actions);
|
||||
CommaLocsTy CommaLocs;
|
||||
if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
|
||||
SkipUntil(tok::r_paren);
|
||||
|
@ -756,9 +757,9 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
|
|||
|
||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
|
||||
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
|
||||
LParenLoc, &ArgExprs[0], ArgExprs.size(),
|
||||
&CommaLocs[0], RParenLoc);
|
||||
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
|
||||
LParenLoc, ArgExprs.take(),
|
||||
ArgExprs.size(), &CommaLocs[0], RParenLoc);
|
||||
}
|
||||
|
||||
/// ParseExceptionSpecification - Parse a C++ exception-specification
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "clang/Parse/Scope.h"
|
||||
#include "ExtensionRAIIObject.h"
|
||||
#include "AstGuard.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace clang;
|
||||
|
@ -238,12 +239,15 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
||||
SourceLocation ColonLoc;
|
||||
|
||||
ExprGuard LHSGuard(Actions, LHS);
|
||||
while (1) {
|
||||
// If this token has a lower precedence than we are allowed to parse (e.g.
|
||||
// because we are called recursively, or because the token is not a binop),
|
||||
// then we are done!
|
||||
if (NextTokPrec < MinPrec)
|
||||
if (NextTokPrec < MinPrec) {
|
||||
LHSGuard.take();
|
||||
return LHS;
|
||||
}
|
||||
|
||||
// Consume the operator, saving the operator token for error reporting.
|
||||
Token OpToken = Tok;
|
||||
|
@ -251,6 +255,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
|
||||
// Special case handling for the ternary operator.
|
||||
ExprResult TernaryMiddle(true);
|
||||
ExprGuard MiddleGuard(Actions);
|
||||
if (NextTokPrec == prec::Conditional) {
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
// Handle this production specially:
|
||||
|
@ -259,7 +264,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
// 'logical-OR-expression' as we might expect.
|
||||
TernaryMiddle = ParseExpression();
|
||||
if (TernaryMiddle.isInvalid) {
|
||||
Actions.DeleteExpr(LHS.Val);
|
||||
return TernaryMiddle;
|
||||
}
|
||||
} else {
|
||||
|
@ -268,12 +272,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
TernaryMiddle = ExprResult(false);
|
||||
Diag(Tok, diag::ext_gnu_conditional_expr);
|
||||
}
|
||||
MiddleGuard.reset(TernaryMiddle);
|
||||
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
Diag(Tok, diag::err_expected_colon);
|
||||
Diag(OpToken, diag::note_matching) << "?";
|
||||
Actions.DeleteExpr(LHS.Val);
|
||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
||||
return ExprResult(true);
|
||||
}
|
||||
|
||||
|
@ -284,10 +287,9 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
// Parse another leaf here for the RHS of the operator.
|
||||
ExprResult RHS = ParseCastExpression(false);
|
||||
if (RHS.isInvalid) {
|
||||
Actions.DeleteExpr(LHS.Val);
|
||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
||||
return RHS;
|
||||
}
|
||||
ExprGuard RHSGuard(Actions, RHS);
|
||||
|
||||
// Remember the precedence of this operator and get the precedence of the
|
||||
// operator immediately to the right of the RHS.
|
||||
|
@ -306,30 +308,32 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
|||
// more tightly than the current operator. If it is left-associative, it
|
||||
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
|
||||
// A=(B=(C=D)), where each paren is a level of recursion here.
|
||||
// The function takes ownership of the RHS.
|
||||
RHSGuard.take();
|
||||
RHS = ParseRHSOfBinaryExpression(RHS, ThisPrec + !isRightAssoc);
|
||||
if (RHS.isInvalid) {
|
||||
Actions.DeleteExpr(LHS.Val);
|
||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
||||
return RHS;
|
||||
}
|
||||
RHSGuard.reset(RHS);
|
||||
|
||||
NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
||||
}
|
||||
assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
|
||||
|
||||
|
||||
if (!LHS.isInvalid) {
|
||||
// Combine the LHS and RHS into the LHS (e.g. build AST).
|
||||
LHSGuard.take();
|
||||
MiddleGuard.take();
|
||||
RHSGuard.take();
|
||||
if (TernaryMiddle.isInvalid)
|
||||
LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
|
||||
OpToken.getKind(), LHS.Val, RHS.Val);
|
||||
else
|
||||
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
|
||||
LHS.Val, TernaryMiddle.Val, RHS.Val);
|
||||
} else {
|
||||
// We had a semantic error on the LHS. Just free the RHS and continue.
|
||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
||||
Actions.DeleteExpr(RHS.Val);
|
||||
LHSGuard.reset(LHS);
|
||||
}
|
||||
// If we had an invalid LHS, Middle and RHS will be freed by the guards here
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -676,24 +680,27 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
|
|||
/// argument-expression-list ',' assignment-expression
|
||||
///
|
||||
Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||
|
||||
ExprGuard LHSGuard(Actions, LHS);
|
||||
// Now that the primary-expression piece of the postfix-expression has been
|
||||
// parsed, see if there are any postfix-expression pieces here.
|
||||
SourceLocation Loc;
|
||||
while (1) {
|
||||
switch (Tok.getKind()) {
|
||||
default: // Not a postfix-expression suffix.
|
||||
LHSGuard.take();
|
||||
return LHS;
|
||||
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
|
||||
Loc = ConsumeBracket();
|
||||
ExprResult Idx = ParseExpression();
|
||||
|
||||
ExprGuard IdxGuard(Actions, Idx);
|
||||
|
||||
SourceLocation RLoc = Tok.getLocation();
|
||||
|
||||
if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square))
|
||||
LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHS.Val, Loc,
|
||||
Idx.Val, RLoc);
|
||||
else
|
||||
if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square)) {
|
||||
LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHSGuard.take(), Loc,
|
||||
IdxGuard.take(), RLoc);
|
||||
LHSGuard.reset(LHS);
|
||||
} else
|
||||
LHS = ExprResult(true);
|
||||
|
||||
// Match the ']'.
|
||||
|
@ -702,7 +709,7 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
}
|
||||
|
||||
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
|
||||
ExprListTy ArgExprs;
|
||||
ExprVector ArgExprs(Actions);
|
||||
CommaLocsTy CommaLocs;
|
||||
|
||||
Loc = ConsumeParen();
|
||||
|
@ -718,8 +725,10 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
if (!LHS.isInvalid && Tok.is(tok::r_paren)) {
|
||||
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
|
||||
"Unexpected number of commas!");
|
||||
LHS = Actions.ActOnCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(),
|
||||
&CommaLocs[0], Tok.getLocation());
|
||||
LHS = Actions.ActOnCallExpr(LHSGuard.take(), Loc, ArgExprs.take(),
|
||||
ArgExprs.size(), &CommaLocs[0],
|
||||
Tok.getLocation());
|
||||
LHSGuard.reset(LHS);
|
||||
}
|
||||
|
||||
MatchRHSPunctuation(tok::r_paren, Loc);
|
||||
|
@ -735,18 +744,22 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
|||
return ExprResult(true);
|
||||
}
|
||||
|
||||
if (!LHS.isInvalid)
|
||||
LHS = Actions.ActOnMemberReferenceExpr(LHS.Val, OpLoc, OpKind,
|
||||
if (!LHS.isInvalid) {
|
||||
LHS = Actions.ActOnMemberReferenceExpr(LHSGuard.take(), OpLoc, OpKind,
|
||||
Tok.getLocation(),
|
||||
*Tok.getIdentifierInfo());
|
||||
LHSGuard.reset(LHS);
|
||||
}
|
||||
ConsumeToken();
|
||||
break;
|
||||
}
|
||||
case tok::plusplus: // postfix-expression: postfix-expression '++'
|
||||
case tok::minusminus: // postfix-expression: postfix-expression '--'
|
||||
if (!LHS.isInvalid)
|
||||
if (!LHS.isInvalid) {
|
||||
LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
|
||||
Tok.getKind(), LHS.Val);
|
||||
Tok.getKind(), LHSGuard.take());
|
||||
LHSGuard.reset(LHS);
|
||||
}
|
||||
ConsumeToken();
|
||||
break;
|
||||
}
|
||||
|
@ -840,6 +853,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
default: assert(0 && "Not a builtin primary expression!");
|
||||
case tok::kw___builtin_va_arg: {
|
||||
ExprResult Expr = ParseAssignmentExpression();
|
||||
ExprGuard ExprGuard(Actions, Expr);
|
||||
if (Expr.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return ExprResult(true);
|
||||
|
@ -854,7 +868,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
Diag(Tok, diag::err_expected_rparen);
|
||||
return ExprResult(true);
|
||||
}
|
||||
Res = Actions.ActOnVAArg(StartLoc, Expr.Val, Ty, ConsumeParen());
|
||||
Res = Actions.ActOnVAArg(StartLoc, ExprGuard.take(), Ty, ConsumeParen());
|
||||
break;
|
||||
}
|
||||
case tok::kw___builtin_offsetof: {
|
||||
|
@ -879,6 +893,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
|
||||
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
|
||||
|
||||
// FIXME: This loop leaks the index expressions on error.
|
||||
while (1) {
|
||||
if (Tok.is(tok::period)) {
|
||||
// offsetof-member-designator: offsetof-member-designator '.' identifier
|
||||
|
@ -921,6 +936,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
}
|
||||
case tok::kw___builtin_choose_expr: {
|
||||
ExprResult Cond = ParseAssignmentExpression();
|
||||
ExprGuard CondGuard(Actions, Cond);
|
||||
if (Cond.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Cond;
|
||||
|
@ -929,6 +945,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
return ExprResult(true);
|
||||
|
||||
ExprResult Expr1 = ParseAssignmentExpression();
|
||||
ExprGuard Guard1(Actions, Expr1);
|
||||
if (Expr1.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Expr1;
|
||||
|
@ -937,6 +954,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
return ExprResult(true);
|
||||
|
||||
ExprResult Expr2 = ParseAssignmentExpression();
|
||||
ExprGuard Guard2(Actions, Expr2);
|
||||
if (Expr2.isInvalid) {
|
||||
SkipUntil(tok::r_paren);
|
||||
return Expr2;
|
||||
|
@ -945,12 +963,12 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
Diag(Tok, diag::err_expected_rparen);
|
||||
return ExprResult(true);
|
||||
}
|
||||
Res = Actions.ActOnChooseExpr(StartLoc, Cond.Val, Expr1.Val, Expr2.Val,
|
||||
ConsumeParen());
|
||||
Res = Actions.ActOnChooseExpr(StartLoc, CondGuard.take(), Guard1.take(),
|
||||
Guard2.take(), ConsumeParen());
|
||||
break;
|
||||
}
|
||||
case tok::kw___builtin_overload: {
|
||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
||||
ExprVector ArgExprs(Actions);
|
||||
llvm::SmallVector<SourceLocation, 8> CommaLocs;
|
||||
|
||||
// For each iteration through the loop look for assign-expr followed by a
|
||||
|
@ -977,7 +995,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|||
SkipUntil(tok::r_paren);
|
||||
return ExprResult(true);
|
||||
}
|
||||
Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(),
|
||||
Res = Actions.ActOnOverloadExpr(ArgExprs.take(), ArgExprs.size(),
|
||||
&CommaLocs[0], StartLoc, ConsumeParen());
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "AstGuard.h"
|
||||
using namespace clang;
|
||||
|
||||
/// ParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
|
||||
|
@ -328,7 +329,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
|||
assert(Tok.is(tok::l_paren) && "Expected '('!");
|
||||
SourceLocation LParenLoc = ConsumeParen();
|
||||
|
||||
ExprListTy Exprs;
|
||||
ExprVector Exprs(Actions);
|
||||
CommaLocsTy CommaLocs;
|
||||
|
||||
if (Tok.isNot(tok::r_paren)) {
|
||||
|
@ -345,7 +346,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
|||
"Unexpected number of commas!");
|
||||
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
|
||||
LParenLoc,
|
||||
&Exprs[0], Exprs.size(),
|
||||
Exprs.take(), Exprs.size(),
|
||||
&CommaLocs[0], RParenLoc);
|
||||
}
|
||||
|
||||
|
@ -659,7 +660,7 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
|
|||
// A '(' now can be a new-placement or the '(' wrapping the type-id in the
|
||||
// second form of new-expression. It can't be a new-type-id.
|
||||
|
||||
ExprListTy PlacementArgs;
|
||||
ExprVector PlacementArgs(Actions);
|
||||
SourceLocation PlacementLParen, PlacementRParen;
|
||||
|
||||
TypeTy *Ty = 0;
|
||||
|
@ -706,7 +707,7 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
|
|||
ParenTypeId = false;
|
||||
}
|
||||
|
||||
ExprListTy ConstructorArgs;
|
||||
ExprVector ConstructorArgs(Actions);
|
||||
SourceLocation ConstructorLParen, ConstructorRParen;
|
||||
|
||||
if (Tok.is(tok::l_paren)) {
|
||||
|
@ -722,9 +723,9 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
|
|||
}
|
||||
|
||||
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
|
||||
&PlacementArgs[0], PlacementArgs.size(),
|
||||
PlacementArgs.take(), PlacementArgs.size(),
|
||||
PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
|
||||
ConstructorLParen, &ConstructorArgs[0],
|
||||
ConstructorLParen, ConstructorArgs.take(),
|
||||
ConstructorArgs.size(), ConstructorRParen);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "clang/Parse/Designator.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "AstGuard.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
using namespace clang;
|
||||
|
@ -238,11 +239,11 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
|
|||
///
|
||||
Parser::ExprResult Parser::ParseBraceInitializer() {
|
||||
SourceLocation LBraceLoc = ConsumeBrace();
|
||||
|
||||
|
||||
/// InitExprs - This is the actual list of expressions contained in the
|
||||
/// initializer.
|
||||
llvm::SmallVector<ExprTy*, 8> InitExprs;
|
||||
|
||||
ExprVector InitExprs(Actions);
|
||||
|
||||
/// ExprDesignators - For each initializer, keep track of the designator that
|
||||
/// was specified for it, if any.
|
||||
InitListDesignations InitExprDesignations(Actions);
|
||||
|
@ -289,6 +290,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
|
|||
// parsing the rest of the initializer. This allows us to emit
|
||||
// diagnostics for later elements that we find. If we don't see a comma,
|
||||
// assume there is a parse error, and just skip to recover.
|
||||
// FIXME: This comment doesn't sound right. If there is a r_brace
|
||||
// immediately, it can't be an error, since there is no other way of
|
||||
// leaving this loop except through this if.
|
||||
if (Tok.isNot(tok::comma)) {
|
||||
SkipUntil(tok::r_brace, false, true);
|
||||
break;
|
||||
|
@ -305,13 +309,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
|
|||
if (Tok.is(tok::r_brace)) break;
|
||||
}
|
||||
if (InitExprsOk && Tok.is(tok::r_brace))
|
||||
return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(),
|
||||
return Actions.ActOnInitList(LBraceLoc, InitExprs.take(), InitExprs.size(),
|
||||
InitExprDesignations, ConsumeBrace());
|
||||
|
||||
// On error, delete any parsed subexpressions.
|
||||
for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
|
||||
Actions.DeleteExpr(InitExprs[i]);
|
||||
|
||||
// Match the '}'.
|
||||
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
|
||||
return ExprResult(true); // an error occurred.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "clang/Parse/Parser.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
#include "clang/Parse/Scope.h"
|
||||
#include "AstGuard.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
using namespace clang;
|
||||
|
@ -1194,6 +1195,7 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
|
|||
}
|
||||
ConsumeParen(); // '('
|
||||
ExprResult Res = ParseExpression();
|
||||
ExprGuard ResGuard(Actions, Res);
|
||||
if (Res.isInvalid) {
|
||||
SkipUntil(tok::semi);
|
||||
return true;
|
||||
|
@ -1216,7 +1218,8 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
|
|||
ExitScope();
|
||||
if (SynchBody.isInvalid)
|
||||
SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||
return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.Val, SynchBody.Val);
|
||||
return Actions.ActOnObjCAtSynchronizedStmt(atLoc, ResGuard.take(),
|
||||
SynchBody.Val);
|
||||
}
|
||||
|
||||
/// objc-try-catch-statement:
|
||||
|
@ -1245,7 +1248,9 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
|||
ExitScope();
|
||||
if (TryBody.isInvalid)
|
||||
TryBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||
|
||||
ExprGuard TryGuard(Actions, TryBody);
|
||||
ExprGuard CatchGuard(Actions), FinallyGuard(Actions);
|
||||
|
||||
while (Tok.is(tok::at)) {
|
||||
// At this point, we need to lookahead to determine if this @ is the start
|
||||
// of an @catch or @finally. We don't want to consume the @ token if this
|
||||
|
@ -1290,7 +1295,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
|||
if (CatchBody.isInvalid)
|
||||
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||
CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc,
|
||||
FirstPart, CatchBody.Val, CatchStmts.Val);
|
||||
FirstPart, CatchBody.Val, CatchGuard.take());
|
||||
CatchGuard.reset(CatchStmts);
|
||||
ExitScope();
|
||||
} else {
|
||||
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
|
||||
|
@ -1313,6 +1319,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
|||
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
|
||||
FinallyBody.Val);
|
||||
FinallyGuard.reset(FinallyStmt);
|
||||
catch_or_finally_seen = true;
|
||||
ExitScope();
|
||||
break;
|
||||
|
@ -1322,8 +1329,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
|||
Diag(atLoc, diag::err_missing_catch_finally);
|
||||
return true;
|
||||
}
|
||||
return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.Val, CatchStmts.Val,
|
||||
FinallyStmt.Val);
|
||||
return Actions.ActOnObjCAtTryStmt(atLoc, TryGuard.take(), CatchGuard.take(),
|
||||
FinallyGuard.take());
|
||||
}
|
||||
|
||||
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
|
||||
|
@ -1468,7 +1475,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
|||
IdentifierInfo *selIdent = ParseObjCSelector(Loc);
|
||||
|
||||
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
|
||||
llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
|
||||
ExprVector KeyExprs(Actions);
|
||||
|
||||
if (Tok.is(tok::colon)) {
|
||||
while (1) {
|
||||
|
@ -1551,9 +1558,9 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
|||
return Actions.ActOnClassMessage(CurScope,
|
||||
ReceiverName, Sel,
|
||||
LBracLoc, NameLoc, RBracLoc,
|
||||
&KeyExprs[0], KeyExprs.size());
|
||||
KeyExprs.take(), KeyExprs.size());
|
||||
return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
|
||||
&KeyExprs[0], KeyExprs.size());
|
||||
KeyExprs.take(), KeyExprs.size());
|
||||
}
|
||||
|
||||
Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
|
||||
|
@ -1564,31 +1571,26 @@ Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
|
|||
// expressions. At this point, we know that the only valid thing that starts
|
||||
// with '@' is an @"".
|
||||
llvm::SmallVector<SourceLocation, 4> AtLocs;
|
||||
llvm::SmallVector<ExprTy*, 4> AtStrings;
|
||||
ExprVector AtStrings(Actions);
|
||||
AtLocs.push_back(AtLoc);
|
||||
AtStrings.push_back(Res.Val);
|
||||
|
||||
while (Tok.is(tok::at)) {
|
||||
AtLocs.push_back(ConsumeToken()); // eat the @.
|
||||
|
||||
ExprResult Res(true); // Invalid unless there is a string literal.
|
||||
ExprResult Lit(true); // Invalid unless there is a string literal.
|
||||
if (isTokenStringLiteral())
|
||||
Res = ParseStringLiteralExpression();
|
||||
Lit = ParseStringLiteralExpression();
|
||||
else
|
||||
Diag(Tok, diag::err_objc_concat_string);
|
||||
|
||||
if (Res.isInvalid) {
|
||||
while (!AtStrings.empty()) {
|
||||
Actions.DeleteExpr(AtStrings.back());
|
||||
AtStrings.pop_back();
|
||||
}
|
||||
return Res;
|
||||
}
|
||||
if (Lit.isInvalid)
|
||||
return Lit;
|
||||
|
||||
AtStrings.push_back(Res.Val);
|
||||
AtStrings.push_back(Lit.Val);
|
||||
}
|
||||
|
||||
return Actions.ParseObjCStringLiteral(&AtLocs[0], &AtStrings[0],
|
||||
return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
|
||||
AtStrings.size());
|
||||
}
|
||||
|
||||
|
@ -1614,7 +1616,6 @@ Parser::ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
|
|||
|
||||
/// objc-protocol-expression
|
||||
/// @protocol ( protocol-name )
|
||||
|
||||
Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
|
||||
SourceLocation ProtoLoc = ConsumeToken();
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ParsePragma.h"
|
||||
#include "AstGuard.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Parse/Action.h"
|
||||
|
@ -35,12 +36,14 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
Action::PragmaPackKind Kind = Action::PPK_Default;
|
||||
IdentifierInfo *Name = 0;
|
||||
Action::ExprResult Alignment;
|
||||
ExprGuard AlignmentGuard(Actions);
|
||||
SourceLocation LParenLoc = Tok.getLocation();
|
||||
PP.Lex(Tok);
|
||||
if (Tok.is(tok::numeric_constant)) {
|
||||
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||
if (Alignment.isInvalid)
|
||||
return;
|
||||
AlignmentGuard.reset(Alignment);
|
||||
|
||||
PP.Lex(Tok);
|
||||
} else if (Tok.is(tok::identifier)) {
|
||||
|
@ -66,6 +69,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||
if (Alignment.isInvalid)
|
||||
return;
|
||||
AlignmentGuard.reset(Alignment);
|
||||
|
||||
PP.Lex(Tok);
|
||||
} else if (Tok.is(tok::identifier)) {
|
||||
|
@ -83,6 +87,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||
if (Alignment.isInvalid)
|
||||
return;
|
||||
AlignmentGuard.reset(Alignment);
|
||||
|
||||
PP.Lex(Tok);
|
||||
}
|
||||
|
@ -100,7 +105,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
|||
}
|
||||
|
||||
SourceLocation RParenLoc = Tok.getLocation();
|
||||
Actions.ActOnPragmaPack(Kind, Name, Alignment.Val, PackLoc,
|
||||
Actions.ActOnPragmaPack(Kind, Name, AlignmentGuard.take(), PackLoc,
|
||||
LParenLoc, RParenLoc);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "ExtensionRAIIObject.h"
|
||||
#include "AstGuard.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Parse/DeclSpec.h"
|
||||
|
@ -229,6 +230,7 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
|||
SkipUntil(tok::colon);
|
||||
return true;
|
||||
}
|
||||
ExprGuard LHSGuard(Actions, LHS);
|
||||
|
||||
// GNU case range extension.
|
||||
SourceLocation DotDotDotLoc;
|
||||
|
@ -244,6 +246,7 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
|||
}
|
||||
RHSVal = RHS.Val;
|
||||
}
|
||||
ExprGuard RHSGuard(Actions, RHSVal);
|
||||
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
Diag(Tok, diag::err_expected_colon_after) << "'case'";
|
||||
|
@ -265,8 +268,8 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
|||
if (SubStmt.isInvalid)
|
||||
SubStmt = Actions.ActOnNullStmt(ColonLoc);
|
||||
|
||||
return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
|
||||
SubStmt.Val);
|
||||
return Actions.ActOnCaseStmt(CaseLoc, LHSGuard.take(), DotDotDotLoc,
|
||||
RHSGuard.take(), ColonLoc, SubStmt.Val);
|
||||
}
|
||||
|
||||
/// ParseDefaultStatement
|
||||
|
@ -351,8 +354,9 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
|||
|
||||
// TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
|
||||
// only allowed at the start of a compound stmt regardless of the language.
|
||||
|
||||
llvm::SmallVector<StmtTy*, 32> Stmts;
|
||||
|
||||
typedef StmtVector StmtsTy;
|
||||
StmtsTy Stmts(Actions);
|
||||
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||
StmtResult R;
|
||||
if (Tok.isNot(tok::kw___extension__)) {
|
||||
|
@ -410,7 +414,7 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
|||
|
||||
SourceLocation RBraceLoc = ConsumeBrace();
|
||||
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
|
||||
&Stmts[0], Stmts.size(), isStmtExpr);
|
||||
Stmts.take(), Stmts.size(), isStmtExpr);
|
||||
}
|
||||
|
||||
/// ParseIfStatement
|
||||
|
@ -456,6 +460,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
|||
} else {
|
||||
CondExp = ParseSimpleParenExpression();
|
||||
}
|
||||
ExprGuard CondGuard(Actions, CondExp);
|
||||
|
||||
if (CondExp.isInvalid) {
|
||||
SkipUntil(tok::semi);
|
||||
|
@ -528,9 +533,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
|||
if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
|
||||
(ThenStmt.isInvalid && ElseStmt.Val == 0) ||
|
||||
(ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
|
||||
// Both invalid, or one is invalid and other is non-present: delete cond and
|
||||
// return error.
|
||||
Actions.DeleteExpr(CondExp.Val);
|
||||
// Both invalid, or one is invalid and other is non-present: return error.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -540,7 +543,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
|||
if (ElseStmt.isInvalid)
|
||||
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
|
||||
|
||||
return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
|
||||
return Actions.ActOnIfStmt(IfLoc, CondGuard.take(), ThenStmt.Val,
|
||||
ElseLoc, ElseStmt.Val);
|
||||
}
|
||||
|
||||
|
@ -668,6 +671,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
|
|||
} else {
|
||||
Cond = ParseSimpleParenExpression();
|
||||
}
|
||||
ExprGuard CondGuard(Actions, Cond);
|
||||
|
||||
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
|
||||
// there is no compound stmt. C90 does not have this clause. We only do this
|
||||
|
@ -685,6 +689,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
|
|||
|
||||
// Read the body statement.
|
||||
StmtResult Body = ParseStatement();
|
||||
StmtGuard BodyGuard(Actions, Body);
|
||||
|
||||
// Pop the body scope if needed.
|
||||
if (NeedsInnerScope) ExitScope();
|
||||
|
@ -693,7 +698,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
|
|||
|
||||
if (Cond.isInvalid || Body.isInvalid) return true;
|
||||
|
||||
return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
|
||||
return Actions.ActOnWhileStmt(WhileLoc, CondGuard.take(), BodyGuard.take());
|
||||
}
|
||||
|
||||
/// ParseDoStatement
|
||||
|
@ -725,6 +730,7 @@ Parser::StmtResult Parser::ParseDoStatement() {
|
|||
|
||||
// Read the body statement.
|
||||
StmtResult Body = ParseStatement();
|
||||
StmtGuard BodyGuard(Actions, Body);
|
||||
|
||||
// Pop the body scope if needed.
|
||||
if (NeedsInnerScope) ExitScope();
|
||||
|
@ -749,12 +755,14 @@ Parser::StmtResult Parser::ParseDoStatement() {
|
|||
|
||||
// Parse the condition.
|
||||
ExprResult Cond = ParseSimpleParenExpression();
|
||||
ExprGuard CondGuard(Actions, Cond);
|
||||
|
||||
ExitScope();
|
||||
|
||||
if (Cond.isInvalid || Body.isInvalid) return true;
|
||||
|
||||
return Actions.ActOnDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
|
||||
return Actions.ActOnDoStmt(DoLoc, BodyGuard.take(),
|
||||
WhileLoc, CondGuard.take());
|
||||
}
|
||||
|
||||
/// ParseForStatement
|
||||
|
@ -810,6 +818,8 @@ Parser::StmtResult Parser::ParseForStatement() {
|
|||
ExprTy *SecondPart = 0;
|
||||
StmtTy *ThirdPart = 0;
|
||||
bool ForEach = false;
|
||||
StmtGuard FirstGuard(Actions), ThirdGuard(Actions);
|
||||
ExprGuard SecondGuard(Actions);
|
||||
|
||||
// Parse the first part of the for specifier.
|
||||
if (Tok.is(tok::semi)) { // for (;
|
||||
|
@ -856,7 +866,10 @@ Parser::StmtResult Parser::ParseForStatement() {
|
|||
SkipUntil(tok::semi);
|
||||
}
|
||||
}
|
||||
FirstGuard.reset(FirstPart);
|
||||
SecondGuard.reset(SecondPart);
|
||||
if (!ForEach) {
|
||||
assert(!SecondGuard.get() && "Shouldn't have a second expression yet.");
|
||||
// Parse the second part of the for specifier.
|
||||
if (Tok.is(tok::semi)) { // for (...;;
|
||||
// no second part.
|
||||
|
@ -888,6 +901,8 @@ Parser::StmtResult Parser::ParseForStatement() {
|
|||
ThirdPart = R.Val;
|
||||
}
|
||||
}
|
||||
SecondGuard.reset(SecondPart);
|
||||
ThirdGuard.reset(ThirdPart);
|
||||
}
|
||||
// Match the ')'.
|
||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
|
@ -918,6 +933,10 @@ Parser::StmtResult Parser::ParseForStatement() {
|
|||
if (Body.isInvalid)
|
||||
return Body;
|
||||
|
||||
// Release all the guards.
|
||||
FirstGuard.take();
|
||||
SecondGuard.take();
|
||||
ThirdGuard.take();
|
||||
if (!ForEach)
|
||||
return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart,
|
||||
SecondPart, ThirdPart, RParenLoc, Body.Val);
|
||||
|
@ -1082,11 +1101,12 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
|||
ExprResult AsmString = ParseAsmStringLiteral();
|
||||
if (AsmString.isInvalid)
|
||||
return true;
|
||||
ExprGuard AsmGuard(Actions, AsmString);
|
||||
|
||||
llvm::SmallVector<std::string, 4> Names;
|
||||
llvm::SmallVector<ExprTy*, 4> Constraints;
|
||||
llvm::SmallVector<ExprTy*, 4> Exprs;
|
||||
llvm::SmallVector<ExprTy*, 4> Clobbers;
|
||||
ExprVector Constraints(Actions);
|
||||
ExprVector Exprs(Actions);
|
||||
ExprVector Clobbers(Actions);
|
||||
|
||||
unsigned NumInputs = 0, NumOutputs = 0;
|
||||
|
||||
|
@ -1097,7 +1117,7 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
|||
|
||||
RParenLoc = ConsumeParen();
|
||||
} else {
|
||||
// Parse Outputs, if present.
|
||||
// Parse Outputs, if present.
|
||||
if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
|
||||
return true;
|
||||
|
||||
|
@ -1136,9 +1156,9 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
|||
|
||||
return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
|
||||
NumOutputs, NumInputs,
|
||||
&Names[0], &Constraints[0], &Exprs[0],
|
||||
AsmString.Val,
|
||||
Clobbers.size(), &Clobbers[0],
|
||||
&Names[0], Constraints.take(),
|
||||
Exprs.take(), AsmGuard.take(),
|
||||
Clobbers.size(), Clobbers.take(),
|
||||
RParenLoc);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue