diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-03-05 14:45:16 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2011-03-05 14:45:16 +0000 |
commit | 7acafd032e145dbdbbed9274ca57ec2c86b912bc (patch) | |
tree | b73974f2c6ede1cebe101a1f5dd33ac75dacbcaa /lib | |
parent | b6ab6c1ca733fda2302a1c5066bdfc6218c89e41 (diff) |
Parser support for noexcept specifications.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127086 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 85 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 101 |
2 files changed, 129 insertions, 57 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 50ba7054fe..5cda4e6d5c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3127,6 +3127,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]", /// C++0x "ref-qualifier[opt]" and "exception-specification[opt]". /// +/// [C++0x] exception-specification: +/// dynamic-exception-specification +/// noexcept-specification +/// void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ParsedAttributes &attrs, bool RequiresArg) { @@ -3147,11 +3151,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DeclSpec DS; SourceLocation RefQualifierLoc; bool RefQualifierIsLValueRef = true; - bool hasExceptionSpec = false; - SourceLocation ThrowLoc; - bool hasAnyExceptionSpec = false; - llvm::SmallVector<ParsedType, 2> Exceptions; - llvm::SmallVector<SourceRange, 2> ExceptionRanges; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + llvm::SmallVector<ParsedType, 2> DynamicExceptions; + llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; + ExprResult NoexceptExpr; if (getLang().CPlusPlus) { MaybeParseCXX0XAttributes(attrs); @@ -3168,16 +3172,14 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, RefQualifierLoc = ConsumeToken(); EndLoc = RefQualifierLoc; } - + // Parse exception-specification[opt]. - if (Tok.is(tok::kw_throw)) { - hasExceptionSpec = true; - ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, - hasAnyExceptionSpec); - assert(Exceptions.size() == ExceptionRanges.size() && - "Produced different number of exception types and ranges."); - } + ESpecType = MaybeParseExceptionSpecification(ESpecRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr); + if (ESpecType != EST_None) + EndLoc = ESpecRange.getEnd(); // Parse trailing-return-type. if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { @@ -3195,11 +3197,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - hasExceptionSpec, ThrowLoc, - hasAnyExceptionSpec, - Exceptions.data(), - ExceptionRanges.data(), - Exceptions.size(), + ESpecType == EST_Dynamic || + ESpecType == EST_DynamicAny, + ESpecRange.getBegin(), + ESpecType == EST_DynamicAny, + DynamicExceptions.data(), + DynamicExceptionRanges.data(), + DynamicExceptions.size(), LParenLoc, RParenLoc, D, TrailingReturnType), EndLoc); @@ -3396,11 +3400,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DeclSpec DS; SourceLocation RefQualifierLoc; bool RefQualifierIsLValueRef = true; - bool hasExceptionSpec = false; - SourceLocation ThrowLoc; - bool hasAnyExceptionSpec = false; - llvm::SmallVector<ParsedType, 2> Exceptions; - llvm::SmallVector<SourceRange, 2> ExceptionRanges; + ExceptionSpecificationType ESpecType = EST_None; + SourceRange ESpecRange; + llvm::SmallVector<ParsedType, 2> DynamicExceptions; + llvm::SmallVector<SourceRange, 2> DynamicExceptionRanges; + ExprResult NoexceptExpr; if (getLang().CPlusPlus) { MaybeParseCXX0XAttributes(attrs); @@ -3420,15 +3424,17 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EndLoc = RefQualifierLoc; } + // FIXME: We should leave the prototype scope before parsing the exception + // specification, and then reenter it when parsing the trailing return type. + // FIXMEFIXME: Why? That wouldn't be right for the noexcept clause. + // Parse exception-specification[opt]. - if (Tok.is(tok::kw_throw)) { - hasExceptionSpec = true; - ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, - hasAnyExceptionSpec); - assert(Exceptions.size() == ExceptionRanges.size() && - "Produced different number of exception types and ranges."); - } + ESpecType = MaybeParseExceptionSpecification(ESpecRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr); + if (ESpecType != EST_None) + EndLoc = ESpecRange.getEnd(); // Parse trailing-return-type. if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { @@ -3436,9 +3442,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } } - // FIXME: We should leave the prototype scope before parsing the exception - // specification, and then reenter it when parsing the trailing return type. - // Leave prototype scope. PrototypeScope.Exit(); @@ -3450,11 +3453,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, DS.getTypeQualifiers(), RefQualifierIsLValueRef, RefQualifierLoc, - hasExceptionSpec, ThrowLoc, - hasAnyExceptionSpec, - Exceptions.data(), - ExceptionRanges.data(), - Exceptions.size(), + ESpecType == EST_Dynamic || + ESpecType == EST_DynamicAny, + ESpecRange.getBegin(), + ESpecType == EST_DynamicAny, + DynamicExceptions.data(), + DynamicExceptionRanges.data(), + DynamicExceptions.size(), LParenLoc, RParenLoc, D, TrailingReturnType), EndLoc); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index f6344248f8..ad1d0015e1 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2001,10 +2001,76 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { EllipsisLoc); } -/// ParseExceptionSpecification - Parse a C++ exception-specification -/// (C++ [except.spec]). +/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). /// /// exception-specification: +/// dynamic-exception-specification +/// noexcept-specification +/// +/// noexcept-specification: +/// 'noexcept' +/// 'noexcept' '(' constant-expression ')' +ExceptionSpecificationType +Parser::MaybeParseExceptionSpecification(SourceRange &SpecificationRange, + llvm::SmallVectorImpl<ParsedType> &DynamicExceptions, + llvm::SmallVectorImpl<SourceRange> &DynamicExceptionRanges, + ExprResult &NoexceptExpr) { + ExceptionSpecificationType Result = EST_None; + + // See if there's a dynamic specification. + if (Tok.is(tok::kw_throw)) { + Result = ParseDynamicExceptionSpecification(SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges); + assert(DynamicExceptions.size() == DynamicExceptionRanges.size() && + "Produced different number of exception types and ranges."); + } + + // If there's no noexcept specification, we're done. + if (Tok.isNot(tok::kw_noexcept)) + return Result; + + // If we already had a dynamic specification, parse the noexcept for, + // recovery, but emit a diagnostic and don't store the results. + SourceRange NoexceptRange; + ExceptionSpecificationType NoexceptType = EST_None; + + SourceLocation KeywordLoc = ConsumeToken(); + if (Tok.is(tok::l_paren)) { + // There is an argument. + SourceLocation LParenLoc = ConsumeParen(); + NoexceptType = EST_ComputedNoexcept; + NoexceptExpr = ParseConstantExpression(); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + NoexceptRange = SourceRange(KeywordLoc, RParenLoc); + } else { + // There is no argument. + NoexceptType = EST_BasicNoexcept; + NoexceptRange = SourceRange(KeywordLoc, KeywordLoc); + } + + if (Result == EST_None) { + SpecificationRange = NoexceptRange; + Result = NoexceptType; + + // If there's a dynamic specification after a noexcept specification, + // parse that and ignore the results. + if (Tok.is(tok::kw_throw)) { + Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); + ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions, + DynamicExceptionRanges); + } + } else { + Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification); + } + + return Result; +} + +/// ParseDynamicExceptionSpecification - Parse a C++ +/// dynamic-exception-specification (C++ [except.spec]). +/// +/// dynamic-exception-specification: /// 'throw' '(' type-id-list [opt] ')' /// [MS] 'throw' '(' '...' ')' /// @@ -2012,46 +2078,47 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { /// type-id ... [opt] /// type-id-list ',' type-id ... [opt] /// -bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, - llvm::SmallVectorImpl<ParsedType> - &Exceptions, - llvm::SmallVectorImpl<SourceRange> - &Ranges, - bool &hasAnyExceptionSpec) { +ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl<ParsedType> &Exceptions, + llvm::SmallVectorImpl<SourceRange> &Ranges) { assert(Tok.is(tok::kw_throw) && "expected throw"); - ConsumeToken(); + SpecificationRange.setBegin(ConsumeToken()); if (!Tok.is(tok::l_paren)) { - return Diag(Tok, diag::err_expected_lparen_after) << "throw"; + Diag(Tok, diag::err_expected_lparen_after) << "throw"; + SpecificationRange.setEnd(SpecificationRange.getBegin()); + return EST_Dynamic; } SourceLocation LParenLoc = ConsumeParen(); // 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); - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return false; + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SpecificationRange.setEnd(RParenLoc); + return EST_DynamicAny; } // Parse the sequence of type-ids. SourceRange Range; while (Tok.isNot(tok::r_paren)) { TypeResult Res(ParseTypeName(&Range)); - + if (Tok.is(tok::ellipsis)) { // C++0x [temp.variadic]p5: // - In a dynamic-exception-specification (15.4); the pattern is a // type-id. SourceLocation Ellipsis = ConsumeToken(); + Range.setEnd(Ellipsis); if (!Res.isInvalid()) Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis); } - + if (!Res.isInvalid()) { Exceptions.push_back(Res.get()); Ranges.push_back(Range); @@ -2063,8 +2130,8 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, break; } - EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return false; + SpecificationRange.setEnd(MatchRHSPunctuation(tok::r_paren, LParenLoc)); + return EST_Dynamic; } /// ParseTrailingReturnType - Parse a trailing return type on a new-style |