r221918 - PR21437, final part of DR1330: delay-parsing of exception-specifications. This

Richard Smith richard-llvm at metafoo.co.uk
Thu Nov 13 12:01:57 PST 2014


Author: rsmith
Date: Thu Nov 13 14:01:57 2014
New Revision: 221918

URL: http://llvm.org/viewvc/llvm-project?rev=221918&view=rev
Log:
PR21437, final part of DR1330: delay-parsing of exception-specifications. This
is a re-commit of Doug's r154844 (modernized and updated to fit into current
Clang).

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
    cfe/trunk/include/clang/Basic/TokenKinds.def
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/CXX/class/class.mem/p2.cpp
    cfe/trunk/test/CXX/drs/dr4xx.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
    cfe/trunk/test/SemaCXX/dependent-noexcept-unevaluated.cpp
    cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Nov 13 14:01:57 2014
@@ -930,6 +930,12 @@ public:
   /// \brief Change the result type of a function type once it is deduced.
   void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
 
+  /// \brief Change the exception specification on a function once it is
+  /// delay-parsed, instantiated, or computed.
+  void adjustExceptionSpec(FunctionDecl *FD,
+                           const FunctionProtoType::ExceptionSpecInfo &ESI,
+                           bool AsWritten = false);
+
   /// \brief Return the uniqued reference to the type for a complex
   /// number with the specified element type.
   QualType getComplexType(QualType T) const;

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Nov 13 14:01:57 2014
@@ -68,6 +68,9 @@ public:
 
   /// \brief Return the TypeLoc wrapper for the type source info.
   TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
+  
+  /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
+  void overrideType(QualType T) { Ty = T; }
 };
 
 /// TranslationUnitDecl - The top declaration context.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Nov 13 14:01:57 2014
