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 ParseSizeofAlignofExpression();
|
||||||
ExprResult ParseBuiltinPrimaryExpression();
|
ExprResult ParseBuiltinPrimaryExpression();
|
||||||
|
|
||||||
typedef llvm::SmallVector<ExprTy*, 8> ExprListTy;
|
static const unsigned ExprListSize = 12;
|
||||||
typedef llvm::SmallVector<SourceLocation, 8> CommaLocsTy;
|
typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
|
||||||
|
typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
|
||||||
|
|
||||||
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
|
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
|
||||||
bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs);
|
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/Basic/Diagnostic.h"
|
||||||
#include "clang/Parse/Scope.h"
|
#include "clang/Parse/Scope.h"
|
||||||
#include "ExtensionRAIIObject.h"
|
#include "ExtensionRAIIObject.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "llvm/ADT/SmallSet.h"
|
#include "llvm/ADT/SmallSet.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ AttributeList *Parser::ParseAttributes() {
|
||||||
} else if (Tok.is(tok::comma)) {
|
} else if (Tok.is(tok::comma)) {
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
// __attribute__(( format(printf, 1, 2) ))
|
// __attribute__(( format(printf, 1, 2) ))
|
||||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
ExprVector ArgExprs(Actions);
|
||||||
bool ArgExprsOk = true;
|
bool ArgExprsOk = true;
|
||||||
|
|
||||||
// now parse the non-empty comma separated list of expressions
|
// now parse the non-empty comma separated list of expressions
|
||||||
|
@ -142,7 +143,7 @@ AttributeList *Parser::ParseAttributes() {
|
||||||
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
||||||
ConsumeParen(); // ignore the right paren loc for now
|
ConsumeParen(); // ignore the right paren loc for now
|
||||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
|
CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
|
||||||
ParmLoc, &ArgExprs[0], ArgExprs.size(), CurrAttr);
|
ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // not an identifier
|
} else { // not an identifier
|
||||||
|
@ -154,7 +155,7 @@ AttributeList *Parser::ParseAttributes() {
|
||||||
0, SourceLocation(), 0, 0, CurrAttr);
|
0, SourceLocation(), 0, 0, CurrAttr);
|
||||||
} else {
|
} else {
|
||||||
// __attribute__(( aligned(16) ))
|
// __attribute__(( aligned(16) ))
|
||||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
ExprVector ArgExprs(Actions);
|
||||||
bool ArgExprsOk = true;
|
bool ArgExprsOk = true;
|
||||||
|
|
||||||
// now parse the list of expressions
|
// now parse the list of expressions
|
||||||
|
@ -175,7 +176,7 @@ AttributeList *Parser::ParseAttributes() {
|
||||||
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
if (ArgExprsOk && Tok.is(tok::r_paren)) {
|
||||||
ConsumeParen(); // ignore the right paren loc for now
|
ConsumeParen(); // ignore the right paren loc for now
|
||||||
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
|
CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
|
||||||
SourceLocation(), &ArgExprs[0], ArgExprs.size(),
|
SourceLocation(), ArgExprs.take(), ArgExprs.size(),
|
||||||
CurrAttr);
|
CurrAttr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +296,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
||||||
} else if (Tok.is(tok::l_paren)) {
|
} else if (Tok.is(tok::l_paren)) {
|
||||||
// Parse C++ direct initializer: '(' expression-list ')'
|
// Parse C++ direct initializer: '(' expression-list ')'
|
||||||
SourceLocation LParenLoc = ConsumeParen();
|
SourceLocation LParenLoc = ConsumeParen();
|
||||||
ExprListTy Exprs;
|
ExprVector Exprs(Actions);
|
||||||
CommaLocsTy CommaLocs;
|
CommaLocsTy CommaLocs;
|
||||||
|
|
||||||
bool InvalidExpr = false;
|
bool InvalidExpr = false;
|
||||||
|
@ -310,7 +311,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
||||||
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
|
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
|
||||||
"Unexpected number of commas!");
|
"Unexpected number of commas!");
|
||||||
Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
|
Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
|
||||||
&Exprs[0], Exprs.size(),
|
Exprs.take(), Exprs.size(),
|
||||||
&CommaLocs[0], RParenLoc);
|
&CommaLocs[0], RParenLoc);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1988,6 +1989,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||||
} else { // we have an expression.
|
} else { // we have an expression.
|
||||||
ExprResult Result = ParseExpression();
|
ExprResult Result = ParseExpression();
|
||||||
|
ExprGuard ResultGuard(Actions, Result);
|
||||||
|
|
||||||
if (Result.isInvalid || Tok.isNot(tok::r_paren)) {
|
if (Result.isInvalid || Tok.isNot(tok::r_paren)) {
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
@ -1997,7 +1999,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||||
const char *PrevSpec = 0;
|
const char *PrevSpec = 0;
|
||||||
// Check for duplicate type specifiers (e.g. "int typeof(int)").
|
// Check for duplicate type specifiers (e.g. "int typeof(int)").
|
||||||
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
|
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
|
||||||
Result.Val))
|
ResultGuard.take()))
|
||||||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||||
}
|
}
|
||||||
DS.SetRangeEnd(RParenLoc);
|
DS.SetRangeEnd(RParenLoc);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
#include "clang/Parse/Scope.h"
|
#include "clang/Parse/Scope.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
/// ParseNamespace - We know that the current token is a namespace keyword. This
|
/// 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
|
// Notify semantic analysis that we have parsed a complete
|
||||||
// base-specifier.
|
// base-specifier.
|
||||||
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
|
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
|
||||||
BaseLoc);
|
BaseType, BaseLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getAccessSpecifierIfPresent - Determine whether the next token is
|
/// getAccessSpecifierIfPresent - Determine whether the next token is
|
||||||
|
@ -747,7 +748,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
|
||||||
SourceLocation LParenLoc = ConsumeParen();
|
SourceLocation LParenLoc = ConsumeParen();
|
||||||
|
|
||||||
// Parse the optional expression-list.
|
// Parse the optional expression-list.
|
||||||
ExprListTy ArgExprs;
|
ExprVector ArgExprs(Actions);
|
||||||
CommaLocsTy CommaLocs;
|
CommaLocsTy CommaLocs;
|
||||||
if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
|
if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
|
||||||
SkipUntil(tok::r_paren);
|
SkipUntil(tok::r_paren);
|
||||||
|
@ -757,8 +758,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
|
||||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
|
||||||
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
|
return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
|
||||||
LParenLoc, &ArgExprs[0], ArgExprs.size(),
|
LParenLoc, ArgExprs.take(),
|
||||||
&CommaLocs[0], RParenLoc);
|
ArgExprs.size(), &CommaLocs[0], RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseExceptionSpecification - Parse a C++ exception-specification
|
/// ParseExceptionSpecification - Parse a C++ exception-specification
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
#include "clang/Parse/Scope.h"
|
#include "clang/Parse/Scope.h"
|
||||||
#include "ExtensionRAIIObject.h"
|
#include "ExtensionRAIIObject.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
@ -238,12 +239,15 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
||||||
SourceLocation ColonLoc;
|
SourceLocation ColonLoc;
|
||||||
|
|
||||||
|
ExprGuard LHSGuard(Actions, LHS);
|
||||||
while (1) {
|
while (1) {
|
||||||
// If this token has a lower precedence than we are allowed to parse (e.g.
|
// 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),
|
// because we are called recursively, or because the token is not a binop),
|
||||||
// then we are done!
|
// then we are done!
|
||||||
if (NextTokPrec < MinPrec)
|
if (NextTokPrec < MinPrec) {
|
||||||
|
LHSGuard.take();
|
||||||
return LHS;
|
return LHS;
|
||||||
|
}
|
||||||
|
|
||||||
// Consume the operator, saving the operator token for error reporting.
|
// Consume the operator, saving the operator token for error reporting.
|
||||||
Token OpToken = Tok;
|
Token OpToken = Tok;
|
||||||
|
@ -251,6 +255,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
|
|
||||||
// Special case handling for the ternary operator.
|
// Special case handling for the ternary operator.
|
||||||
ExprResult TernaryMiddle(true);
|
ExprResult TernaryMiddle(true);
|
||||||
|
ExprGuard MiddleGuard(Actions);
|
||||||
if (NextTokPrec == prec::Conditional) {
|
if (NextTokPrec == prec::Conditional) {
|
||||||
if (Tok.isNot(tok::colon)) {
|
if (Tok.isNot(tok::colon)) {
|
||||||
// Handle this production specially:
|
// Handle this production specially:
|
||||||
|
@ -259,7 +264,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
// 'logical-OR-expression' as we might expect.
|
// 'logical-OR-expression' as we might expect.
|
||||||
TernaryMiddle = ParseExpression();
|
TernaryMiddle = ParseExpression();
|
||||||
if (TernaryMiddle.isInvalid) {
|
if (TernaryMiddle.isInvalid) {
|
||||||
Actions.DeleteExpr(LHS.Val);
|
|
||||||
return TernaryMiddle;
|
return TernaryMiddle;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,12 +272,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
TernaryMiddle = ExprResult(false);
|
TernaryMiddle = ExprResult(false);
|
||||||
Diag(Tok, diag::ext_gnu_conditional_expr);
|
Diag(Tok, diag::ext_gnu_conditional_expr);
|
||||||
}
|
}
|
||||||
|
MiddleGuard.reset(TernaryMiddle);
|
||||||
|
|
||||||
if (Tok.isNot(tok::colon)) {
|
if (Tok.isNot(tok::colon)) {
|
||||||
Diag(Tok, diag::err_expected_colon);
|
Diag(Tok, diag::err_expected_colon);
|
||||||
Diag(OpToken, diag::note_matching) << "?";
|
Diag(OpToken, diag::note_matching) << "?";
|
||||||
Actions.DeleteExpr(LHS.Val);
|
|
||||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,10 +287,9 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
// Parse another leaf here for the RHS of the operator.
|
// Parse another leaf here for the RHS of the operator.
|
||||||
ExprResult RHS = ParseCastExpression(false);
|
ExprResult RHS = ParseCastExpression(false);
|
||||||
if (RHS.isInvalid) {
|
if (RHS.isInvalid) {
|
||||||
Actions.DeleteExpr(LHS.Val);
|
|
||||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
|
||||||
return RHS;
|
return RHS;
|
||||||
}
|
}
|
||||||
|
ExprGuard RHSGuard(Actions, RHS);
|
||||||
|
|
||||||
// Remember the precedence of this operator and get the precedence of the
|
// Remember the precedence of this operator and get the precedence of the
|
||||||
// operator immediately to the right of the RHS.
|
// operator immediately to the right of the RHS.
|
||||||
|
@ -306,12 +308,13 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
// more tightly than the current operator. If it is left-associative, it
|
// 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
|
// 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.
|
// 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);
|
RHS = ParseRHSOfBinaryExpression(RHS, ThisPrec + !isRightAssoc);
|
||||||
if (RHS.isInvalid) {
|
if (RHS.isInvalid) {
|
||||||
Actions.DeleteExpr(LHS.Val);
|
|
||||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
|
||||||
return RHS;
|
return RHS;
|
||||||
}
|
}
|
||||||
|
RHSGuard.reset(RHS);
|
||||||
|
|
||||||
NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
NextTokPrec = getBinOpPrecedence(Tok.getKind());
|
||||||
}
|
}
|
||||||
|
@ -319,17 +322,18 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
|
||||||
|
|
||||||
if (!LHS.isInvalid) {
|
if (!LHS.isInvalid) {
|
||||||
// Combine the LHS and RHS into the LHS (e.g. build AST).
|
// Combine the LHS and RHS into the LHS (e.g. build AST).
|
||||||
|
LHSGuard.take();
|
||||||
|
MiddleGuard.take();
|
||||||
|
RHSGuard.take();
|
||||||
if (TernaryMiddle.isInvalid)
|
if (TernaryMiddle.isInvalid)
|
||||||
LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
|
LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
|
||||||
OpToken.getKind(), LHS.Val, RHS.Val);
|
OpToken.getKind(), LHS.Val, RHS.Val);
|
||||||
else
|
else
|
||||||
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
|
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
|
||||||
LHS.Val, TernaryMiddle.Val, RHS.Val);
|
LHS.Val, TernaryMiddle.Val, RHS.Val);
|
||||||
} else {
|
LHSGuard.reset(LHS);
|
||||||
// We had a semantic error on the LHS. Just free the RHS and continue.
|
|
||||||
Actions.DeleteExpr(TernaryMiddle.Val);
|
|
||||||
Actions.DeleteExpr(RHS.Val);
|
|
||||||
}
|
}
|
||||||
|
// 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
|
/// argument-expression-list ',' assignment-expression
|
||||||
///
|
///
|
||||||
Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||||
|
ExprGuard LHSGuard(Actions, LHS);
|
||||||
// Now that the primary-expression piece of the postfix-expression has been
|
// Now that the primary-expression piece of the postfix-expression has been
|
||||||
// parsed, see if there are any postfix-expression pieces here.
|
// parsed, see if there are any postfix-expression pieces here.
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
default: // Not a postfix-expression suffix.
|
default: // Not a postfix-expression suffix.
|
||||||
|
LHSGuard.take();
|
||||||
return LHS;
|
return LHS;
|
||||||
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
|
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
|
||||||
Loc = ConsumeBracket();
|
Loc = ConsumeBracket();
|
||||||
ExprResult Idx = ParseExpression();
|
ExprResult Idx = ParseExpression();
|
||||||
|
ExprGuard IdxGuard(Actions, Idx);
|
||||||
|
|
||||||
SourceLocation RLoc = Tok.getLocation();
|
SourceLocation RLoc = Tok.getLocation();
|
||||||
|
|
||||||
if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square))
|
if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square)) {
|
||||||
LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHS.Val, Loc,
|
LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHSGuard.take(), Loc,
|
||||||
Idx.Val, RLoc);
|
IdxGuard.take(), RLoc);
|
||||||
else
|
LHSGuard.reset(LHS);
|
||||||
|
} else
|
||||||
LHS = ExprResult(true);
|
LHS = ExprResult(true);
|
||||||
|
|
||||||
// Match the ']'.
|
// Match the ']'.
|
||||||
|
@ -702,7 +709,7 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
|
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
|
||||||
ExprListTy ArgExprs;
|
ExprVector ArgExprs(Actions);
|
||||||
CommaLocsTy CommaLocs;
|
CommaLocsTy CommaLocs;
|
||||||
|
|
||||||
Loc = ConsumeParen();
|
Loc = ConsumeParen();
|
||||||
|
@ -718,8 +725,10 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||||
if (!LHS.isInvalid && Tok.is(tok::r_paren)) {
|
if (!LHS.isInvalid && Tok.is(tok::r_paren)) {
|
||||||
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
|
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
|
||||||
"Unexpected number of commas!");
|
"Unexpected number of commas!");
|
||||||
LHS = Actions.ActOnCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(),
|
LHS = Actions.ActOnCallExpr(LHSGuard.take(), Loc, ArgExprs.take(),
|
||||||
&CommaLocs[0], Tok.getLocation());
|
ArgExprs.size(), &CommaLocs[0],
|
||||||
|
Tok.getLocation());
|
||||||
|
LHSGuard.reset(LHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchRHSPunctuation(tok::r_paren, Loc);
|
MatchRHSPunctuation(tok::r_paren, Loc);
|
||||||
|
@ -735,18 +744,22 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LHS.isInvalid)
|
if (!LHS.isInvalid) {
|
||||||
LHS = Actions.ActOnMemberReferenceExpr(LHS.Val, OpLoc, OpKind,
|
LHS = Actions.ActOnMemberReferenceExpr(LHSGuard.take(), OpLoc, OpKind,
|
||||||
Tok.getLocation(),
|
Tok.getLocation(),
|
||||||
*Tok.getIdentifierInfo());
|
*Tok.getIdentifierInfo());
|
||||||
|
LHSGuard.reset(LHS);
|
||||||
|
}
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::plusplus: // postfix-expression: postfix-expression '++'
|
case tok::plusplus: // postfix-expression: postfix-expression '++'
|
||||||
case tok::minusminus: // postfix-expression: postfix-expression '--'
|
case tok::minusminus: // postfix-expression: postfix-expression '--'
|
||||||
if (!LHS.isInvalid)
|
if (!LHS.isInvalid) {
|
||||||
LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
|
LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
|
||||||
Tok.getKind(), LHS.Val);
|
Tok.getKind(), LHSGuard.take());
|
||||||
|
LHSGuard.reset(LHS);
|
||||||
|
}
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -840,6 +853,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
default: assert(0 && "Not a builtin primary expression!");
|
default: assert(0 && "Not a builtin primary expression!");
|
||||||
case tok::kw___builtin_va_arg: {
|
case tok::kw___builtin_va_arg: {
|
||||||
ExprResult Expr = ParseAssignmentExpression();
|
ExprResult Expr = ParseAssignmentExpression();
|
||||||
|
ExprGuard ExprGuard(Actions, Expr);
|
||||||
if (Expr.isInvalid) {
|
if (Expr.isInvalid) {
|
||||||
SkipUntil(tok::r_paren);
|
SkipUntil(tok::r_paren);
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
|
@ -854,7 +868,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
Diag(Tok, diag::err_expected_rparen);
|
Diag(Tok, diag::err_expected_rparen);
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
}
|
}
|
||||||
Res = Actions.ActOnVAArg(StartLoc, Expr.Val, Ty, ConsumeParen());
|
Res = Actions.ActOnVAArg(StartLoc, ExprGuard.take(), Ty, ConsumeParen());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::kw___builtin_offsetof: {
|
case tok::kw___builtin_offsetof: {
|
||||||
|
@ -879,6 +893,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
|
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
|
||||||
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
|
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
|
||||||
|
|
||||||
|
// FIXME: This loop leaks the index expressions on error.
|
||||||
while (1) {
|
while (1) {
|
||||||
if (Tok.is(tok::period)) {
|
if (Tok.is(tok::period)) {
|
||||||
// offsetof-member-designator: offsetof-member-designator '.' identifier
|
// offsetof-member-designator: offsetof-member-designator '.' identifier
|
||||||
|
@ -921,6 +936,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
}
|
}
|
||||||
case tok::kw___builtin_choose_expr: {
|
case tok::kw___builtin_choose_expr: {
|
||||||
ExprResult Cond = ParseAssignmentExpression();
|
ExprResult Cond = ParseAssignmentExpression();
|
||||||
|
ExprGuard CondGuard(Actions, Cond);
|
||||||
if (Cond.isInvalid) {
|
if (Cond.isInvalid) {
|
||||||
SkipUntil(tok::r_paren);
|
SkipUntil(tok::r_paren);
|
||||||
return Cond;
|
return Cond;
|
||||||
|
@ -929,6 +945,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
|
|
||||||
ExprResult Expr1 = ParseAssignmentExpression();
|
ExprResult Expr1 = ParseAssignmentExpression();
|
||||||
|
ExprGuard Guard1(Actions, Expr1);
|
||||||
if (Expr1.isInvalid) {
|
if (Expr1.isInvalid) {
|
||||||
SkipUntil(tok::r_paren);
|
SkipUntil(tok::r_paren);
|
||||||
return Expr1;
|
return Expr1;
|
||||||
|
@ -937,6 +954,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
|
|
||||||
ExprResult Expr2 = ParseAssignmentExpression();
|
ExprResult Expr2 = ParseAssignmentExpression();
|
||||||
|
ExprGuard Guard2(Actions, Expr2);
|
||||||
if (Expr2.isInvalid) {
|
if (Expr2.isInvalid) {
|
||||||
SkipUntil(tok::r_paren);
|
SkipUntil(tok::r_paren);
|
||||||
return Expr2;
|
return Expr2;
|
||||||
|
@ -945,12 +963,12 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
Diag(Tok, diag::err_expected_rparen);
|
Diag(Tok, diag::err_expected_rparen);
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
}
|
}
|
||||||
Res = Actions.ActOnChooseExpr(StartLoc, Cond.Val, Expr1.Val, Expr2.Val,
|
Res = Actions.ActOnChooseExpr(StartLoc, CondGuard.take(), Guard1.take(),
|
||||||
ConsumeParen());
|
Guard2.take(), ConsumeParen());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::kw___builtin_overload: {
|
case tok::kw___builtin_overload: {
|
||||||
llvm::SmallVector<ExprTy*, 8> ArgExprs;
|
ExprVector ArgExprs(Actions);
|
||||||
llvm::SmallVector<SourceLocation, 8> CommaLocs;
|
llvm::SmallVector<SourceLocation, 8> CommaLocs;
|
||||||
|
|
||||||
// For each iteration through the loop look for assign-expr followed by a
|
// 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);
|
SkipUntil(tok::r_paren);
|
||||||
return ExprResult(true);
|
return ExprResult(true);
|
||||||
}
|
}
|
||||||
Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(),
|
Res = Actions.ActOnOverloadExpr(ArgExprs.take(), ArgExprs.size(),
|
||||||
&CommaLocs[0], StartLoc, ConsumeParen());
|
&CommaLocs[0], StartLoc, ConsumeParen());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Parse/Parser.h"
|
#include "clang/Parse/Parser.h"
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
/// ParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
|
/// 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 '('!");
|
assert(Tok.is(tok::l_paren) && "Expected '('!");
|
||||||
SourceLocation LParenLoc = ConsumeParen();
|
SourceLocation LParenLoc = ConsumeParen();
|
||||||
|
|
||||||
ExprListTy Exprs;
|
ExprVector Exprs(Actions);
|
||||||
CommaLocsTy CommaLocs;
|
CommaLocsTy CommaLocs;
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
|
@ -345,7 +346,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
|
||||||
"Unexpected number of commas!");
|
"Unexpected number of commas!");
|
||||||
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
|
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
|
||||||
LParenLoc,
|
LParenLoc,
|
||||||
&Exprs[0], Exprs.size(),
|
Exprs.take(), Exprs.size(),
|
||||||
&CommaLocs[0], RParenLoc);
|
&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
|
// 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.
|
// second form of new-expression. It can't be a new-type-id.
|
||||||
|
|
||||||
ExprListTy PlacementArgs;
|
ExprVector PlacementArgs(Actions);
|
||||||
SourceLocation PlacementLParen, PlacementRParen;
|
SourceLocation PlacementLParen, PlacementRParen;
|
||||||
|
|
||||||
TypeTy *Ty = 0;
|
TypeTy *Ty = 0;
|
||||||
|
@ -706,7 +707,7 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
|
||||||
ParenTypeId = false;
|
ParenTypeId = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprListTy ConstructorArgs;
|
ExprVector ConstructorArgs(Actions);
|
||||||
SourceLocation ConstructorLParen, ConstructorRParen;
|
SourceLocation ConstructorLParen, ConstructorRParen;
|
||||||
|
|
||||||
if (Tok.is(tok::l_paren)) {
|
if (Tok.is(tok::l_paren)) {
|
||||||
|
@ -722,9 +723,9 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
|
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
|
||||||
&PlacementArgs[0], PlacementArgs.size(),
|
PlacementArgs.take(), PlacementArgs.size(),
|
||||||
PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
|
PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
|
||||||
ConstructorLParen, &ConstructorArgs[0],
|
ConstructorLParen, ConstructorArgs.take(),
|
||||||
ConstructorArgs.size(), ConstructorRParen);
|
ConstructorArgs.size(), ConstructorRParen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "clang/Parse/Designator.h"
|
#include "clang/Parse/Designator.h"
|
||||||
#include "clang/Parse/Parser.h"
|
#include "clang/Parse/Parser.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
@ -241,7 +242,7 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
|
||||||
|
|
||||||
/// InitExprs - This is the actual list of expressions contained in the
|
/// InitExprs - This is the actual list of expressions contained in the
|
||||||
/// initializer.
|
/// initializer.
|
||||||
llvm::SmallVector<ExprTy*, 8> InitExprs;
|
ExprVector InitExprs(Actions);
|
||||||
|
|
||||||
/// ExprDesignators - For each initializer, keep track of the designator that
|
/// ExprDesignators - For each initializer, keep track of the designator that
|
||||||
/// was specified for it, if any.
|
/// was specified for it, if any.
|
||||||
|
@ -289,6 +290,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
|
||||||
// parsing the rest of the initializer. This allows us to emit
|
// 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,
|
// 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.
|
// 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)) {
|
if (Tok.isNot(tok::comma)) {
|
||||||
SkipUntil(tok::r_brace, false, true);
|
SkipUntil(tok::r_brace, false, true);
|
||||||
break;
|
break;
|
||||||
|
@ -305,13 +309,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
|
||||||
if (Tok.is(tok::r_brace)) break;
|
if (Tok.is(tok::r_brace)) break;
|
||||||
}
|
}
|
||||||
if (InitExprsOk && Tok.is(tok::r_brace))
|
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());
|
InitExprDesignations, ConsumeBrace());
|
||||||
|
|
||||||
// On error, delete any parsed subexpressions.
|
|
||||||
for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
|
|
||||||
Actions.DeleteExpr(InitExprs[i]);
|
|
||||||
|
|
||||||
// Match the '}'.
|
// Match the '}'.
|
||||||
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
|
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
|
||||||
return ExprResult(true); // an error occurred.
|
return ExprResult(true); // an error occurred.
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "clang/Parse/Parser.h"
|
#include "clang/Parse/Parser.h"
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
#include "clang/Parse/Scope.h"
|
#include "clang/Parse/Scope.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
@ -1194,6 +1195,7 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
|
||||||
}
|
}
|
||||||
ConsumeParen(); // '('
|
ConsumeParen(); // '('
|
||||||
ExprResult Res = ParseExpression();
|
ExprResult Res = ParseExpression();
|
||||||
|
ExprGuard ResGuard(Actions, Res);
|
||||||
if (Res.isInvalid) {
|
if (Res.isInvalid) {
|
||||||
SkipUntil(tok::semi);
|
SkipUntil(tok::semi);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1216,7 +1218,8 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
|
||||||
ExitScope();
|
ExitScope();
|
||||||
if (SynchBody.isInvalid)
|
if (SynchBody.isInvalid)
|
||||||
SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
|
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:
|
/// objc-try-catch-statement:
|
||||||
|
@ -1245,6 +1248,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
||||||
ExitScope();
|
ExitScope();
|
||||||
if (TryBody.isInvalid)
|
if (TryBody.isInvalid)
|
||||||
TryBody = Actions.ActOnNullStmt(Tok.getLocation());
|
TryBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||||
|
ExprGuard TryGuard(Actions, TryBody);
|
||||||
|
ExprGuard CatchGuard(Actions), FinallyGuard(Actions);
|
||||||
|
|
||||||
while (Tok.is(tok::at)) {
|
while (Tok.is(tok::at)) {
|
||||||
// At this point, we need to lookahead to determine if this @ is the start
|
// At this point, we need to lookahead to determine if this @ is the start
|
||||||
|
@ -1290,7 +1295,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
||||||
if (CatchBody.isInvalid)
|
if (CatchBody.isInvalid)
|
||||||
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
|
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||||
CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc,
|
CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc,
|
||||||
FirstPart, CatchBody.Val, CatchStmts.Val);
|
FirstPart, CatchBody.Val, CatchGuard.take());
|
||||||
|
CatchGuard.reset(CatchStmts);
|
||||||
ExitScope();
|
ExitScope();
|
||||||
} else {
|
} else {
|
||||||
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
|
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
|
||||||
|
@ -1313,6 +1319,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
||||||
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
|
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
|
||||||
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
|
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
|
||||||
FinallyBody.Val);
|
FinallyBody.Val);
|
||||||
|
FinallyGuard.reset(FinallyStmt);
|
||||||
catch_or_finally_seen = true;
|
catch_or_finally_seen = true;
|
||||||
ExitScope();
|
ExitScope();
|
||||||
break;
|
break;
|
||||||
|
@ -1322,8 +1329,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
|
||||||
Diag(atLoc, diag::err_missing_catch_finally);
|
Diag(atLoc, diag::err_missing_catch_finally);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.Val, CatchStmts.Val,
|
return Actions.ActOnObjCAtTryStmt(atLoc, TryGuard.take(), CatchGuard.take(),
|
||||||
FinallyStmt.Val);
|
FinallyGuard.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
|
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
|
||||||
|
@ -1468,7 +1475,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
||||||
IdentifierInfo *selIdent = ParseObjCSelector(Loc);
|
IdentifierInfo *selIdent = ParseObjCSelector(Loc);
|
||||||
|
|
||||||
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
|
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
|
||||||
llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
|
ExprVector KeyExprs(Actions);
|
||||||
|
|
||||||
if (Tok.is(tok::colon)) {
|
if (Tok.is(tok::colon)) {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -1551,9 +1558,9 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
|
||||||
return Actions.ActOnClassMessage(CurScope,
|
return Actions.ActOnClassMessage(CurScope,
|
||||||
ReceiverName, Sel,
|
ReceiverName, Sel,
|
||||||
LBracLoc, NameLoc, RBracLoc,
|
LBracLoc, NameLoc, RBracLoc,
|
||||||
&KeyExprs[0], KeyExprs.size());
|
KeyExprs.take(), KeyExprs.size());
|
||||||
return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
|
return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
|
||||||
&KeyExprs[0], KeyExprs.size());
|
KeyExprs.take(), KeyExprs.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
|
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
|
// expressions. At this point, we know that the only valid thing that starts
|
||||||
// with '@' is an @"".
|
// with '@' is an @"".
|
||||||
llvm::SmallVector<SourceLocation, 4> AtLocs;
|
llvm::SmallVector<SourceLocation, 4> AtLocs;
|
||||||
llvm::SmallVector<ExprTy*, 4> AtStrings;
|
ExprVector AtStrings(Actions);
|
||||||
AtLocs.push_back(AtLoc);
|
AtLocs.push_back(AtLoc);
|
||||||
AtStrings.push_back(Res.Val);
|
AtStrings.push_back(Res.Val);
|
||||||
|
|
||||||
while (Tok.is(tok::at)) {
|
while (Tok.is(tok::at)) {
|
||||||
AtLocs.push_back(ConsumeToken()); // eat the @.
|
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())
|
if (isTokenStringLiteral())
|
||||||
Res = ParseStringLiteralExpression();
|
Lit = ParseStringLiteralExpression();
|
||||||
else
|
else
|
||||||
Diag(Tok, diag::err_objc_concat_string);
|
Diag(Tok, diag::err_objc_concat_string);
|
||||||
|
|
||||||
if (Res.isInvalid) {
|
if (Lit.isInvalid)
|
||||||
while (!AtStrings.empty()) {
|
return Lit;
|
||||||
Actions.DeleteExpr(AtStrings.back());
|
|
||||||
AtStrings.pop_back();
|
|
||||||
}
|
|
||||||
return Res;
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
AtStrings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1614,7 +1616,6 @@ Parser::ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
|
||||||
|
|
||||||
/// objc-protocol-expression
|
/// objc-protocol-expression
|
||||||
/// @protocol ( protocol-name )
|
/// @protocol ( protocol-name )
|
||||||
|
|
||||||
Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
|
Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
|
||||||
SourceLocation ProtoLoc = ConsumeToken();
|
SourceLocation ProtoLoc = ConsumeToken();
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "ParsePragma.h"
|
#include "ParsePragma.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/Parse/Action.h"
|
#include "clang/Parse/Action.h"
|
||||||
|
@ -35,12 +36,14 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
||||||
Action::PragmaPackKind Kind = Action::PPK_Default;
|
Action::PragmaPackKind Kind = Action::PPK_Default;
|
||||||
IdentifierInfo *Name = 0;
|
IdentifierInfo *Name = 0;
|
||||||
Action::ExprResult Alignment;
|
Action::ExprResult Alignment;
|
||||||
|
ExprGuard AlignmentGuard(Actions);
|
||||||
SourceLocation LParenLoc = Tok.getLocation();
|
SourceLocation LParenLoc = Tok.getLocation();
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
if (Tok.is(tok::numeric_constant)) {
|
if (Tok.is(tok::numeric_constant)) {
|
||||||
Alignment = Actions.ActOnNumericConstant(Tok);
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||||
if (Alignment.isInvalid)
|
if (Alignment.isInvalid)
|
||||||
return;
|
return;
|
||||||
|
AlignmentGuard.reset(Alignment);
|
||||||
|
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
} else if (Tok.is(tok::identifier)) {
|
} else if (Tok.is(tok::identifier)) {
|
||||||
|
@ -66,6 +69,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
||||||
Alignment = Actions.ActOnNumericConstant(Tok);
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||||
if (Alignment.isInvalid)
|
if (Alignment.isInvalid)
|
||||||
return;
|
return;
|
||||||
|
AlignmentGuard.reset(Alignment);
|
||||||
|
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
} else if (Tok.is(tok::identifier)) {
|
} else if (Tok.is(tok::identifier)) {
|
||||||
|
@ -83,6 +87,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
||||||
Alignment = Actions.ActOnNumericConstant(Tok);
|
Alignment = Actions.ActOnNumericConstant(Tok);
|
||||||
if (Alignment.isInvalid)
|
if (Alignment.isInvalid)
|
||||||
return;
|
return;
|
||||||
|
AlignmentGuard.reset(Alignment);
|
||||||
|
|
||||||
PP.Lex(Tok);
|
PP.Lex(Tok);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +105,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceLocation RParenLoc = Tok.getLocation();
|
SourceLocation RParenLoc = Tok.getLocation();
|
||||||
Actions.ActOnPragmaPack(Kind, Name, Alignment.Val, PackLoc,
|
Actions.ActOnPragmaPack(Kind, Name, AlignmentGuard.take(), PackLoc,
|
||||||
LParenLoc, RParenLoc);
|
LParenLoc, RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "clang/Parse/Parser.h"
|
#include "clang/Parse/Parser.h"
|
||||||
#include "ExtensionRAIIObject.h"
|
#include "ExtensionRAIIObject.h"
|
||||||
|
#include "AstGuard.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Parse/DeclSpec.h"
|
#include "clang/Parse/DeclSpec.h"
|
||||||
|
@ -229,6 +230,7 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
||||||
SkipUntil(tok::colon);
|
SkipUntil(tok::colon);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
ExprGuard LHSGuard(Actions, LHS);
|
||||||
|
|
||||||
// GNU case range extension.
|
// GNU case range extension.
|
||||||
SourceLocation DotDotDotLoc;
|
SourceLocation DotDotDotLoc;
|
||||||
|
@ -244,6 +246,7 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
||||||
}
|
}
|
||||||
RHSVal = RHS.Val;
|
RHSVal = RHS.Val;
|
||||||
}
|
}
|
||||||
|
ExprGuard RHSGuard(Actions, RHSVal);
|
||||||
|
|
||||||
if (Tok.isNot(tok::colon)) {
|
if (Tok.isNot(tok::colon)) {
|
||||||
Diag(Tok, diag::err_expected_colon_after) << "'case'";
|
Diag(Tok, diag::err_expected_colon_after) << "'case'";
|
||||||
|
@ -265,8 +268,8 @@ Parser::StmtResult Parser::ParseCaseStatement() {
|
||||||
if (SubStmt.isInvalid)
|
if (SubStmt.isInvalid)
|
||||||
SubStmt = Actions.ActOnNullStmt(ColonLoc);
|
SubStmt = Actions.ActOnNullStmt(ColonLoc);
|
||||||
|
|
||||||
return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
|
return Actions.ActOnCaseStmt(CaseLoc, LHSGuard.take(), DotDotDotLoc,
|
||||||
SubStmt.Val);
|
RHSGuard.take(), ColonLoc, SubStmt.Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseDefaultStatement
|
/// ParseDefaultStatement
|
||||||
|
@ -352,7 +355,8 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
||||||
// TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
|
// 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.
|
// 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)) {
|
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
|
||||||
StmtResult R;
|
StmtResult R;
|
||||||
if (Tok.isNot(tok::kw___extension__)) {
|
if (Tok.isNot(tok::kw___extension__)) {
|
||||||
|
@ -410,7 +414,7 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
||||||
|
|
||||||
SourceLocation RBraceLoc = ConsumeBrace();
|
SourceLocation RBraceLoc = ConsumeBrace();
|
||||||
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
|
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
|
||||||
&Stmts[0], Stmts.size(), isStmtExpr);
|
Stmts.take(), Stmts.size(), isStmtExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseIfStatement
|
/// ParseIfStatement
|
||||||
|
@ -456,6 +460,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
||||||
} else {
|
} else {
|
||||||
CondExp = ParseSimpleParenExpression();
|
CondExp = ParseSimpleParenExpression();
|
||||||
}
|
}
|
||||||
|
ExprGuard CondGuard(Actions, CondExp);
|
||||||
|
|
||||||
if (CondExp.isInvalid) {
|
if (CondExp.isInvalid) {
|
||||||
SkipUntil(tok::semi);
|
SkipUntil(tok::semi);
|
||||||
|
@ -528,9 +533,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
||||||
if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
|
if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
|
||||||
(ThenStmt.isInvalid && ElseStmt.Val == 0) ||
|
(ThenStmt.isInvalid && ElseStmt.Val == 0) ||
|
||||||
(ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
|
(ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
|
||||||
// Both invalid, or one is invalid and other is non-present: delete cond and
|
// Both invalid, or one is invalid and other is non-present: return error.
|
||||||
// return error.
|
|
||||||
Actions.DeleteExpr(CondExp.Val);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +543,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
|
||||||
if (ElseStmt.isInvalid)
|
if (ElseStmt.isInvalid)
|
||||||
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
|
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
|
||||||
|
|
||||||
return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
|
return Actions.ActOnIfStmt(IfLoc, CondGuard.take(), ThenStmt.Val,
|
||||||
ElseLoc, ElseStmt.Val);
|
ElseLoc, ElseStmt.Val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -668,6 +671,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
|
||||||
} else {
|
} else {
|
||||||
Cond = ParseSimpleParenExpression();
|
Cond = ParseSimpleParenExpression();
|
||||||
}
|
}
|
||||||
|
ExprGuard CondGuard(Actions, Cond);
|
||||||
|
|
||||||
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
|
// 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
|
// 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.
|
// Read the body statement.
|
||||||
StmtResult Body = ParseStatement();
|
StmtResult Body = ParseStatement();
|
||||||
|
StmtGuard BodyGuard(Actions, Body);
|
||||||
|
|
||||||
// Pop the body scope if needed.
|
// Pop the body scope if needed.
|
||||||
if (NeedsInnerScope) ExitScope();
|
if (NeedsInnerScope) ExitScope();
|
||||||
|
@ -693,7 +698,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
|
||||||
|
|
||||||
if (Cond.isInvalid || Body.isInvalid) return true;
|
if (Cond.isInvalid || Body.isInvalid) return true;
|
||||||
|
|
||||||
return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
|
return Actions.ActOnWhileStmt(WhileLoc, CondGuard.take(), BodyGuard.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseDoStatement
|
/// ParseDoStatement
|
||||||
|
@ -725,6 +730,7 @@ Parser::StmtResult Parser::ParseDoStatement() {
|
||||||
|
|
||||||
// Read the body statement.
|
// Read the body statement.
|
||||||
StmtResult Body = ParseStatement();
|
StmtResult Body = ParseStatement();
|
||||||
|
StmtGuard BodyGuard(Actions, Body);
|
||||||
|
|
||||||
// Pop the body scope if needed.
|
// Pop the body scope if needed.
|
||||||
if (NeedsInnerScope) ExitScope();
|
if (NeedsInnerScope) ExitScope();
|
||||||
|
@ -749,12 +755,14 @@ Parser::StmtResult Parser::ParseDoStatement() {
|
||||||
|
|
||||||
// Parse the condition.
|
// Parse the condition.
|
||||||
ExprResult Cond = ParseSimpleParenExpression();
|
ExprResult Cond = ParseSimpleParenExpression();
|
||||||
|
ExprGuard CondGuard(Actions, Cond);
|
||||||
|
|
||||||
ExitScope();
|
ExitScope();
|
||||||
|
|
||||||
if (Cond.isInvalid || Body.isInvalid) return true;
|
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
|
/// ParseForStatement
|
||||||
|
@ -810,6 +818,8 @@ Parser::StmtResult Parser::ParseForStatement() {
|
||||||
ExprTy *SecondPart = 0;
|
ExprTy *SecondPart = 0;
|
||||||
StmtTy *ThirdPart = 0;
|
StmtTy *ThirdPart = 0;
|
||||||
bool ForEach = false;
|
bool ForEach = false;
|
||||||
|
StmtGuard FirstGuard(Actions), ThirdGuard(Actions);
|
||||||
|
ExprGuard SecondGuard(Actions);
|
||||||
|
|
||||||
// Parse the first part of the for specifier.
|
// Parse the first part of the for specifier.
|
||||||
if (Tok.is(tok::semi)) { // for (;
|
if (Tok.is(tok::semi)) { // for (;
|
||||||
|
@ -856,7 +866,10 @@ Parser::StmtResult Parser::ParseForStatement() {
|
||||||
SkipUntil(tok::semi);
|
SkipUntil(tok::semi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FirstGuard.reset(FirstPart);
|
||||||
|
SecondGuard.reset(SecondPart);
|
||||||
if (!ForEach) {
|
if (!ForEach) {
|
||||||
|
assert(!SecondGuard.get() && "Shouldn't have a second expression yet.");
|
||||||
// Parse the second part of the for specifier.
|
// Parse the second part of the for specifier.
|
||||||
if (Tok.is(tok::semi)) { // for (...;;
|
if (Tok.is(tok::semi)) { // for (...;;
|
||||||
// no second part.
|
// no second part.
|
||||||
|
@ -888,6 +901,8 @@ Parser::StmtResult Parser::ParseForStatement() {
|
||||||
ThirdPart = R.Val;
|
ThirdPart = R.Val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SecondGuard.reset(SecondPart);
|
||||||
|
ThirdGuard.reset(ThirdPart);
|
||||||
}
|
}
|
||||||
// Match the ')'.
|
// Match the ')'.
|
||||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
@ -918,6 +933,10 @@ Parser::StmtResult Parser::ParseForStatement() {
|
||||||
if (Body.isInvalid)
|
if (Body.isInvalid)
|
||||||
return Body;
|
return Body;
|
||||||
|
|
||||||
|
// Release all the guards.
|
||||||
|
FirstGuard.take();
|
||||||
|
SecondGuard.take();
|
||||||
|
ThirdGuard.take();
|
||||||
if (!ForEach)
|
if (!ForEach)
|
||||||
return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart,
|
return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart,
|
||||||
SecondPart, ThirdPart, RParenLoc, Body.Val);
|
SecondPart, ThirdPart, RParenLoc, Body.Val);
|
||||||
|
@ -1082,11 +1101,12 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
||||||
ExprResult AsmString = ParseAsmStringLiteral();
|
ExprResult AsmString = ParseAsmStringLiteral();
|
||||||
if (AsmString.isInvalid)
|
if (AsmString.isInvalid)
|
||||||
return true;
|
return true;
|
||||||
|
ExprGuard AsmGuard(Actions, AsmString);
|
||||||
|
|
||||||
llvm::SmallVector<std::string, 4> Names;
|
llvm::SmallVector<std::string, 4> Names;
|
||||||
llvm::SmallVector<ExprTy*, 4> Constraints;
|
ExprVector Constraints(Actions);
|
||||||
llvm::SmallVector<ExprTy*, 4> Exprs;
|
ExprVector Exprs(Actions);
|
||||||
llvm::SmallVector<ExprTy*, 4> Clobbers;
|
ExprVector Clobbers(Actions);
|
||||||
|
|
||||||
unsigned NumInputs = 0, NumOutputs = 0;
|
unsigned NumInputs = 0, NumOutputs = 0;
|
||||||
|
|
||||||
|
@ -1136,9 +1156,9 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
|
||||||
|
|
||||||
return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
|
return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
|
||||||
NumOutputs, NumInputs,
|
NumOutputs, NumInputs,
|
||||||
&Names[0], &Constraints[0], &Exprs[0],
|
&Names[0], Constraints.take(),
|
||||||
AsmString.Val,
|
Exprs.take(), AsmGuard.take(),
|
||||||
Clobbers.size(), &Clobbers[0],
|
Clobbers.size(), Clobbers.take(),
|
||||||
RParenLoc);
|
RParenLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue