[cfe-commits] r127086 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h include/clang/Sema/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp test/CXX/except/except.spec/p1.cpp test/Parser/cxx-exception-spec.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sat Mar 5 06:45:16 PST 2011
Author: cornedbee
Date: Sat Mar 5 08:45:16 2011
New Revision: 127086
URL: http://llvm.org/viewvc/llvm-project?rev=127086&view=rev
Log:
Parser support for noexcept specifications.
Added:
cfe/trunk/test/CXX/except/except.spec/p1.cpp
Removed:
cfe/trunk/test/Parser/cxx-exception-spec.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/DeclSpec.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=127086&r1=127085&r2=127086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Mar 5 08:45:16 2011
@@ -300,6 +300,8 @@
"expected '{' after base class list">;
def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
+def err_dynamic_and_noexcept_specification : Error<
+ "cannot have both throw() and noexcept() clause on the same function">;
def err_expected_catch : Error<"expected catch">;
def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
def err_using_namespace_in_class : Error<
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=127086&r1=127085&r2=127086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Mar 5 08:45:16 2011
@@ -1114,11 +1114,18 @@
//===--------------------------------------------------------------------===//
// C++ 15: C++ Throw Expression
ExprResult ParseThrowExpression();
+
+ ExceptionSpecificationType MaybeParseExceptionSpecification(
+ SourceRange &SpecificationRange,
+ llvm::SmallVectorImpl<ParsedType> &DynamicExceptions,
+ llvm::SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
+ ExprResult &NoexceptExpr);
+
// EndLoc is filled with the location of the last token of the specification.
- bool ParseExceptionSpecification(SourceLocation &EndLoc,
- llvm::SmallVectorImpl<ParsedType> &Exns,
- llvm::SmallVectorImpl<SourceRange> &Ranges,
- bool &hasAnyExceptionSpec);
+ ExceptionSpecificationType ParseDynamicExceptionSpecification(
+ SourceRange &SpecificationRange,
+ llvm::SmallVectorImpl<ParsedType> &Exceptions,
+ llvm::SmallVectorImpl<SourceRange> &Ranges);
//===--------------------------------------------------------------------===//
// C++0x 8: Function declaration trailing-return-type
Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=127086&r1=127085&r2=127086&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Sat Mar 5 08:45:16 2011
@@ -907,6 +907,15 @@
/// parsing.
typedef llvm::SmallVector<Token, 4> CachedTokens;
+/// \brief The various types of exception specifications that exist in C++0x.
+enum ExceptionSpecificationType {
+ EST_None, ///< no exception specification
+ EST_Dynamic, ///< throw() or throw(T1, T2)
+ EST_DynamicAny, ///< Microsoft throw(...) extension
+ EST_BasicNoexcept, ///< noexcept
+ EST_ComputedNoexcept ///< noexcept(expression)
+};
+
/// DeclaratorChunk - One instance of this struct is used for each type in a
/// declarator that is parsed.
///
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=127086&r1=127085&r2=127086&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Mar 5 08:45:16 2011
@@ -3127,6 +3127,10 @@
/// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- // 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 @@
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);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=127086&r1=127085&r2=127086&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Mar 5 08:45:16 2011
@@ -2001,10 +2001,76 @@
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 @@
/// 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 @@
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
Added: cfe/trunk/test/CXX/except/except.spec/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=127086&view=auto
==============================================================================
--- cfe/trunk/test/CXX/except/except.spec/p1.cpp (added)
+++ cfe/trunk/test/CXX/except/except.spec/p1.cpp Sat Mar 5 08:45:16 2011
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// Simple parser tests, dynamic specification.
+
+namespace dyn {
+
+ struct X { };
+
+ struct Y { };
+
+ void f() throw() { }
+
+ void g(int) throw(X) { }
+
+ void h() throw(X, Y) { }
+
+ class Class {
+ void foo() throw (X, Y) { }
+ };
+
+ void (*fptr)() throw();
+
+}
+
+// Simple parser tests, noexcept specification.
+
+namespace noex {
+
+ void f() noexcept { }
+ void g() noexcept (true) { }
+ void h() noexcept (false) { }
+ void i() noexcept (1 < 2) { }
+
+ class Class {
+ void foo() noexcept { }
+ void bar() noexcept (true) { }
+ };
+
+ void (*fptr)() noexcept;
+ void (*gptr)() noexcept (true);
+
+}
+
+namespace bad {
+
+ void f() throw(int) noexcept { } // expected-error {{cannot have both}}
+ void g() noexcept throw(int) { } // expected-error {{cannot have both}}
+
+}
Removed: cfe/trunk/test/Parser/cxx-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-exception-spec.cpp?rev=127085&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx-exception-spec.cpp (original)
+++ cfe/trunk/test/Parser/cxx-exception-spec.cpp (removed)
@@ -1,17 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only %s
-
-struct X { };
-
-struct Y { };
-
-void f() throw() { }
-
-void g(int) throw(X) { }
-
-void h() throw(X, Y) { }
-
-class Class {
- void foo() throw (X, Y) { }
-};
-
-void (*fptr)() throw();
More information about the cfe-commits
mailing list