aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2011-03-05 14:45:16 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2011-03-05 14:45:16 +0000
commit7acafd032e145dbdbbed9274ca57ec2c86b912bc (patch)
treeb73974f2c6ede1cebe101a1f5dd33ac75dacbcaa /lib
parentb6ab6c1ca733fda2302a1c5066bdfc6218c89e41 (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.cpp85
-rw-r--r--lib/Parse/ParseDeclCXX.cpp101
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