@@ -1245,6 +1245,7 @@ protected:
 
   class FunctionTypeBitfields {
     friend class FunctionType;
+    friend class FunctionProtoType;
 
     unsigned : NumTypeBits;
 
@@ -1259,6 +1260,11 @@ protected:
     /// C++ 8.3.5p4: The return type, the parameter type list and the
     /// cv-qualifier-seq, [...], are part of the function type.
     unsigned TypeQuals : 3;
+
+    /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+    ///
+    /// This is a value of type \c RefQualifierKind.
+    unsigned RefQualifier : 2;
   };
 
   class ObjCObjectTypeBitfields {
@@ -2765,7 +2771,7 @@ class FunctionType : public Type {
 
 protected:
   FunctionType(TypeClass tc, QualType res,
-               unsigned typeQuals, QualType Canonical, bool Dependent,
+               QualType Canonical, bool Dependent,
                bool InstantiationDependent,
                bool VariablyModified, bool ContainsUnexpandedParameterPack,
                ExtInfo Info)
@@ -2773,7 +2779,6 @@ protected:
            ContainsUnexpandedParameterPack),
       ResultType(res) {
     FunctionTypeBits.ExtInfo = Info.Bits;
-    FunctionTypeBits.TypeQuals = typeQuals;
   }
   unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
 
@@ -2810,7 +2815,7 @@ public:
 /// no information available about its arguments.
 class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
   FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
-    : FunctionType(FunctionNoProto, Result, 0, Canonical,
+    : FunctionType(FunctionNoProto, Result, Canonical,
                    /*Dependent=*/false, /*InstantiationDependent=*/false,
                    Result->isVariablyModifiedType(),
                    /*ContainsUnexpandedParameterPack=*/false, Info) {}
@@ -2914,7 +2919,7 @@ private:
   unsigned NumExceptions : 9;
 
   /// ExceptionSpecType - The type of exception specification this function has.
-  unsigned ExceptionSpecType : 3;
+  unsigned ExceptionSpecType : 4;
 
   /// HasAnyConsumedParams - Whether this function has any consumed parameters.
   unsigned HasAnyConsumedParams : 1;
@@ -2925,11 +2930,6 @@ private:
   /// HasTrailingReturn - Whether this function has a trailing return type.
   unsigned HasTrailingReturn : 1;
 
-  /// \brief The ref-qualifier associated with a \c FunctionProtoType.
-  ///
-  /// This is a value of type \c RefQualifierKind.
-  unsigned RefQualifier : 2;
-
   // ParamInfo - There is an variable size array after the class in memory that
   // holds the parameter types.
 
@@ -3076,7 +3076,7 @@ public:
 
   /// \brief Retrieve the ref-qualifier associated with this function type.
   RefQualifierKind getRefQualifier() const {
-    return static_cast<RefQualifierKind>(RefQualifier);
+    return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier);
   }
 
   typedef const QualType *param_type_iterator;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Nov 13 14:01:57 2014
@@ -496,6 +496,8 @@ def ext_ellipsis_exception_spec : Extens
   InGroup<Microsoft>;
 def err_dynamic_and_noexcept_specification : Error<
   "cannot have both throw() and noexcept() clause on the same function">;
+def err_except_spec_unparsed : Error<
+  "unexpected end of exception specification">;
 def warn_cxx98_compat_noexcept_decl : Warning<
   "noexcept specifications are incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Nov 13 14:01:57 2014
@@ -1117,6 +1117,8 @@ def warn_missing_exception_specification
   "%0 is missing exception specification '%1'">;
 def err_noexcept_needs_constant_expression : Error<
   "argument to noexcept specifier must be a constant expression">;
+def err_exception_spec_not_parsed : Error<
+  "exception specification is not available until end of class definition">;
 
 // C++ access checking
 def err_class_redeclared_with_different_access : Error<

Modified: cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h (original)
+++ cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h Thu Nov 13 14:01:57 2014
@@ -26,7 +26,8 @@ enum ExceptionSpecificationType {
   EST_BasicNoexcept,    ///< noexcept
   EST_ComputedNoexcept, ///< noexcept(expression)
   EST_Unevaluated,      ///< not evaluated yet, for special member function
-  EST_Uninstantiated    ///< not instantiated yet
+  EST_Uninstantiated,   ///< not instantiated yet
+  EST_Unparsed          ///< not parsed yet
 };
 
 inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {

Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Thu Nov 13 14:01:57 2014
@@ -117,6 +117,7 @@ TOK(eod)                 // End of prepr
                          // directive).
 TOK(code_completion)     // Code completion marker
 TOK(cxx_defaultarg_end)  // C++ default argument end marker
+TOK(cxx_exceptspec_end)  // C++ exception-specification end marker
 
 // C99 6.4.9: Comments.
 TOK(comment)             // Comment (only in -E -C[C] mode)

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Nov 13 14:01:57 2014
@@ -1453,10 +1453,12 @@ private:
   ExprResult ParseThrowExpression();
 
   ExceptionSpecificationType tryParseExceptionSpecification(
+                    bool Delayed,
                     SourceRange &SpecificationRange,
                     SmallVectorImpl<ParsedType> &DynamicExceptions,
                     SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
-                    ExprResult &NoexceptExpr);
+                    ExprResult &NoexceptExpr,
+                    CachedTokens *&ExceptionSpecTokens);
 
   // EndLoc is filled with the location of the last token of the specification.
   ExceptionSpecificationType ParseDynamicExceptionSpecification(

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Nov 13 14:01:57 2014
@@ -1176,7 +1176,7 @@ struct DeclaratorChunk {
     unsigned TypeQuals : 3;
 
     /// ExceptionSpecType - An ExceptionSpecificationType value.
-    unsigned ExceptionSpecType : 3;
+    unsigned ExceptionSpecType : 4;
 
     /// DeleteParams - If this is true, we need to delete[] Params.
     unsigned DeleteParams : 1;
@@ -1243,6 +1243,10 @@ struct DeclaratorChunk {
       /// \brief Pointer to the expression in the noexcept-specifier of this
       /// function, if it has one.
       Expr *NoexceptExpr;
+  
+      /// \brief Pointer to the cached tokens for an exception-specification
+      /// that has not yet been parsed.
+      CachedTokens *ExceptionSpecTokens;
     };
 
     /// \brief If HasTrailingReturnType is true, this is the trailing return
@@ -1269,6 +1273,8 @@ struct DeclaratorChunk {
         delete[] Params;
       if (getExceptionSpecType() == EST_Dynamic)
         delete[] Exceptions;
+      else if (getExceptionSpecType() == EST_Unparsed)
+        delete ExceptionSpecTokens;
     }
 
     /// isKNRPrototype - Return true if this is a K&R style identifier list,
@@ -1464,6 +1470,7 @@ struct DeclaratorChunk {
                                      SourceRange *ExceptionRanges,
                                      unsigned NumExceptions,
                                      Expr *NoexceptExpr,
+                                     CachedTokens *ExceptionSpecTokens,
                                      SourceLocation LocalRangeBegin,
                                      SourceLocation LocalRangeEnd,
                                      Declarator &TheDeclarator,

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Nov 13 14:01:57 2014
@@ -4106,6 +4106,16 @@ public:
                                    SmallVectorImpl<QualType> &Exceptions,
                                    FunctionProtoType::ExceptionSpecInfo &ESI);
 
+  /// \brief Add an exception-specification to the given member function
+  /// (or member function template). The exception-specification was parsed
+  /// after the method itself was declared.
+  void actOnDelayedExceptionSpecification(Decl *Method,
+         ExceptionSpecificationType EST,
+         SourceRange SpecificationRange,
+         ArrayRef<ParsedType> DynamicExceptions,
+         ArrayRef<SourceRange> DynamicExceptionRanges,
+         Expr *NoexceptExpr);
+
   /// \brief Determine if a special member function should have a deleted
   /// definition when it is defaulted.
   bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Nov 13 14:01:57 2014
@@ -2111,6 +2111,62 @@ void ASTContext::adjustDeducedFunctionRe
     L->DeducedReturnType(FD, ResultType);
 }
 
+/// Get a function type and produce the equivalent function type with the
+/// specified exception specification. Type sugar that can be present on a
+/// declaration of a function with an exception specification is permitted
+/// and preserved. Other type sugar (for instance, typedefs) is not.
+static QualType getFunctionTypeWithExceptionSpec(
+    ASTContext &Context, QualType Orig,
+    const FunctionProtoType::ExceptionSpecInfo &ESI) {
+  // Might have some parens.
+  if (auto *PT = dyn_cast<ParenType>(Orig))
+    return Context.getParenType(
+        getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI));
+
+  // Might have a calling-convention attribute.
+  if (auto *AT = dyn_cast<AttributedType>(Orig))
+    return Context.getAttributedType(
+        AT->getAttrKind(),
+        getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI),
+        getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(),
+                                         ESI));
+
+  // Anything else must be a function type. Rebuild it with the new exception
+  // specification.
+  const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig);
+  return Context.getFunctionType(
+      Proto->getReturnType(), Proto->getParamTypes(),
+      Proto->getExtProtoInfo().withExceptionSpec(ESI));
+}
+
+void ASTContext::adjustExceptionSpec(
+    FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI,
+    bool AsWritten) {
+  // Update the type.
+  QualType Updated =
+      getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI);
+  FD->setType(Updated);
+
+  if (!AsWritten)
+    return;
+
+  // Update the type in the type source information too.
+  if (TypeSourceInfo *TSInfo = FD->getTypeSourceInfo()) {
+    // If the type and the type-as-written differ, we may need to update
+    // the type-as-written too.
+    if (TSInfo->getType() != FD->getType())
+      Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI);
+
+    // FIXME: When we get proper type location information for exceptions,
+    // we'll also have to rebuild the TypeSourceInfo. For now, we just patch
+    // up the TypeSourceInfo;
+    assert(TypeLoc::getFullDataSizeForType(Updated) ==
+               TypeLoc::getFullDataSizeForType(TSInfo->getType()) &&
+           "TypeLoc size mismatch from updating exception specification");
+    TSInfo->overrideType(Updated);
+  }
+}
+
 /// getComplexType - Return the uniqued reference to the type for a complex
 /// number with the specified element type.
 QualType ASTContext::getComplexType(QualType T) const {

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Thu Nov 13 14:01:57 2014
@@ -1593,7 +1593,7 @@ StringRef FunctionType::getNameForCallCo
 FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
                                      QualType canonical,
                                      const ExtProtoInfo &epi)
