forked from OSchip/llvm-project
Have the parser communicate the exception specification to the action.
llvm-svn: 70389
This commit is contained in:
parent
99fe1695c7
commit
2b9cacbffa
|
@ -512,31 +512,45 @@ struct DeclaratorChunk {
|
|||
/// argument. If the function is () or (a,b,c), then it has no prototype,
|
||||
/// and is treated as a K&R-style function.
|
||||
bool hasPrototype : 1;
|
||||
|
||||
|
||||
/// isVariadic - If this function has a prototype, and if that
|
||||
/// proto ends with ',...)', this is true. When true, EllipsisLoc
|
||||
/// contains the location of the ellipsis.
|
||||
bool isVariadic : 1;
|
||||
|
||||
/// When isVariadic is true, the location of the ellipsis in the source.
|
||||
unsigned EllipsisLoc;
|
||||
|
||||
/// The type qualifiers: const/volatile/restrict.
|
||||
/// The qualifier bitmask values are the same as in QualType.
|
||||
unsigned TypeQuals : 3;
|
||||
|
||||
/// hasExceptionSpec - True if the function has an exception specification.
|
||||
bool hasExceptionSpec : 1;
|
||||
|
||||
/// hasAnyExceptionSpec - True if the function has a throw(...) specifier.
|
||||
bool hasAnyExceptionSpec : 1;
|
||||
|
||||
/// DeleteArgInfo - If this is true, we need to delete[] ArgInfo.
|
||||
bool DeleteArgInfo : 1;
|
||||
|
||||
/// When isVariadic is true, the location of the ellipsis in the source.
|
||||
unsigned EllipsisLoc;
|
||||
|
||||
/// NumArgs - This is the number of formal arguments provided for the
|
||||
/// declarator.
|
||||
unsigned NumArgs;
|
||||
|
||||
/// NumExceptions - This is the number of types in the exception-decl, if
|
||||
/// the function has one.
|
||||
unsigned NumExceptions;
|
||||
|
||||
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
|
||||
/// describe the arguments for this function declarator. This is null if
|
||||
/// there are no arguments specified.
|
||||
ParamInfo *ArgInfo;
|
||||
|
||||
|
||||
/// Exceptions - This is a pointer to a new[]'d array of TypeTy pointers
|
||||
/// that contains the types in the function's exception specification.
|
||||
ActionBase::TypeTy **Exceptions;
|
||||
|
||||
/// freeArgs - reset the argument list to having zero arguments. This is
|
||||
/// used in various places for error recovery.
|
||||
void freeArgs() {
|
||||
|
@ -546,10 +560,11 @@ struct DeclaratorChunk {
|
|||
}
|
||||
NumArgs = 0;
|
||||
}
|
||||
|
||||
|
||||
void destroy() {
|
||||
if (DeleteArgInfo)
|
||||
delete[] ArgInfo;
|
||||
delete[] Exceptions;
|
||||
}
|
||||
|
||||
SourceLocation getEllipsisLoc() const {
|
||||
|
@ -670,7 +685,10 @@ struct DeclaratorChunk {
|
|||
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
|
||||
SourceLocation EllipsisLoc,
|
||||
ParamInfo *ArgInfo, unsigned NumArgs,
|
||||
unsigned TypeQuals, SourceLocation Loc,
|
||||
unsigned TypeQuals, bool hasExceptionSpec,
|
||||
bool hasAnyExceptionSpec,
|
||||
ActionBase::TypeTy **Exceptions,
|
||||
unsigned NumExceptions, SourceLocation Loc,
|
||||
Declarator &TheDeclarator);
|
||||
|
||||
/// getBlockPointer - Return a DeclaratorChunk for a block.
|
||||
|
|
|
@ -682,7 +682,9 @@ private:
|
|||
// C++ 15: C++ Throw Expression
|
||||
OwningExprResult ParseThrowExpression();
|
||||
// EndLoc is filled with the location of the last token of the specification.
|
||||
bool ParseExceptionSpecification(SourceLocation &EndLoc);
|
||||
bool ParseExceptionSpecification(SourceLocation &EndLoc,
|
||||
std::vector<TypeTy*> &Exceptions,
|
||||
bool &hasAnyExceptionSpec);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 2.13.5: C++ Boolean Literals
|
||||
|
|
|
@ -32,19 +32,27 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
|
|||
ParamInfo *ArgInfo,
|
||||
unsigned NumArgs,
|
||||
unsigned TypeQuals,
|
||||
bool hasExceptionSpec,
|
||||
bool hasAnyExceptionSpec,
|
||||
ActionBase::TypeTy **Exceptions,
|
||||
unsigned NumExceptions,
|
||||
SourceLocation Loc,
|
||||
Declarator &TheDeclarator) {
|
||||
DeclaratorChunk I;
|
||||
I.Kind = Function;
|
||||
I.Loc = Loc;
|
||||
I.Fun.hasPrototype = hasProto;
|
||||
I.Fun.isVariadic = isVariadic;
|
||||
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
|
||||
I.Fun.DeleteArgInfo = false;
|
||||
I.Fun.TypeQuals = TypeQuals;
|
||||
I.Fun.NumArgs = NumArgs;
|
||||
I.Fun.ArgInfo = 0;
|
||||
|
||||
I.Kind = Function;
|
||||
I.Loc = Loc;
|
||||
I.Fun.hasPrototype = hasProto;
|
||||
I.Fun.isVariadic = isVariadic;
|
||||
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
|
||||
I.Fun.DeleteArgInfo = false;
|
||||
I.Fun.TypeQuals = TypeQuals;
|
||||
I.Fun.NumArgs = NumArgs;
|
||||
I.Fun.ArgInfo = 0;
|
||||
I.Fun.hasExceptionSpec = hasExceptionSpec;
|
||||
I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec;
|
||||
I.Fun.NumExceptions = NumExceptions;
|
||||
I.Fun.Exceptions = 0;
|
||||
|
||||
// new[] an argument array if needed.
|
||||
if (NumArgs) {
|
||||
// If the 'InlineParams' in Declarator is unused and big enough, put our
|
||||
|
@ -62,6 +70,12 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
|
|||
}
|
||||
memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs);
|
||||
}
|
||||
// new[] an exception array if needed
|
||||
if (NumExceptions) {
|
||||
I.Fun.Exceptions = new ActionBase::TypeTy*[NumExceptions];
|
||||
memcpy(I.Fun.Exceptions, Exceptions,
|
||||
sizeof(ActionBase::TypeTy*)*NumExceptions);
|
||||
}
|
||||
return I;
|
||||
}
|
||||
|
||||
|
|
|
@ -2246,14 +2246,21 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||
|
||||
// cv-qualifier-seq[opt].
|
||||
DeclSpec DS;
|
||||
bool hasExceptionSpec = false;
|
||||
bool hasAnyExceptionSpec = false;
|
||||
// FIXME: Does an empty vector ever allocate? Exception specifications are
|
||||
// extremely rare, so we want something like a SmallVector<TypeTy*, 0>. :-)
|
||||
std::vector<TypeTy*> Exceptions;
|
||||
if (getLang().CPlusPlus) {
|
||||
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
|
||||
if (!DS.getSourceRange().getEnd().isInvalid())
|
||||
Loc = DS.getSourceRange().getEnd();
|
||||
|
||||
// Parse exception-specification[opt].
|
||||
if (Tok.is(tok::kw_throw))
|
||||
ParseExceptionSpecification(Loc);
|
||||
if (Tok.is(tok::kw_throw)) {
|
||||
hasExceptionSpec = true;
|
||||
ParseExceptionSpecification(Loc, Exceptions, hasAnyExceptionSpec);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember that we parsed a function type, and remember the attributes.
|
||||
|
@ -2263,6 +2270,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||
SourceLocation(),
|
||||
/*arglist*/ 0, 0,
|
||||
DS.getTypeQualifiers(),
|
||||
hasExceptionSpec,
|
||||
hasAnyExceptionSpec,
|
||||
Exceptions.empty() ? 0 :
|
||||
&Exceptions[0],
|
||||
Exceptions.size(),
|
||||
LParenLoc, D),
|
||||
Loc);
|
||||
return;
|
||||
|
@ -2406,6 +2418,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||
SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||
|
||||
DeclSpec DS;
|
||||
bool hasExceptionSpec = false;
|
||||
bool hasAnyExceptionSpec = false;
|
||||
// FIXME: Does an empty vector ever allocate? Exception specifications are
|
||||
// extremely rare, so we want something like a SmallVector<TypeTy*, 0>. :-)
|
||||
std::vector<TypeTy*> Exceptions;
|
||||
if (getLang().CPlusPlus) {
|
||||
// Parse cv-qualifier-seq[opt].
|
||||
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
|
||||
|
@ -2413,8 +2430,10 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||
Loc = DS.getSourceRange().getEnd();
|
||||
|
||||
// Parse exception-specification[opt].
|
||||
if (Tok.is(tok::kw_throw))
|
||||
ParseExceptionSpecification(Loc);
|
||||
if (Tok.is(tok::kw_throw)) {
|
||||
hasExceptionSpec = true;
|
||||
ParseExceptionSpecification(Loc, Exceptions, hasAnyExceptionSpec);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember that we parsed a function type, and remember the attributes.
|
||||
|
@ -2422,7 +2441,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||
EllipsisLoc,
|
||||
&ParamInfo[0], ParamInfo.size(),
|
||||
DS.getTypeQualifiers(),
|
||||
LParenLoc, D),
|
||||
hasExceptionSpec,
|
||||
hasAnyExceptionSpec,
|
||||
Exceptions.empty() ? 0 :
|
||||
&Exceptions[0],
|
||||
Exceptions.size(), LParenLoc, D),
|
||||
Loc);
|
||||
}
|
||||
|
||||
|
@ -2496,7 +2519,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
|
|||
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
|
||||
SourceLocation(),
|
||||
&ParamInfo[0], ParamInfo.size(),
|
||||
/*TypeQuals*/0, LParenLoc, D),
|
||||
/*TypeQuals*/0,
|
||||
/*exception*/false, false, 0, 0,
|
||||
LParenLoc, D),
|
||||
RLoc);
|
||||
}
|
||||
|
||||
|
|
|
@ -1112,7 +1112,9 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
|
|||
/// type-id
|
||||
/// type-id-list ',' type-id
|
||||
///
|
||||
bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc) {
|
||||
bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
|
||||
std::vector<TypeTy*> &Exceptions,
|
||||
bool &hasAnyExceptionSpec) {
|
||||
assert(Tok.is(tok::kw_throw) && "expected throw");
|
||||
|
||||
SourceLocation ThrowLoc = ConsumeToken();
|
||||
|
@ -1125,6 +1127,7 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc) {
|
|||
// Parse throw(...), a Microsoft extension that means "this function
|
||||
// can throw anything".
|
||||
if (Tok.is(tok::ellipsis)) {
|
||||
hasAnyExceptionSpec = true;
|
||||
SourceLocation EllipsisLoc = ConsumeToken();
|
||||
if (!getLang().Microsoft)
|
||||
Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
|
||||
|
@ -1134,10 +1137,12 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc) {
|
|||
|
||||
// Parse the sequence of type-ids.
|
||||
while (Tok.isNot(tok::r_paren)) {
|
||||
ParseTypeName();
|
||||
TypeResult Res(ParseTypeName());
|
||||
if (!Res.isInvalid())
|
||||
Exceptions.push_back(Res.get());
|
||||
if (Tok.is(tok::comma))
|
||||
ConsumeToken();
|
||||
else
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1353,8 +1353,9 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
|
|||
// Otherwise, pretend we saw (void).
|
||||
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
|
||||
SourceLocation(),
|
||||
0, 0, 0, CaretLoc,
|
||||
ParamInfo),
|
||||
0, 0, 0,
|
||||
false, false, 0, 0,
|
||||
CaretLoc, ParamInfo),
|
||||
CaretLoc);
|
||||
// Inform sema that we are starting a block.
|
||||
Actions.ActOnBlockArguments(ParamInfo, CurScope);
|
||||
|
|
|
@ -3066,8 +3066,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|||
Error = Error; // Silence warning.
|
||||
assert(!Error && "Error setting up implicit decl!");
|
||||
Declarator D(DS, Declarator::BlockContext);
|
||||
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(),
|
||||
0, 0, 0, Loc, D),
|
||||
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0,
|
||||
0, 0, false, false, 0, 0, Loc, D),
|
||||
SourceLocation());
|
||||
D.SetIdentifier(&II, Loc);
|
||||
|
||||
|
|
|
@ -13,3 +13,5 @@ void h() throw(X, Y) { }
|
|||
class Class {
|
||||
void foo() throw (X, Y) { }
|
||||
};
|
||||
|
||||
void (*fptr)() throw();
|
||||
|
|
|
@ -1668,7 +1668,7 @@ welcome!</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td> 15.4 [except.spec]</td>
|
||||
<td></td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
|
|
Loading…
Reference in New Issue