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] - + ✓