-    : FunctionType(FunctionProto, result, epi.TypeQuals, canonical,
+    : FunctionType(FunctionProto, result, canonical,
                    result->isDependentType(),
                    result->isInstantiationDependentType(),
                    result->isVariablyModifiedType(),
@@ -1602,10 +1602,12 @@ FunctionProtoType::FunctionProtoType(Qua
       NumExceptions(epi.ExceptionSpec.Exceptions.size()),
       ExceptionSpecType(epi.ExceptionSpec.Type),
       HasAnyConsumedParams(epi.ConsumedParameters != nullptr),
-      Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn),
-      RefQualifier(epi.RefQualifier) {
+      Variadic(epi.Variadic), HasTrailingReturn(epi.HasTrailingReturn) {
   assert(NumParams == params.size() && "function has too many parameters");
 
+  FunctionTypeBits.TypeQuals = epi.TypeQuals;
+  FunctionTypeBits.RefQualifier = epi.RefQualifier;
+
   // Fill in the trailing argument array.
   QualType *argSlot = reinterpret_cast<QualType*>(this+1);
   for (unsigned i = 0; i != NumParams; ++i) {
@@ -1772,7 +1774,7 @@ void FunctionProtoType::Profile(llvm::Fo
   assert(!(unsigned(epi.Variadic) & ~1) &&
          !(unsigned(epi.TypeQuals) & ~255) &&
          !(unsigned(epi.RefQualifier) & ~3) &&
-         !(unsigned(epi.ExceptionSpec.Type) & ~7) &&
+         !(unsigned(epi.ExceptionSpec.Type) & ~15) &&
          "Values larger than expected.");
   ID.AddInteger(unsigned(epi.Variadic) +
                 (epi.TypeQuals << 1) +

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Thu Nov 13 14:01:57 2014
@@ -366,6 +366,76 @@ void Parser::ParseLexedMethodDeclaration
     }
   }
 
+  // Parse a delayed exception-specification, if there is one.
+  if (CachedTokens *Toks = LM.ExceptionSpecTokens) {
+    // Save the current token position.
+    SourceLocation origLoc = Tok.getLocation();
+
+    // Parse the default argument from its saved token stream.
+    Toks->push_back(Tok); // So that the current token doesn't get lost
+    PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
+
+    // Consume the previously-pushed token.
+    ConsumeAnyToken();
+
+    // C++11 [expr.prim.general]p3:
+    //   If a declaration declares a member function or member function
+    //   template of a class X, the expression this is a prvalue of type
+    //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+    //   and the end of the function-definition, member-declarator, or
+    //   declarator.
+    CXXMethodDecl *Method;
+    if (FunctionTemplateDecl *FunTmpl
+          = dyn_cast<FunctionTemplateDecl>(LM.Method))
+      Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+    else
+      Method = cast<CXXMethodDecl>(LM.Method);
+
+    Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(),
+                                     Method->getTypeQualifiers(),
+                                     getLangOpts().CPlusPlus11);
+
+    // Parse the exception-specification.
+    SourceRange SpecificationRange;
+    SmallVector<ParsedType, 4> DynamicExceptions;
+    SmallVector<SourceRange, 4> DynamicExceptionRanges;
+    ExprResult NoexceptExpr;
+    CachedTokens *ExceptionSpecTokens;
+
+    ExceptionSpecificationType EST
+      = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange,
+                                       DynamicExceptions,
+                                       DynamicExceptionRanges, NoexceptExpr,
+                                       ExceptionSpecTokens);
+
+    // Clean up the remaining tokens.
+    if (Tok.is(tok::cxx_exceptspec_end))
+      ConsumeToken();
+    else if (EST != EST_None)
+      Diag(Tok.getLocation(), diag::err_except_spec_unparsed);
+
+    // Attach the exception-specification to the method.
+    if (EST != EST_None)
+      Actions.actOnDelayedExceptionSpecification(LM.Method, EST,
+                                                 SpecificationRange,
+                                                 DynamicExceptions,
+                                                 DynamicExceptionRanges,
+                                                 NoexceptExpr.isUsable()?
+                                                   NoexceptExpr.get() : nullptr);
+
+    assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+                                                            Tok.getLocation()) &&
+           "tryParseExceptionSpecification went over the exception tokens!");
+
+    // There could be leftover tokens (e.g. because of an error).
+    // Skip through until we reach the original token position.
+    while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof))
+      ConsumeAnyToken();
+
+    delete Toks;
+    LM.ExceptionSpecTokens = nullptr;
+  }
+
   PrototypeScope.Exit();
 
   // Finish the delayed C++ method declaration.

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Nov 13 14:01:57 2014
@@ -5193,6 +5193,7 @@ void Parser::ParseFunctionDeclarator(Dec
   SmallVector<ParsedType, 2> DynamicExceptions;
   SmallVector<SourceRange, 2> DynamicExceptionRanges;
   ExprResult NoexceptExpr;
+  CachedTokens *ExceptionSpecTokens = 0;
   ParsedAttributes FnAttrs(AttrFactory);
   TypeResult TrailingReturnType;
 
@@ -5279,10 +5280,14 @@ void Parser::ParseFunctionDeclarator(Dec
                                IsCXX11MemberFunction);
 
       // Parse exception-specification[opt].
-      ESpecType = tryParseExceptionSpecification(ESpecRange,
+      bool Delayed = D.isFirstDeclarationOfMember() &&
+                     D.isFunctionDeclaratorAFunctionDeclaration();
+      ESpecType = tryParseExceptionSpecification(Delayed,
+                                                 ESpecRange,
                                                  DynamicExceptions,
                                                  DynamicExceptionRanges,
-                                                 NoexceptExpr);
+                                                 NoexceptExpr,
+                                                 ExceptionSpecTokens);
       if (ESpecType != EST_None)
         EndLoc = ESpecRange.getEnd();
 
@@ -5322,6 +5327,7 @@ void Parser::ParseFunctionDeclarator(Dec
                                              DynamicExceptions.size(),
                                              NoexceptExpr.isUsable() ?
                                                NoexceptExpr.get() : nullptr,
+                                             ExceptionSpecTokens,
                                              StartLoc, LocalEndLoc, D,
                                              TrailingReturnType),
                 FnAttrs, EndLoc);

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Nov 13 14:01:57 2014
@@ -1875,16 +1875,34 @@ AccessSpecifier Parser::getAccessSpecifi
 }
 
 /// \brief If the given declarator has any parts for which parsing has to be
