From 2b9cacbffa4f7cc024ff5cdd7025e881c23f407e Mon Sep 17 00:00:00 2001
From: Sebastian Redl
Date: Wed, 29 Apr 2009 17:30:04 +0000
Subject: [PATCH] Have the parser communicate the exception specification to
the action.
llvm-svn: 70389
---
clang/include/clang/Parse/DeclSpec.h | 32 +++++++++++++++-----
clang/include/clang/Parse/Parser.h | 4 ++-
clang/lib/Parse/DeclSpec.cpp | 34 +++++++++++++++-------
clang/lib/Parse/ParseDecl.cpp | 37 ++++++++++++++++++++----
clang/lib/Parse/ParseDeclCXX.cpp | 11 +++++--
clang/lib/Parse/ParseExpr.cpp | 5 ++--
clang/lib/Sema/SemaDecl.cpp | 4 +--
clang/test/Parser/cxx-exception-spec.cpp | 2 ++
clang/www/cxx_status.html | 2 +-
9 files changed, 99 insertions(+), 32 deletions(-)
diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h
index e1f52a02466c..e97c20f2d19b 100644
--- a/clang/include/clang/Parse/DeclSpec.h
+++ b/clang/include/clang/Parse/DeclSpec.h
@@ -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.
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index fdb2327d4b35..084996d61c19 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -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 &Exceptions,
+ bool &hasAnyExceptionSpec);
//===--------------------------------------------------------------------===//
// C++ 2.13.5: C++ Boolean Literals
diff --git a/clang/lib/Parse/DeclSpec.cpp b/clang/lib/Parse/DeclSpec.cpp
index bcf14d916cb6..d742ef2ed093 100644
--- a/clang/lib/Parse/DeclSpec.cpp
+++ b/clang/lib/Parse/DeclSpec.cpp
@@ -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;
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f02b8a068255..ec8923a23b2d 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -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. :-)
+ std::vector 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. :-)
+ std::vector 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);
}
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index c6a373dc5c4d..f684649f858b 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -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 &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;
}
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 55bc1862f56f..f299c5246ec6 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 14136a30b691..4d6a103ccd70 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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);
diff --git a/clang/test/Parser/cxx-exception-spec.cpp b/clang/test/Parser/cxx-exception-spec.cpp
index b2203c96df72..0a87ab702302 100644
--- a/clang/test/Parser/cxx-exception-spec.cpp
+++ b/clang/test/Parser/cxx-exception-spec.cpp
@@ -13,3 +13,5 @@ void h() throw(X, Y) { }
class Class {
void foo() throw (X, Y) { }
};
+
+void (*fptr)() throw();
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index e8547cd6bb45..8f857e4d8d45 100644
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1668,7 +1668,7 @@ welcome!
15.4 [except.spec] |
- |
+ ✓ |
|
|
|