Have the parser communicate the exception specification to the action.

llvm-svn: 70389
This commit is contained in:
Sebastian Redl 2009-04-29 17:30:04 +00:00
parent 99fe1695c7
commit 2b9cacbffa
9 changed files with 99 additions and 32 deletions

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -13,3 +13,5 @@ void h() throw(X, Y) { }
class Class {
void foo() throw (X, Y) { }
};
void (*fptr)() throw();

View File

@ -1668,7 +1668,7 @@ welcome!</p>
</tr>
<tr>
<td>&nbsp;&nbsp;15.4 [except.spec]</td>
<td></td>
<td class="complete" align="center">&#x2713;</td>
<td></td>
<td></td>
<td></td>