-/// delayed, e.g., default arguments, create a late-parsed method declaration
-/// record to handle the parsing at the end of the class definition.
+/// delayed, e.g., default arguments or an exception-specification, create a
+/// late-parsed method declaration record to handle the parsing at the end of
+/// the class definition.
 void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
                                             Decl *ThisDecl) {
   // We just declared a member function. If this member function
-  // has any default arguments, we'll need to parse them later.
+  // has any default arguments or an exception-specification, we'll need to
+  // parse them later.
   LateParsedMethodDeclaration *LateMethod = nullptr;
   DeclaratorChunk::FunctionTypeInfo &FTI
     = DeclaratorInfo.getFunctionTypeInfo();
 
+  // If there was a late-parsed exception-specification, hold onto its tokens.
+  if (FTI.getExceptionSpecType() == EST_Unparsed) {
+    // Push this method onto the stack of late-parsed method
+    // declarations.
+    LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
+    getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
+    LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();
+
+    // Stash the exception-specification tokens in the late-pased mthod.
+    LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
+    FTI.ExceptionSpecTokens = 0;
+
+    // Reserve space for the parameters.
+    LateMethod->DefaultArgs.reserve(FTI.NumParams);
+  }
+
   for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
     if (LateMethod || FTI.Params[ParamIdx].DefaultArgTokens) {
       if (!LateMethod) {
@@ -2857,7 +2875,7 @@ void Parser::ParseCXXMemberSpecification
 
   // C++11 [class.mem]p2:
   //   Within the class member-specification, the class is regarded as complete
-  //   within function bodies, default arguments, and
+  //   within function bodies, default arguments, exception-specifications, and
   //   brace-or-equal-initializers for non-static data members (including such
   //   things in nested classes).
   if (TagDecl && NonNestedClass) {
@@ -3076,13 +3094,63 @@ MemInitResult Parser::ParseMemInitialize
 ///         'noexcept'
 ///         'noexcept' '(' constant-expression ')'
 ExceptionSpecificationType
-Parser::tryParseExceptionSpecification(
+Parser::tryParseExceptionSpecification(bool Delayed,
                     SourceRange &SpecificationRange,
                     SmallVectorImpl<ParsedType> &DynamicExceptions,
                     SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
-                    ExprResult &NoexceptExpr) {
+                    ExprResult &NoexceptExpr,
+                    CachedTokens *&ExceptionSpecTokens) {
   ExceptionSpecificationType Result = EST_None;
-
+  ExceptionSpecTokens = 0;
+  
+  // Handle delayed parsing of exception-specifications.
+  if (Delayed) {
+    if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))
+      return EST_None;
+
+    // Consume and cache the starting token.
+    bool IsNoexcept = Tok.is(tok::kw_noexcept);
+    Token StartTok = Tok;
+    SpecificationRange = SourceRange(ConsumeToken());
+
+    // Check for a '('.
+    if (!Tok.is(tok::l_paren)) {
+      // If this is a bare 'noexcept', we're done.
+      if (IsNoexcept) {
+        Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);
+        NoexceptExpr = 0;
+        return EST_BasicNoexcept;
+      }
+      
+      Diag(Tok, diag::err_expected_lparen_after) << "throw";
+      return EST_DynamicNone;
+    }
+    
+    // Cache the tokens for the exception-specification.
+    ExceptionSpecTokens = new CachedTokens;
+    ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'
+    ExceptionSpecTokens->push_back(Tok); // '('
+    SpecificationRange.setEnd(ConsumeParen()); // '('
+    
+    if (!ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,
+                              /*StopAtSemi=*/true,
+                              /*ConsumeFinalToken=*/true)) {
+      NoexceptExpr = 0;
+      delete ExceptionSpecTokens;
+      ExceptionSpecTokens = 0;
+      return IsNoexcept? EST_BasicNoexcept : EST_DynamicNone;
+    }
+    SpecificationRange.setEnd(Tok.getLocation());
+    
+    // Add the 'stop' token.
+    Token End;
+    End.startToken();
+    End.setKind(tok::cxx_exceptspec_end);
+    End.setLocation(Tok.getLocation());
+    ExceptionSpecTokens->push_back(End);
+    return EST_Unparsed;
+  }
+  
   // See if there's a dynamic specification.
   if (Tok.is(tok::kw_throw)) {
     Result = ParseDynamicExceptionSpecification(SpecificationRange,

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Thu Nov 13 14:01:57 2014
@@ -2642,6 +2642,7 @@ ExprResult Parser::ParseBlockLiteralExpr
                                              /*ExceptionRanges=*/nullptr,
                                              /*NumExceptions=*/0,
                                              /*NoexceptExpr=*/nullptr,
+                                             /*ExceptionSpecTokens=*/nullptr,
                                              CaretLoc, CaretLoc,
                                              ParamInfo),
                           attrs, CaretLoc);

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Nov 13 14:01:57 2014
@@ -1061,10 +1061,13 @@ ExprResult Parser::ParseLambdaExpression
     SmallVector<ParsedType, 2> DynamicExceptions;
     SmallVector<SourceRange, 2> DynamicExceptionRanges;
     ExprResult NoexceptExpr;
-    ESpecType = tryParseExceptionSpecification(ESpecRange,
+    CachedTokens *ExceptionSpecTokens;
+    ESpecType = tryParseExceptionSpecification(/*Delayed=*/false,
+                                               ESpecRange,
                                                DynamicExceptions,
                                                DynamicExceptionRanges,
-                                               NoexceptExpr);
+                                               NoexceptExpr,
+                                               ExceptionSpecTokens);
 
     if (ESpecType != EST_None)
       DeclEndLoc = ESpecRange.getEnd();
@@ -1105,6 +1108,7 @@ ExprResult Parser::ParseLambdaExpression
                                            DynamicExceptions.size(),
                                            NoexceptExpr.isUsable() ?
                                              NoexceptExpr.get() : nullptr,
+                                           /*ExceptionSpecTokens*/nullptr,
                                            LParenLoc, FunLocalRangeEnd, D,
                                            TrailingReturnType),
                   Attr, DeclEndLoc);
