зеркало из https://github.com/microsoft/clang-1.git
This patch continues parser-level implementation of designators:
1. It introduces new parser level abstractions for designators that are used to communicate between parser and sema. 2. This fixes a FIXME where "identifier ':'" was considered to be a designator even if it wasn't the first in a designator list. 3. In the "identifier ':'" case, it actually builds the designator representation. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58205 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
838cb21b80
Коммит
eccc53a0a0
|
@ -441,6 +441,7 @@
|
||||||
DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentifierTable.cpp; sourceTree = "<group>"; };
|
DE3986F30CB8D50C00223765 /* IdentifierTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IdentifierTable.cpp; sourceTree = "<group>"; };
|
||||||
DE3B90DE0EAC5EF200D01046 /* ExtensionRAIIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtensionRAIIObject.h; path = lib/Parse/ExtensionRAIIObject.h; sourceTree = "<group>"; };
|
DE3B90DE0EAC5EF200D01046 /* ExtensionRAIIObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExtensionRAIIObject.h; path = lib/Parse/ExtensionRAIIObject.h; sourceTree = "<group>"; };
|
||||||
DE3B921C0EB1A81400D01046 /* SemaInherit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInherit.h; path = lib/Sema/SemaInherit.h; sourceTree = "<group>"; };
|
DE3B921C0EB1A81400D01046 /* SemaInherit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaInherit.h; path = lib/Sema/SemaInherit.h; sourceTree = "<group>"; };
|
||||||
|
DE3B92230EB5152000D01046 /* Designator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Designator.h; path = clang/Parse/Designator.h; sourceTree = "<group>"; };
|
||||||
DE41211D0D7F1BBE0080F80A /* GRWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRWorkList.h; path = clang/Analysis/PathSensitive/GRWorkList.h; sourceTree = "<group>"; };
|
DE41211D0D7F1BBE0080F80A /* GRWorkList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRWorkList.h; path = clang/Analysis/PathSensitive/GRWorkList.h; sourceTree = "<group>"; };
|
||||||
DE41211E0D7F1BBE0080F80A /* SymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolManager.h; path = clang/Analysis/PathSensitive/SymbolManager.h; sourceTree = "<group>"; };
|
DE41211E0D7F1BBE0080F80A /* SymbolManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolManager.h; path = clang/Analysis/PathSensitive/SymbolManager.h; sourceTree = "<group>"; };
|
||||||
DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRBlockCounter.h; path = clang/Analysis/PathSensitive/GRBlockCounter.h; sourceTree = "<group>"; };
|
DE41211F0D7F1BBE0080F80A /* GRBlockCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GRBlockCounter.h; path = clang/Analysis/PathSensitive/GRBlockCounter.h; sourceTree = "<group>"; };
|
||||||
|
@ -764,6 +765,7 @@
|
||||||
84D9A88B0C1A581300AC7ABC /* AttributeList.h */,
|
84D9A88B0C1A581300AC7ABC /* AttributeList.h */,
|
||||||
DE06E8130A8FF9330050E87E /* Action.h */,
|
DE06E8130A8FF9330050E87E /* Action.h */,
|
||||||
DE17336F0B068DC60080B521 /* DeclSpec.h */,
|
DE17336F0B068DC60080B521 /* DeclSpec.h */,
|
||||||
|
DE3B92230EB5152000D01046 /* Designator.h */,
|
||||||
DE1F22020A7D852A00FBF588 /* Parser.h */,
|
DE1F22020A7D852A00FBF588 /* Parser.h */,
|
||||||
DE06BECA0A854E4B0050E87E /* Scope.h */,
|
DE06BECA0A854E4B0050E87E /* Scope.h */,
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace clang {
|
||||||
class Scope;
|
class Scope;
|
||||||
class Action;
|
class Action;
|
||||||
class Selector;
|
class Selector;
|
||||||
|
class InitListDesignations;
|
||||||
// Lex.
|
// Lex.
|
||||||
class Token;
|
class Token;
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LLVM_CLANG_PARSE_SEMADECLSPEC_H
|
#ifndef LLVM_CLANG_PARSE_DECLSPEC_H
|
||||||
#define LLVM_CLANG_PARSE_SEMADECLSPEC_H
|
#define LLVM_CLANG_PARSE_DECLSPEC_H
|
||||||
|
|
||||||
#include "clang/Parse/Action.h"
|
#include "clang/Parse/Action.h"
|
||||||
#include "clang/Parse/AttributeList.h"
|
#include "clang/Parse/AttributeList.h"
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
//===--- Designator.h - Initialization Designator ---------------*- 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 interfaces used to represent Designators in the parser and
|
||||||
|
// is the input to Actions module.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H
|
||||||
|
#define LLVM_CLANG_PARSE_DESIGNATOR_H
|
||||||
|
|
||||||
|
#include "clang/Parse/Action.h"
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
|
||||||
|
/// Designator - This class is a discriminated union which holds the various
|
||||||
|
/// different sorts of designators possible. A Designation is an array of
|
||||||
|
/// these. An example of a designator are things like this:
|
||||||
|
/// [8] .field [47] // C99 designation: 3 designators
|
||||||
|
/// [8 ... 47] field: // GNU extensions: 2 designators
|
||||||
|
/// These occur in initializers, e.g.:
|
||||||
|
/// int a[10] = {2, 4, [8]=9, 10};
|
||||||
|
///
|
||||||
|
class Designator {
|
||||||
|
public:
|
||||||
|
enum DesignatorKind {
|
||||||
|
FieldDesignator, ArrayDesignator, ArrayRangeDesignator
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
DesignatorKind Kind;
|
||||||
|
|
||||||
|
struct FieldDesignatorInfo {
|
||||||
|
const IdentifierInfo *II;
|
||||||
|
};
|
||||||
|
struct ArrayDesignatorInfo {
|
||||||
|
Action::ExprTy *Index;
|
||||||
|
};
|
||||||
|
struct ArrayRangeDesignatorInfo {
|
||||||
|
Action::ExprTy *Start, *End;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
FieldDesignatorInfo FieldInfo;
|
||||||
|
ArrayDesignatorInfo ArrayInfo;
|
||||||
|
ArrayRangeDesignatorInfo ArrayRangeInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DesignatorKind getKind() const { return Kind; }
|
||||||
|
bool isFieldDesignator() const { return Kind == FieldDesignator; }
|
||||||
|
bool isArrayDesignator() const { return Kind == ArrayDesignator; }
|
||||||
|
bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; }
|
||||||
|
|
||||||
|
const IdentifierInfo *getField() const {
|
||||||
|
assert(isFieldDesignator() && "Invalid accessor");
|
||||||
|
return FieldInfo.II;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ExprTy *getArrayIndex() const {
|
||||||
|
assert(isArrayDesignator() && "Invalid accessor");
|
||||||
|
return ArrayInfo.Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::ExprTy *getArrayRangeStart() const {
|
||||||
|
assert(isArrayRangeDesignator() && "Invalid accessor");
|
||||||
|
return ArrayRangeInfo.Start;
|
||||||
|
}
|
||||||
|
Action::ExprTy *getArrayRangeEnd() const {
|
||||||
|
assert(isArrayRangeDesignator() && "Invalid accessor");
|
||||||
|
return ArrayRangeInfo.End;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Designator getField(const IdentifierInfo *II) {
|
||||||
|
Designator D;
|
||||||
|
D.Kind = FieldDesignator;
|
||||||
|
D.FieldInfo.II = II;
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Designator getArray(Action::ExprTy *Index) {
|
||||||
|
Designator D;
|
||||||
|
D.Kind = ArrayDesignator;
|
||||||
|
D.ArrayInfo.Index = Index;
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Designator getArrayRange(Action::ExprTy *Start, Action::ExprTy *End) {
|
||||||
|
Designator D;
|
||||||
|
D.Kind = ArrayRangeDesignator;
|
||||||
|
D.ArrayRangeInfo.Start = Start;
|
||||||
|
D.ArrayRangeInfo.End = End;
|
||||||
|
return D;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ClearExprs - Null out any expression references, which prevents them from
|
||||||
|
/// being 'delete'd later.
|
||||||
|
void ClearExprs(Action &Actions) {
|
||||||
|
switch (Kind) {
|
||||||
|
case FieldDesignator: return;
|
||||||
|
case ArrayDesignator:
|
||||||
|
ArrayInfo.Index = 0;
|
||||||
|
return;
|
||||||
|
case ArrayRangeDesignator:
|
||||||
|
ArrayRangeInfo.Start = 0;
|
||||||
|
ArrayRangeInfo.End = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FreeExprs - Release any unclaimed memory for the expressions in this
|
||||||
|
/// designator.
|
||||||
|
void FreeExprs(Action &Actions) {
|
||||||
|
switch (Kind) {
|
||||||
|
case FieldDesignator: return; // nothing to free.
|
||||||
|
case ArrayDesignator:
|
||||||
|
Actions.DeleteExpr(getArrayIndex());
|
||||||
|
return;
|
||||||
|
case ArrayRangeDesignator:
|
||||||
|
Actions.DeleteExpr(getArrayRangeStart());
|
||||||
|
Actions.DeleteExpr(getArrayRangeEnd());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Designation - Represent a full designation, which is a sequence of
|
||||||
|
/// designators. This class is mostly a helper for InitListDesignations.
|
||||||
|
class Designation {
|
||||||
|
friend class InitListDesignations;
|
||||||
|
|
||||||
|
/// InitIndex - The index of the initializer expression this is for. For
|
||||||
|
/// example, if the initializer were "{ A, .foo=B, C }" a Designation would
|
||||||
|
/// exist with InitIndex=1, because element #1 has a designation.
|
||||||
|
unsigned InitIndex;
|
||||||
|
|
||||||
|
/// Designators - The actual designators for this initializer.
|
||||||
|
llvm::SmallVector<Designator, 2> Designators;
|
||||||
|
|
||||||
|
Designation(unsigned Idx) : InitIndex(Idx) {}
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// AddDesignator - Add a designator to the end of this list.
|
||||||
|
void AddDesignator(Designator D) {
|
||||||
|
Designators.push_back(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ClearExprs - Null out any expression references, which prevents them from
|
||||||
|
/// being 'delete'd later.
|
||||||
|
void ClearExprs(Action &Actions) {
|
||||||
|
for (unsigned i = 0, e = Designators.size(); i != e; ++i)
|
||||||
|
Designators[i].ClearExprs(Actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FreeExprs - Release any unclaimed memory for the expressions in this
|
||||||
|
/// designation.
|
||||||
|
void FreeExprs(Action &Actions) {
|
||||||
|
for (unsigned i = 0, e = Designators.size(); i != e; ++i)
|
||||||
|
Designators[i].FreeExprs(Actions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// InitListDesignations - This contains all the designators for an
|
||||||
|
/// initializer list. This is somewhat like a two dimensional array of
|
||||||
|
/// Designators, but is optimized for the cases when designators are not
|
||||||
|
/// present.
|
||||||
|
class InitListDesignations {
|
||||||
|
Action &Actions;
|
||||||
|
|
||||||
|
/// Designations - All of the designators in this init list. These are kept
|
||||||
|
/// in order sorted by their InitIndex.
|
||||||
|
llvm::SmallVector<Designation, 3> Designations;
|
||||||
|
|
||||||
|
InitListDesignations(const InitListDesignations&); // DO NOT IMPLEMENT
|
||||||
|
void operator=(const InitListDesignations&); // DO NOT IMPLEMENT
|
||||||
|
public:
|
||||||
|
InitListDesignations(Action &A) : Actions(A) {}
|
||||||
|
|
||||||
|
~InitListDesignations() {
|
||||||
|
// Release any unclaimed memory for the expressions in this init list.
|
||||||
|
for (unsigned i = 0, e = Designations.size(); i != e; ++i)
|
||||||
|
Designations[i].FreeExprs(Actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAnyDesignators() const {
|
||||||
|
return Designations.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
Designation &CreateDesignation(unsigned Idx) {
|
||||||
|
assert((Designations.empty() || Designations.back().InitIndex < Idx) &&
|
||||||
|
"not sorted by InitIndex!");
|
||||||
|
Designations.push_back(Designation(Idx));
|
||||||
|
return Designations.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace clang
|
||||||
|
|
||||||
|
#endif
|
|
@ -480,7 +480,8 @@ private:
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// C99 6.7.8: Initialization.
|
// C99 6.7.8: Initialization.
|
||||||
ExprResult ParseInitializer();
|
ExprResult ParseInitializer();
|
||||||
ExprResult ParseInitializerWithPotentialDesignator();
|
ExprResult ParseInitializerWithPotentialDesignator(InitListDesignations &D,
|
||||||
|
unsigned InitNum);
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// clang Expressions
|
// clang Expressions
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "clang/Parse/Designator.h"
|
||||||
#include "clang/Parse/Parser.h"
|
#include "clang/Parse/Parser.h"
|
||||||
#include "clang/Basic/Diagnostic.h"
|
#include "clang/Basic/Diagnostic.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
|
@ -54,7 +55,32 @@ static bool MayBeDesignationStart(tok::TokenKind K) {
|
||||||
/// initializer (because it is an expression). We need to consider this case
|
/// initializer (because it is an expression). We need to consider this case
|
||||||
/// when parsing array designators.
|
/// when parsing array designators.
|
||||||
///
|
///
|
||||||
Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
|
Parser::ExprResult Parser::
|
||||||
|
ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
|
||||||
|
unsigned InitNum) {
|
||||||
|
|
||||||
|
// If this is the old-style GNU extension:
|
||||||
|
// designation ::= identifier ':'
|
||||||
|
// Handle it as a field designator. Otherwise, this must be the start of a
|
||||||
|
// normal expression.
|
||||||
|
if (Tok.is(tok::identifier)) {
|
||||||
|
if (NextToken().is(tok::colon)) {
|
||||||
|
Diag(Tok, diag::ext_gnu_old_style_field_designator);
|
||||||
|
|
||||||
|
Designation &D = Designations.CreateDesignation(InitNum);
|
||||||
|
D.AddDesignator(Designator::getField(Tok.getIdentifierInfo()));
|
||||||
|
ConsumeToken(); // Eat the identifier.
|
||||||
|
|
||||||
|
assert(Tok.is(tok::colon) && "NextToken() not working properly!");
|
||||||
|
ConsumeToken();
|
||||||
|
return ParseInitializer();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, parse the assignment-expression.
|
||||||
|
return ParseAssignmentExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Parse each designator in the designator list until we find an initializer.
|
// Parse each designator in the designator list until we find an initializer.
|
||||||
while (1) {
|
while (1) {
|
||||||
switch (Tok.getKind()) {
|
switch (Tok.getKind()) {
|
||||||
|
@ -138,25 +164,6 @@ Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
|
||||||
MatchRHSPunctuation(tok::r_square, StartLoc);
|
MatchRHSPunctuation(tok::r_square, StartLoc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::identifier: {
|
|
||||||
// Due to the GNU "designation: identifier ':'" extension, we don't know
|
|
||||||
// whether something starting with an identifier is an
|
|
||||||
// assignment-expression or if it is an old-style structure field
|
|
||||||
// designator.
|
|
||||||
// TODO: Check that this is the first designator.
|
|
||||||
|
|
||||||
// If this is the gross GNU extension, handle it now.
|
|
||||||
if (NextToken().is(tok::colon)) {
|
|
||||||
Diag(Tok, diag::ext_gnu_old_style_field_designator);
|
|
||||||
ConsumeToken(); // The identifier.
|
|
||||||
assert(Tok.is(tok::colon) && "NextToken() not working properly!");
|
|
||||||
ConsumeToken();
|
|
||||||
return ParseInitializer();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, parse the assignment-expression.
|
|
||||||
return ParseAssignmentExpression();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,6 +181,8 @@ Parser::ExprResult Parser::ParseInitializerWithPotentialDesignator() {
|
||||||
/// initializer-list ',' designation[opt] initializer
|
/// initializer-list ',' designation[opt] initializer
|
||||||
///
|
///
|
||||||
Parser::ExprResult Parser::ParseInitializer() {
|
Parser::ExprResult Parser::ParseInitializer() {
|
||||||
|
// TODO: Split this up into ParseInitializer + ParseBraceInitializer, make
|
||||||
|
// ParseInitializer inline so that the non-brace case is short-cut.
|
||||||
if (Tok.isNot(tok::l_brace))
|
if (Tok.isNot(tok::l_brace))
|
||||||
return ParseAssignmentExpression();
|
return ParseAssignmentExpression();
|
||||||
|
|
||||||
|
@ -186,7 +195,15 @@ Parser::ExprResult Parser::ParseInitializer() {
|
||||||
// Match the '}'.
|
// Match the '}'.
|
||||||
return Actions.ActOnInitList(LBraceLoc, 0, 0, ConsumeBrace());
|
return Actions.ActOnInitList(LBraceLoc, 0, 0, ConsumeBrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// InitExprs - This is the actual list of expressions contained in the
|
||||||
|
/// initializer.
|
||||||
llvm::SmallVector<ExprTy*, 8> InitExprs;
|
llvm::SmallVector<ExprTy*, 8> InitExprs;
|
||||||
|
|
||||||
|
/// ExprDesignators - For each initializer, keep track of the designator that
|
||||||
|
/// was specified for it, if any.
|
||||||
|
InitListDesignations InitExprDesignations(Actions);
|
||||||
|
|
||||||
bool InitExprsOk = true;
|
bool InitExprsOk = true;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -198,7 +215,8 @@ Parser::ExprResult Parser::ParseInitializer() {
|
||||||
if (!MayBeDesignationStart(Tok.getKind()))
|
if (!MayBeDesignationStart(Tok.getKind()))
|
||||||
SubElt = ParseInitializer();
|
SubElt = ParseInitializer();
|
||||||
else
|
else
|
||||||
SubElt = ParseInitializerWithPotentialDesignator();
|
SubElt = ParseInitializerWithPotentialDesignator(InitExprDesignations,
|
||||||
|
InitExprs.size());
|
||||||
|
|
||||||
// If we couldn't parse the subelement, bail out.
|
// If we couldn't parse the subelement, bail out.
|
||||||
if (!SubElt.isInvalid) {
|
if (!SubElt.isInvalid) {
|
||||||
|
@ -220,7 +238,7 @@ Parser::ExprResult Parser::ParseInitializer() {
|
||||||
// If we don't have a comma continued list, we're done.
|
// If we don't have a comma continued list, we're done.
|
||||||
if (Tok.isNot(tok::comma)) break;
|
if (Tok.isNot(tok::comma)) break;
|
||||||
|
|
||||||
// FIXME: save comma locations.
|
// TODO: save comma locations if some client cares.
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
||||||
// Handle trailing comma.
|
// Handle trailing comma.
|
||||||
|
@ -230,7 +248,7 @@ Parser::ExprResult Parser::ParseInitializer() {
|
||||||
return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(),
|
return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(),
|
||||||
ConsumeBrace());
|
ConsumeBrace());
|
||||||
|
|
||||||
// Delete any parsed subexpressions.
|
// On error, delete any parsed subexpressions.
|
||||||
for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
|
for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
|
||||||
Actions.DeleteExpr(InitExprs[i]);
|
Actions.DeleteExpr(InitExprs[i]);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче