[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