@@ -1173,6 +1177,7 @@ ExprResult Parser::ParseLambdaExpression
                                                /*ExceptionRanges=*/nullptr,
                                                /*NumExceptions=*/0,
                                                /*NoexceptExpr=*/nullptr,
+                                               /*ExceptionSpecTokens=*/nullptr,
                                                DeclLoc, DeclEndLoc, D,
                                                TrailingReturnType),
                   Attr, DeclEndLoc);

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Thu Nov 13 14:01:57 2014
@@ -182,6 +182,7 @@ DeclaratorChunk DeclaratorChunk::getFunc
                                              SourceRange *ExceptionRanges,
                                              unsigned NumExceptions,
                                              Expr *NoexceptExpr,
+                                             CachedTokens *ExceptionSpecTokens,
                                              SourceLocation LocalRangeBegin,
                                              SourceLocation LocalRangeEnd,
                                              Declarator &TheDeclarator,
@@ -219,6 +220,9 @@ DeclaratorChunk DeclaratorChunk::getFunc
                                   TrailingReturnType.isInvalid();
   I.Fun.TrailingReturnType      = TrailingReturnType.get();
 
+  assert(I.Fun.TypeQuals == TypeQuals && "bitfield overflow");
+  assert(I.Fun.ExceptionSpecType == ESpecType && "bitfield overflow");
+
   // new[] a parameter array if needed.
   if (NumParams) {
     // If the 'InlineParams' in Declarator is unused and big enough, put our
@@ -255,6 +259,10 @@ DeclaratorChunk DeclaratorChunk::getFunc
   case EST_ComputedNoexcept:
     I.Fun.NoexceptExpr = NoexceptExpr;
     break;
+
+  case EST_Unparsed:
+    I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
+    break;
   }
   return I;
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Nov 13 14:01:57 2014
@@ -10682,6 +10682,7 @@ NamedDecl *Sema::ImplicitlyDefineFunctio
                                              /*ExceptionRanges=*/nullptr,
                                              /*NumExceptions=*/0,
                                              /*NoexceptExpr=*/nullptr,
+                                             /*ExceptionSpecTokens=*/nullptr,
                                              Loc, Loc, D),
                 DS.getAttributes(),
                 SourceLocation());

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Nov 13 14:01:57 2014
@@ -5286,6 +5286,12 @@ void Sema::CheckExplicitlyDefaultedSpeci
 /// C++11 [dcl.fct.def.default]p2.
 void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
     CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
+  // If the exception specification was explicitly specified but hadn't been
+  // parsed when the method was defaulted, grab it now.
+  if (SpecifiedType->getExceptionSpecType() == EST_Unparsed)
+    SpecifiedType =
+        MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();
+
   // Compute the implicit exception specification.
   CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
                                                        /*IsCXXMethod=*/true);
@@ -13245,6 +13251,7 @@ bool Sema::checkThisInStaticMemberFuncti
   FindCXXThisExpr Finder(*this);
 
   switch (Proto->getExceptionSpecType()) {
+  case EST_Unparsed:
   case EST_Uninstantiated:
   case EST_Unevaluated:
   case EST_BasicNoexcept:
@@ -13372,6 +13379,45 @@ void Sema::checkExceptionSpecification(
   }
 }
 
+void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
+             ExceptionSpecificationType EST,
+             SourceRange SpecificationRange,
+             ArrayRef<ParsedType> DynamicExceptions,
+             ArrayRef<SourceRange> DynamicExceptionRanges,
+             Expr *NoexceptExpr) {
+  if (!MethodD)
+    return;
+
+  // Dig out the method we're referring to.
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
+    MethodD = FunTmpl->getTemplatedDecl();
+
+  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD);
+  if (!Method)
+    return;
+
+  // Check the exception specification.
+  llvm::SmallVector<QualType, 4> Exceptions;
+  FunctionProtoType::ExceptionSpecInfo ESI;
+  checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions,
+                              DynamicExceptionRanges, NoexceptExpr, Exceptions,
+                              ESI);
+
+  // Update the exception specification on the function type.
+  Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true);
+
+  if (Method->isStatic())
+    checkThisInStaticMemberFunctionExceptionSpec(Method);
+
+  if (Method->isVirtual()) {
+    // Check overrides, which we previously had to delay.
+    for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
+                                     OEnd = Method->end_overridden_methods();
+         O != OEnd; ++O)
+      CheckOverridingFunctionExceptionSpec(Method, *O);
+  }
+}
+
 /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
 ///
 MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Thu Nov 13 14:01:57 2014
@@ -112,6 +112,11 @@ bool Sema::CheckDistantExceptionSpec(Qua
 
 const FunctionProtoType *
 Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
+  if (FPT->getExceptionSpecType() == EST_Unparsed) {
+    Diag(Loc, diag::err_exception_spec_not_parsed);
+    return nullptr;
+  }
+
   if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
     return FPT;
 
@@ -135,16 +140,8 @@ Sema::ResolveExceptionSpec(SourceLocatio
 void
 Sema::UpdateExceptionSpec(FunctionDecl *FD,
                           const FunctionProtoType::ExceptionSpecInfo &ESI) {
-  for (auto *Redecl : FD->redecls()) {
-    auto *RedeclFD = dyn_cast<FunctionDecl>(Redecl);
-    const FunctionProtoType *Proto =
-        RedeclFD->getType()->castAs<FunctionProtoType>();
-
-    // Overwrite the exception spec and rebuild the function type.
-    RedeclFD->setType(Context.getFunctionType(
-        Proto->getReturnType(), Proto->getParamTypes(),
-        Proto->getExtProtoInfo().withExceptionSpec(ESI)));
-  }
+  for (auto *Redecl : FD->redecls())
+    Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
 
   // If we've fully resolved the exception specification, notify listeners.
   if (!isUnresolvedExceptionSpec(ESI.Type))
@@ -790,6 +787,11 @@ bool Sema::CheckOverridingFunctionExcept
       return false;
     }
   }
+  // If the exception specification hasn't been parsed yet, skip the check.
+  // We'll get called again once it's been parsed.
+  if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
+      EST_Unparsed)
+    return false;
   unsigned DiagID = diag::err_override_exception_spec;
   if (getLangOpts().MicrosoftExt)
     DiagID = diag::ext_override_exception_spec;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Nov 13 14:01:57 2014
@@ -661,27 +661,27 @@ static void maybeSynthesizeBlockSignatur
   // ...and *prepend* it to the declarator.
   SourceLocation NoLoc;
   declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
-                             /*HasProto=*/true,
-                             /*IsAmbiguous=*/false,
-                             /*LParenLoc=*/NoLoc,
-                             /*ArgInfo=*/nullptr,
-                             /*NumArgs=*/0,
-                             /*EllipsisLoc=*/NoLoc,
-                             /*RParenLoc=*/NoLoc,
-                             /*TypeQuals=*/0,
-                             /*RefQualifierIsLvalueRef=*/true,
-                             /*RefQualifierLoc=*/NoLoc,
-                             /*ConstQualifierLoc=*/NoLoc,
-                             /*VolatileQualifierLoc=*/NoLoc,
-                             /*RestrictQualifierLoc=*/NoLoc,
-                             /*MutableLoc=*/NoLoc,
-                             EST_None,
-                             /*ESpecLoc=*/NoLoc,
-                             /*Exceptions=*/nullptr,
-                             /*ExceptionRanges=*/nullptr,
-                             /*NumExceptions=*/0,
-                             /*NoexceptExpr=*/nullptr,
-                             loc, loc, declarator));
+      /*HasProto=*/true,
+      /*IsAmbiguous=*/false,
+      /*LParenLoc=*/NoLoc,
+      /*ArgInfo=*/nullptr,
+      /*NumArgs=*/0,
+      /*EllipsisLoc=*/NoLoc,
+      /*RParenLoc=*/NoLoc,
+      /*TypeQuals=*/0,
+      /*RefQualifierIsLvalueRef=*/true,
+      /*RefQualifierLoc=*/NoLoc,
+      /*ConstQualifierLoc=*/NoLoc,
+      /*VolatileQualifierLoc=*/NoLoc,
+      /*RestrictQualifierLoc=*/NoLoc,
+      /*MutableLoc=*/NoLoc, EST_None,
+      /*ESpecLoc=*/NoLoc,
+      /*Exceptions=*/nullptr,
+      /*ExceptionRanges=*/nullptr,
+      /*NumExceptions=*/0,
+      /*NoexceptExpr=*/nullptr,
+      /*ExceptionSpecTokens=*/nullptr,
+      loc, loc, declarator));
 
   // For consistency, make sure the state still has us as processing
   // the decl spec.

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Nov 13 14:01:57 2014
@@ -2782,10 +2782,8 @@ void ASTDeclReader::attachPreviousDeclIm
   if (FPT && PrevFPT &&
       isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
       !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) {
-    FunctionProtoType::ExtProtoInfo EPI = PrevFPT->getExtProtoInfo();
-    FD->setType(Reader.Context.getFunctionType(
-        FPT->getReturnType(), FPT->getParamTypes(),
-        FPT->getExtProtoInfo().withExceptionSpec(EPI.ExceptionSpec)));
+    Reader.Context.adjustExceptionSpec(
+        FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
   }
 }
 }

Modified: cfe/trunk/test/CXX/class/class.mem/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.mem/p2.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class/class.mem/p2.cpp (original)
+++ cfe/trunk/test/CXX/class/class.mem/p2.cpp Thu Nov 13 14:01:57 2014
@@ -56,3 +56,33 @@ namespace test3 {
 
   template struct A2<int>;
 }
+
+namespace PR12629 {
+  struct S {
+    static int (f)() throw();
+    static int ((((((g))))() throw(U)));
+    int (*h)() noexcept(false);
+    static int (&i)() noexcept(true);
+    static int (*j)() throw(U); // expected-error {{unknown type name 'U'}}
+    static int (k)() throw(U);
+
+    struct U {};
+  };
+  static_assert(noexcept(S::f()), "");
+  static_assert(!noexcept(S::g()), "");
+  static_assert(!noexcept(S().h()), "");
+  static_assert(noexcept(S::i()), "");
+}
+
+namespace PR12688 {
+  struct S {
+    // FIXME: Producing one error saying this can't have the same name
+    //        as the class because it's not a constructor, then producing
+    //        another error saying this can't have a return type because
+    //        it is a constructor, is redundant and inconsistent.
+    nonsense S() throw (more_nonsense); // \
+    // expected-error {{'nonsense'}} \
+    // expected-error {{has the same name as its class}} \
+    // expected-error {{constructor cannot have a return type}}
+  };
+}

Modified: cfe/trunk/test/CXX/drs/dr4xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr4xx.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr4xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr4xx.cpp Thu Nov 13 14:01:57 2014
@@ -502,15 +502,15 @@ namespace dr436 { // dr436: yes
   void f(); // expected-error {{redefinition}}
 }
 
-namespace dr437 { // dr437: no
+namespace dr437 { // dr437: sup 1308
   // This is superseded by 1308, which is in turn superseded by 1330,
   // which restores this rule.
-  template<typename U> struct T : U {}; // expected-error {{incomplete}}
-  struct S { // expected-note {{not complete}}
+  template<typename U> struct T : U {};
+  struct S {
     void f() throw(S);
-    void g() throw(T<S>); // expected-note {{in instantiation of}}
-    struct U; // expected-note {{forward}}
-    void h() throw(U); // expected-error {{incomplete}}
+    void g() throw(T<S>);
+    struct U;
+    void h() throw(U);
     struct U {};
   };
 }

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp Thu Nov 13 14:01:57 2014
@@ -136,12 +136,11 @@ namespace Static {
 
 namespace PR12564 {
   struct Base {
-    void bar(Base&) {} // FIXME: expected-note {{here}}
+    void bar(Base&) {}
   };
 
   struct Derived : Base {
-    // FIXME: This should be accepted.
-    void foo(Derived& d) noexcept(noexcept(d.bar(d))) {} // expected-error {{cannot bind to a value of unrelated type}}
+    void foo(Derived& d) noexcept(noexcept(d.bar(d))) {}
   };
 }
 

Modified: cfe/trunk/test/SemaCXX/dependent-noexcept-unevaluated.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dependent-noexcept-unevaluated.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dependent-noexcept-unevaluated.cpp (original)
+++ cfe/trunk/test/SemaCXX/dependent-noexcept-unevaluated.cpp Thu Nov 13 14:01:57 2014
@@ -23,7 +23,7 @@ struct array
 {
     T data[N];
 
-    void swap(array& a) noexcept(noexcept(swap(declval<T&>(), declval<T&>())));
+  void swap(array& a) noexcept(noexcept(::swap(declval<T&>(), declval<T&>())));
 };
 
 struct DefaultOnly
@@ -38,3 +38,4 @@ int main()
 {
     array<DefaultOnly, 1> a, b;
 }
+

Modified: cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp?rev=221918&r1=221917&r2=221918&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp Thu Nov 13 14:01:57 2014
@@ -46,13 +46,12 @@ namespace InClassInitializers {
 }
 
 namespace ExceptionSpecification {
-  // A type is permitted to be used in a dynamic exception specification when it
-  // is still being defined, but isn't complete within such an exception
-  // specification.
-  struct Nested { // expected-note {{not complete}}
+  // FIXME: This diagnostic is quite useless; we should indicate whose
+  // exception specification we were looking for and why.
+  struct Nested {
     struct T {
-      T() noexcept(!noexcept(Nested())); // expected-error{{incomplete type}}
-    } t;
+      T() noexcept(!noexcept(Nested()));
+    } t; // expected-error{{exception specification is not available until end of class definition}}
   };
 }
 





More information about the cfe-commits mailing list