[cfe-commits] r160847 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/Analysis/ lib/Sema/ lib/Serialization/ test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/ test/CodeGenCXX/ test/SemaCXX/ test/

Richard Smith richard at metafoo.co.uk
Thu Jul 26 22:47:03 PDT 2012


A function template or a (non-template) member function of a class
temploid. Basically, a thing that can be instantiated to produce a
function. This terminology isn't yet in the standard, but core issue 1253
is all about this.
On 26 Jul 2012 22:22, "Sean Silva" <silvas at purdue.edu> wrote:

> what is a "function temploid"?
>
> --Sean Silva
>
> On Thu, Jul 26, 2012 at 9:22 PM, Richard Smith
> <richard-llvm at metafoo.co.uk> wrote:
> > Author: rsmith
> > Date: Thu Jul 26 23:22:15 2012
> > New Revision: 160847
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=160847&view=rev
> > Log:
> > Final piece of core issue 1330: delay computing the exception
> specification of
> > a defaulted special member function until the exception specification is
> needed
> > (using the same criteria used for the delayed instantiation of exception
> > specifications for function temploids).
> >
> > EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
> > EST_Uninstantiated, carries a pointer to the FunctionDecl which will be
> used to
> > resolve the exception specification.
> >
> > This is enabled for all C++ modes: it's a little faster in the case
> where the
> > exception specification isn't used, allows our C++11-in-C++98 extensions
> to
> > work, and is still correct for C++98, since in that mode the computation
> of the
> > exception specification can't fail.
> >
> > The diagnostics here aren't great (in particular, we should include
> implicit
> > evaluation of exception specifications for defaulted special members in
> the
> > template instantiation backtraces), but they're not much worse than
> before.
> >
> > Our approach to the problem of cycles between in-class initializers and
> the
> > exception specification for a defaulted default constructor is modified a
> > little by this change -- we now reject any odr-use of a defaulted default
> > constructor if that constructor uses an in-class initializer and the use
> is in
> > an in-class initialzer which is declared lexically earlier. This is a
> closer
> > approximation to the current draft solution in core issue 1351, but
> isn't an
> > exact match (but the current draft wording isn't reasonable, so that's
> to be
> > expected).
> >
> > Removed:
> >     cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp
> > Modified:
> >     cfe/trunk/include/clang/AST/Type.h
> >     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> >     cfe/trunk/include/clang/Basic/ExceptionSpecificationType.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/Analysis/CFG.cpp
> >     cfe/trunk/lib/Sema/SemaDecl.cpp
> >     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> >     cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
> >     cfe/trunk/lib/Sema/SemaExpr.cpp
> >     cfe/trunk/lib/Sema/SemaExprCXX.cpp
> >     cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
> >     cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> >     cfe/trunk/lib/Serialization/ASTReader.cpp
> >     cfe/trunk/lib/Serialization/ASTWriter.cpp
> >
> cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp
> >     cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp
> >     cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
> >     cfe/trunk/test/SemaCXX/member-init.cpp
> >     cfe/trunk/test/SemaCXX/type-traits.cpp
> >     cfe/trunk/test/SemaTemplate/instantiation-depth.cpp
> >
> > Modified: cfe/trunk/include/clang/AST/Type.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/Type.h (original)
> > +++ cfe/trunk/include/clang/AST/Type.h Thu Jul 26 23:22:15 2012
> > @@ -2847,6 +2847,8 @@
> >      } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
> >        EPI.ExceptionSpecDecl = getExceptionSpecDecl();
> >        EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
> > +    } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
> > +      EPI.ExceptionSpecDecl = getExceptionSpecDecl();
> >      }
> >      if (hasAnyConsumedArgs())
> >        EPI.ConsumedArguments = getConsumedArgsBuffer();
> > @@ -2890,11 +2892,13 @@
> >      // NoexceptExpr sits where the arguments end.
> >      return *reinterpret_cast<Expr *const *>(arg_type_end());
> >    }
> > -  /// \brief If this function type has an uninstantiated exception
> > -  /// specification, this is the function whose exception specification
> > -  /// is represented by this type.
> > +  /// \brief If this function type has an exception specification which
> hasn't
> > +  /// been determined yet (either because it has not been evaluated or
> because
> > +  /// it has not been instantiated), this is the function whose
> exception
> > +  /// specification is represented by this type.
> >    FunctionDecl *getExceptionSpecDecl() const {
> > -    if (getExceptionSpecType() != EST_Uninstantiated)
> > +    if (getExceptionSpecType() != EST_Uninstantiated &&
> > +        getExceptionSpecType() != EST_Unevaluated)
> >        return 0;
> >      return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0];
> >    }
> > @@ -2909,7 +2913,7 @@
> >    }
> >    bool isNothrow(ASTContext &Ctx) const {
> >      ExceptionSpecificationType EST = getExceptionSpecType();
> > -    assert(EST != EST_Delayed && EST != EST_Uninstantiated);
> > +    assert(EST != EST_Unevaluated && EST != EST_Uninstantiated);
> >      if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
> >        return true;
> >      if (EST != EST_ComputedNoexcept)
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 26
> 23:22:15 2012
> > @@ -870,8 +870,6 @@
> >    "%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_unknown : Error<
> > -  "exception specification is not available until end of class
> definition">;
> >
> >  // C++ access checking
> >  def err_class_redeclared_with_different_access : Error<
> > @@ -5088,6 +5086,9 @@
> >    "'constexpr' specifier">;
> >  def err_in_class_initializer_non_constant : Error<
> >    "in-class initializer for static data member is not a constant
> expression">;
> > +def err_in_class_initializer_references_def_ctor : Error<
> > +  "defaulted default constructor of %0 cannot be used by non-static
> data "
> > +  "member initializer which appears before end of class definition">;
> >
> >  def ext_in_class_initializer_non_constant : Extension<
> >    "in-class initializer for static data member is not a constant
> expression; "
> >
> > Modified: cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h (original)
> > +++ cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h Thu Jul
> 26 23:22:15 2012
> > @@ -25,7 +25,7 @@
> >    EST_MSAny,            ///< Microsoft throw(...) extension
> >    EST_BasicNoexcept,    ///< noexcept
> >    EST_ComputedNoexcept, ///< noexcept(expression)
> > -  EST_Delayed,          ///< not known yet
> > +  EST_Unevaluated,      ///< not evaluated yet, for special member
> function
> >    EST_Uninstantiated    ///< not instantiated yet
> >  };
> >
> > @@ -37,6 +37,10 @@
> >    return ESpecType == EST_BasicNoexcept || ESpecType ==
> EST_ComputedNoexcept;
> >  }
> >
> > +inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType
> ESpecType) {
> > +  return ESpecType == EST_Unevaluated || ESpecType ==
> EST_Uninstantiated;
> > +}
> > +
> >  /// \brief Possible results from evaluation of a noexcept expression.
> >  enum CanThrowResult {
> >    CT_Cannot,
> >
> > Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> > +++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Jul 26 23:22:15 2012
> > @@ -1152,8 +1152,7 @@
> >      /// any.
> >      unsigned MutableLoc;
> >
> > -    /// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the
> > -    /// location of the keyword introducing the spec.
> > +    /// \brief The location of the keyword introducing the spec, if any.
> >      unsigned ExceptionSpecLoc;
> >
> >      /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo
> objects that
> >
> > Modified: cfe/trunk/include/clang/Sema/Sema.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > +++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 26 23:22:15 2012
> > @@ -3335,17 +3335,6 @@
> >      /// \brief Integrate an invoked expression into the collected data.
> >      void CalledExpr(Expr *E);
> >
> > -    /// \brief Specify that the exception specification can't be
> detemined yet.
> > -    void SetDelayed() {
> > -      ClearExceptions();
> > -      ComputedEST = EST_Delayed;
> > -    }
> > -
> > -    /// \brief Have we been unable to compute this exception
> specification?
> > -    bool isDelayed() {
> > -      return ComputedEST == EST_Delayed;
> > -    }
> > -
> >      /// \brief Overwrite an EPI's exception specification with this
> >      /// computed exception specification.
> >      void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const {
> > @@ -3363,34 +3352,39 @@
> >    /// \brief Determine what sort of exception specification a defaulted
> >    /// copy constructor of a class will have.
> >    ImplicitExceptionSpecification
> > -  ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl);
> > +  ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
> > +                                           CXXMethodDecl *MD);
> >
> >    /// \brief Determine what sort of exception specification a defaulted
> >    /// default constructor of a class will have, and whether the
> parameter
> >    /// will be const.
> > -  std::pair<ImplicitExceptionSpecification, bool>
> > -  ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl
> *ClassDecl);
> > +  ImplicitExceptionSpecification
> > +  ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD);
> >
> >    /// \brief Determine what sort of exception specification a defautled
> >    /// copy assignment operator of a class will have, and whether the
> >    /// parameter will be const.
> > -  std::pair<ImplicitExceptionSpecification, bool>
> > -  ComputeDefaultedCopyAssignmentExceptionSpecAndConst(CXXRecordDecl
> *ClassDecl);
> > +  ImplicitExceptionSpecification
> > +  ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD);
> >
> >    /// \brief Determine what sort of exception specification a defaulted
> move
> >    /// constructor of a class will have.
> >    ImplicitExceptionSpecification
> > -  ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl);
> > +  ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD);
> >
> >    /// \brief Determine what sort of exception specification a defaulted
> move
> >    /// assignment operator of a class will have.
> >    ImplicitExceptionSpecification
> > -  ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl);
> > +  ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD);
> >
> >    /// \brief Determine what sort of exception specification a defaulted
> >    /// destructor of a class will have.
> >    ImplicitExceptionSpecification
> > -  ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl);
> > +  ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD);
> > +
> > +  /// \brief Evaluate the implicit exception specification for a
> defaulted
> > +  /// special member function.
> > +  void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl
> *MD);
> >
> >    /// \brief Check the given exception-specification and update the
> >    /// extended prototype information with the results.
> > @@ -3438,8 +3432,7 @@
> >    /// C++11 says that user-defined destructors with no exception spec
> get one
> >    /// that looks as if the destructor was implicitly declared.
> >    void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
> > -                                     CXXDestructorDecl *Destructor,
> > -                                     bool WasDelayed = false);
> > +                                     CXXDestructorDecl *Destructor);
> >
> >    /// \brief Declare all inherited constructors for the given class.
> >    ///
> > @@ -4262,6 +4255,11 @@
> >    void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
> >                        bool DefinitionRequired = false);
> >
> > +  /// \brief Mark the exception specifications of all virtual member
> functions
> > +  /// in the given class as needed.
> > +  void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
> > +                                             const CXXRecordDecl *RD);
> > +
> >    /// MarkVirtualMembersReferenced - Will mark all members of the given
> >    /// CXXRecordDecl referenced.
> >    void MarkVirtualMembersReferenced(SourceLocation Loc,
> >
> > Modified: cfe/trunk/lib/AST/ASTContext.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> > +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Jul 26 23:22:15 2012
> > @@ -2367,15 +2367,18 @@
> >    //  - exception types
> >    //  - consumed-arguments flags
> >    // Instead of the exception types, there could be a noexcept
> > -  // expression.
> > +  // expression, or information used to resolve the exception
> > +  // specification.
> >    size_t Size = sizeof(FunctionProtoType) +
> >                  NumArgs * sizeof(QualType);
> > -  if (EPI.ExceptionSpecType == EST_Dynamic)
> > +  if (EPI.ExceptionSpecType == EST_Dynamic) {
> >      Size += EPI.NumExceptions * sizeof(QualType);
> > -  else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
> > +  } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
> >      Size += sizeof(Expr*);
> >    } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
> >      Size += 2 * sizeof(FunctionDecl*);
> > +  } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
> > +    Size += sizeof(FunctionDecl*);
> >    }
> >    if (EPI.ConsumedArguments)
> >      Size += NumArgs * sizeof(bool);
> >
> > Modified: cfe/trunk/lib/AST/Type.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/Type.cpp (original)
> > +++ cfe/trunk/lib/AST/Type.cpp Thu Jul 26 23:22:15 2012
> > @@ -1584,6 +1584,11 @@
> >      slot[1] = epi.ExceptionSpecTemplate;
> >      // This exception specification doesn't make the type dependent,
> because
> >      // it's not instantiated as part of instantiating the type.
> > +  } else if (getExceptionSpecType() == EST_Unevaluated) {
> > +    // Store the function decl from which we will resolve our
> > +    // exception specification.
> > +    FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot +
> numArgs);
> > +    slot[0] = epi.ExceptionSpecDecl;
> >    }
> >
> >    if (epi.ConsumedArguments) {
> > @@ -1667,7 +1672,8 @@
> >        ID.AddPointer(epi.Exceptions[i].getAsOpaquePtr());
> >    } else if (epi.ExceptionSpecType == EST_ComputedNoexcept &&
> epi.NoexceptExpr){
> >      epi.NoexceptExpr->Profile(ID, Context, false);
> > -  } else if (epi.ExceptionSpecType == EST_Uninstantiated) {
> > +  } else if (epi.ExceptionSpecType == EST_Uninstantiated ||
> > +             epi.ExceptionSpecType == EST_Unevaluated) {
> >      ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
> >    }
> >    if (epi.ConsumedArguments) {
> >
> > Modified: cfe/trunk/lib/Analysis/CFG.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Analysis/CFG.cpp (original)
> > +++ cfe/trunk/lib/Analysis/CFG.cpp Thu Jul 26 23:22:15 2012
> > @@ -1340,7 +1340,7 @@
> >    const FunctionType *FT = Ty->getAs<FunctionType>();
> >    if (FT) {
> >      if (const FunctionProtoType *Proto =
> dyn_cast<FunctionProtoType>(FT))
> > -      if (Proto->getExceptionSpecType() != EST_Uninstantiated &&
> > +      if (!isUnresolvedExceptionSpec(Proto->getExceptionSpecType()) &&
> >            Proto->isNothrow(Ctx))
> >          return false;
> >    }
> >
> > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jul 26 23:22:15 2012
> > @@ -4655,11 +4655,6 @@
> >    return false;
> >  }
> >
> > -static bool hasDelayedExceptionSpec(CXXMethodDecl *Method) {
> > -  const FunctionProtoType *Proto
> =Method->getType()->getAs<FunctionProtoType>();
> > -  return Proto && Proto->getExceptionSpecType() == EST_Delayed;
> > -}
> > -
> >  /// AddOverriddenMethods - See if a method overrides any in the base
> classes,
> >  /// and if so, check that it's a valid override and remember it.
> >  bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
> > @@ -4675,8 +4670,7 @@
> >        if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
> >          MD->addOverriddenMethod(OldMD->getCanonicalDecl());
> >          if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
> > -            (hasDelayedExceptionSpec(MD) ||
> > -             !CheckOverridingFunctionExceptionSpec(MD, OldMD)) &&
> > +            !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
> >              !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
> >            AddedAny = true;
> >          }
> >
> > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jul 26 23:22:15 2012
> > @@ -128,8 +128,8 @@
> >
> >  void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation
> CallLoc,
> >                                                        CXXMethodDecl
> *Method) {
> > -  // If we have an MSAny or unknown spec already, don't bother.
> > -  if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
> > +  // If we have an MSAny spec already, don't bother.
> > +  if (!Method || ComputedEST == EST_MSAny)
> >      return;
> >
> >    const FunctionProtoType *Proto
> > @@ -141,7 +141,7 @@
> >    ExceptionSpecificationType EST = Proto->getExceptionSpecType();
> >
> >    // If this function can throw any exceptions, make a note of that.
> > -  if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) {
> > +  if (EST == EST_MSAny || EST == EST_None) {
> >      ClearExceptions();
> >      ComputedEST = EST;
> >      return;
> > @@ -198,7 +198,7 @@
> >  }
> >
> >  void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
> > -  if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
> > +  if (!E || ComputedEST == EST_MSAny)
> >      return;
> >
> >    // FIXME:
> > @@ -3881,9 +3881,6 @@
> >    //   instantiated (e.g. meta-functions). This doesn't apply to
> classes that
> >    //   have inherited constructors.
> >    DeclareInheritedConstructors(Record);
> > -
> > -  if (!Record->isDependentType())
> > -    CheckExplicitlyDefaultedMethods(Record);
> >  }
> >
> >  void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) {
> > @@ -3989,6 +3986,45 @@
> >    return true;
> >  }
> >
> > +static Sema::ImplicitExceptionSpecification
> > +computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl
> *MD) {
> > +  switch (S.getSpecialMember(MD)) {
> > +  case Sema::CXXDefaultConstructor:
> > +    return S.ComputeDefaultedDefaultCtorExceptionSpec(Loc, MD);
> > +  case Sema::CXXCopyConstructor:
> > +    return S.ComputeDefaultedCopyCtorExceptionSpec(MD);
> > +  case Sema::CXXCopyAssignment:
> > +    return S.ComputeDefaultedCopyAssignmentExceptionSpec(MD);
> > +  case Sema::CXXMoveConstructor:
> > +    return S.ComputeDefaultedMoveCtorExceptionSpec(MD);
> > +  case Sema::CXXMoveAssignment:
> > +    return S.ComputeDefaultedMoveAssignmentExceptionSpec(MD);
> > +  case Sema::CXXDestructor:
> > +    return S.ComputeDefaultedDtorExceptionSpec(MD);
> > +  case Sema::CXXInvalid:
> > +    break;
> > +  }
> > +  llvm_unreachable("only special members have implicit exception
> specs");
> > +}
> > +
> > +void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc,
> CXXMethodDecl *MD) {
> > +  const FunctionProtoType *FPT =
> MD->getType()->castAs<FunctionProtoType>();
> > +  if (FPT->getExceptionSpecType() != EST_Unevaluated)
> > +    return;
> > +
> > +  // Evaluate the exception specification and update the type of the
> special
> > +  // member to use it.
> > +  FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
> > +  computeImplicitExceptionSpec(*this, Loc, MD).getEPI(EPI);
> > +  const FunctionProtoType *NewFPT = cast<FunctionProtoType>(
> > +    Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
> > +                            FPT->getNumArgs(), EPI));
> > +  MD->setType(QualType(NewFPT, 0));
> > +}
> > +
> > +static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl
> *ClassDecl);
> > +static bool isImplicitCopyAssignmentArgConst(Sema &S, CXXRecordDecl
> *ClassDecl);
> > +
> >  void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
> >    CXXRecordDecl *RD = MD->getParent();
> >    CXXSpecialMember CSM = getSpecialMember(MD);
> > @@ -4023,40 +4059,28 @@
> >
> >    const FunctionProtoType *Type =
> MD->getType()->getAs<FunctionProtoType>();
> >
> > -  // Compute implicit exception specification, argument constness,
> constexpr
> > -  // and triviality.
> > -  ImplicitExceptionSpecification Spec(*this);
> > +  // Compute argument constness, constexpr, and triviality.
> >    bool CanHaveConstParam = false;
> >    bool Trivial;
> >    switch (CSM) {
> >    case CXXDefaultConstructor:
> > -    Spec = ComputeDefaultedDefaultCtorExceptionSpec(RD);
> > -    if (Spec.isDelayed())
> > -      // Exception specification depends on some deferred part of the
> class.
> > -      // We'll try again when the class's definition has been fully
> processed.
> > -      return;
> >      Trivial = RD->hasTrivialDefaultConstructor();
> >      break;
> >    case CXXCopyConstructor:
> > -    llvm::tie(Spec, CanHaveConstParam) =
> > -      ComputeDefaultedCopyCtorExceptionSpecAndConst(RD);
> > +    CanHaveConstParam = isImplicitCopyCtorArgConst(*this, RD);
> >      Trivial = RD->hasTrivialCopyConstructor();
> >      break;
> >    case CXXCopyAssignment:
> > -    llvm::tie(Spec, CanHaveConstParam) =
> > -      ComputeDefaultedCopyAssignmentExceptionSpecAndConst(RD);
> > +    CanHaveConstParam = isImplicitCopyAssignmentArgConst(*this, RD);
> >      Trivial = RD->hasTrivialCopyAssignment();
> >      break;
> >    case CXXMoveConstructor:
> > -    Spec = ComputeDefaultedMoveCtorExceptionSpec(RD);
> >      Trivial = RD->hasTrivialMoveConstructor();
> >      break;
> >    case CXXMoveAssignment:
> > -    Spec = ComputeDefaultedMoveAssignmentExceptionSpec(RD);
> >      Trivial = RD->hasTrivialMoveAssignment();
> >      break;
> >    case CXXDestructor:
> > -    Spec = ComputeDefaultedDtorExceptionSpec(RD);
> >      Trivial = RD->hasTrivialDestructor();
> >      break;
> >    case CXXInvalid:
> > @@ -4126,11 +4150,15 @@
> >      HadError = true;
> >    }
> >
> > -  // Rebuild the type with the implicit exception specification added.
> > -  FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
> > -  Spec.getEPI(EPI);
> > -  const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
> > -    Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI));
> > +  // Rebuild the type with the implicit exception specification added,
> if we
> > +  // are going to need it.
> > +  const FunctionProtoType *ImplicitType = 0;
> > +  if (First || Type->hasExceptionSpec()) {
> > +    FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
> > +    computeImplicitExceptionSpec(*this, MD->getLocation(),
> MD).getEPI(EPI);
> > +    ImplicitType = cast<FunctionProtoType>(
> > +      Context.getFunctionType(ReturnType, &ArgType, ExpectedParams,
> EPI));
> > +  }
> >
> >    // C++11 [dcl.fct.def.default]p2:
> >    //   An explicitly-defaulted function may be declared constexpr only
> if it
> > @@ -6685,7 +6713,10 @@
> >  }
> >
> >  Sema::ImplicitExceptionSpecification
> > -Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl
> *ClassDecl) {
> > +Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
> > +                                               CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> > +
> >    // C++ [except.spec]p14:
> >    //   An implicitly declared special member function (Clause 12) shall
> have an
> >    //   exception-specification. [...]
> > @@ -6732,7 +6763,21 @@
> >        if (Expr *E = F->getInClassInitializer())
> >          ExceptSpec.CalledExpr(E);
> >        else if (!F->isInvalidDecl())
> > -        ExceptSpec.SetDelayed();
> > +        // DR1351:
> > +        //   If the brace-or-equal-initializer of a non-static data
> member
> > +        //   invokes a defaulted default constructor of its class or of
> an
> > +        //   enclosing class in a potentially evaluated subexpression,
> the
> > +        //   program is ill-formed.
> > +        //
> > +        // This resolution is unworkable: the exception specification
> of the
> > +        // default constructor can be needed in an unevaluated context,
> in
> > +        // particular, in the operand of a noexcept-expression, and we
> can be
> > +        // unable to compute an exception specification for an enclosed
> class.
> > +        //
> > +        // We do not allow an in-class initializer to require the
> evaluation
> > +        // of the exception specification for any in-class initializer
> whose
> > +        // definition is not lexically complete.
> > +        Diag(Loc, diag::err_in_class_initializer_references_def_ctor)
> << MD;
> >      } else if (const RecordType *RecordTy
> >                =
> Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
> >        CXXRecordDecl *FieldRecDecl =
> cast<CXXRecordDecl>(RecordTy->getDecl());
> > @@ -6761,10 +6806,6 @@
> >    assert(!ClassDecl->hasUserDeclaredConstructor() &&
> >           "Should not build implicit default constructor!");
> >
> > -  ImplicitExceptionSpecification Spec =
> > -    ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> > -
> >    bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
> >
> CXXDefaultConstructor,
> >                                                       false);
> > @@ -6777,15 +6818,20 @@
> >      = Context.DeclarationNames.getCXXConstructorName(ClassType);
> >    DeclarationNameInfo NameInfo(Name, ClassLoc);
> >    CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
> > -      Context, ClassDecl, ClassLoc, NameInfo,
> > -      Context.getFunctionType(Context.VoidTy, 0, 0, EPI), /*TInfo=*/0,
> > +      Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(),
> /*TInfo=*/0,
> >        /*isExplicit=*/false, /*isInline=*/true,
> /*isImplicitlyDeclared=*/true,
> >        Constexpr);
> >    DefaultCon->setAccess(AS_public);
> >    DefaultCon->setDefaulted();
> >    DefaultCon->setImplicit();
> >    DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());
> > -
> > +
> > +  // Build an exception specification pointing back at this constructor.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = DefaultCon;
> > +  DefaultCon->setType(Context.getFunctionType(Context.VoidTy, 0, 0,
> EPI));
> > +
> >    // Note that we have declared this constructor.
> >    ++ASTContext::NumImplicitDefaultConstructorsDeclared;
> >
> > @@ -6830,58 +6876,14 @@
> >    }
> >  }
> >
> > -/// Get any existing defaulted default constructor for the given class.
> Do not
> > -/// implicitly define one if it does not exist.
> > -static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema
> &Self,
> > -
> CXXRecordDecl *D) {
> > -  ASTContext &Context = Self.Context;
> > -  QualType ClassType = Context.getTypeDeclType(D);
> > -  DeclarationName ConstructorName
> > -    = Context.DeclarationNames.getCXXConstructorName(
> > -
>  Context.getCanonicalType(ClassType.getUnqualifiedType()));
> > -
> > -  DeclContext::lookup_const_iterator Con, ConEnd;
> > -  for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName);
> > -       Con != ConEnd; ++Con) {
> > -    // A function template cannot be defaulted.
> > -    if (isa<FunctionTemplateDecl>(*Con))
> > -      continue;
> > -
> > -    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con);
> > -    if (Constructor->isDefaultConstructor())
> > -      return Constructor->isDefaulted() ? Constructor : 0;
> > -  }
> > -  return 0;
> > -}
> > -
> >  void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
> >    if (!D) return;
> >    AdjustDeclIfTemplate(D);
> >
> >    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D);
> > -  CXXConstructorDecl *CtorDecl
> > -    = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl);
> > -
> > -  if (!CtorDecl) return;
> >
> > -  // Compute the exception specification for the default constructor.
> > -  const FunctionProtoType *CtorTy =
> > -    CtorDecl->getType()->castAs<FunctionProtoType>();
> > -  if (CtorTy->getExceptionSpecType() == EST_Delayed) {
> > -    // FIXME: Don't do this unless the exception spec is needed.
> > -    ImplicitExceptionSpecification Spec =
> > -      ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
> > -    FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> > -    assert(EPI.ExceptionSpecType != EST_Delayed);
> > -
> > -    CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0,
> EPI));
> > -  }
> > -
> > -  // If the default constructor is explicitly defaulted, checking the
> exception
> > -  // specification is deferred until now.
> > -  if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() &&
> > -      !ClassDecl->isDependentType())
> > -    CheckExplicitlyDefaultedSpecialMember(CtorDecl);
> > +  if (!ClassDecl->isDependentType())
> > +    CheckExplicitlyDefaultedMethods(ClassDecl);
> >  }
> >
> >  void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) {
> > @@ -7065,7 +7067,9 @@
> >  }
> >
> >  Sema::ImplicitExceptionSpecification
> > -Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
> > +Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> > +
> >    // C++ [except.spec]p14:
> >    //   An implicitly declared special member function (Clause 12) shall
> have
> >    //   an exception-specification.
> > @@ -7112,14 +7116,8 @@
> >    //   If a class has no user-declared destructor, a destructor is
> >    //   declared implicitly. An implicitly-declared destructor is an
> >    //   inline public member of its class.
> > -
> > -  ImplicitExceptionSpecification Spec =
> > -      ComputeDefaultedDtorExceptionSpec(ClassDecl);
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> >
> >    // Create the actual destructor declaration.
> > -  QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI);
> > -
> >    CanQualType ClassType
> >      = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
> >    SourceLocation ClassLoc = ClassDecl->getLocation();
> > @@ -7127,24 +7125,27 @@
> >      = Context.DeclarationNames.getCXXDestructorName(ClassType);
> >    DeclarationNameInfo NameInfo(Name, ClassLoc);
> >    CXXDestructorDecl *Destructor
> > -      = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc,
> NameInfo, Ty, 0,
> > -                                  /*isInline=*/true,
> > +      = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc,
> NameInfo,
> > +                                  QualType(), 0, /*isInline=*/true,
> >                                    /*isImplicitlyDeclared=*/true);
> >    Destructor->setAccess(AS_public);
> >    Destructor->setDefaulted();
> >    Destructor->setImplicit();
> >    Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
> > -
> > +
> > +  // Build an exception specification pointing back at this destructor.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = Destructor;
> > +  Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0,
> EPI));
> > +
> >    // Note that we have declared this destructor.
> >    ++ASTContext::NumImplicitDestructorsDeclared;
> > -
> > +
> >    // Introduce this destructor into its scope.
> >    if (Scope *S = getScopeForContext(ClassDecl))
> >      PushOnScopeChains(Destructor, S, false);
> >    ClassDecl->addDecl(Destructor);
> > -
> > -  // This could be uniqued if it ever proves significant.
> > -  Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty));
> >
> >    AddOverriddenMethods(ClassDecl, Destructor);
> >
> > @@ -7194,15 +7195,6 @@
> >  /// \brief Perform any semantic analysis which needs to be delayed
> until all
> >  /// pending class member declarations have been parsed.
> >  void Sema::ActOnFinishCXXMemberDecls() {
> > -  // Now we have parsed all exception specifications, determine the
> implicit
> > -  // exception specifications for destructors.
> > -  for (unsigned i = 0, e = DelayedDestructorExceptionSpecs.size();
> > -       i != e; ++i) {
> > -    CXXDestructorDecl *Dtor = DelayedDestructorExceptionSpecs[i];
> > -    AdjustDestructorExceptionSpec(Dtor->getParent(), Dtor, true);
> > -  }
> > -  DelayedDestructorExceptionSpecs.clear();
> > -
> >    // Perform any deferred checking of exception specifications for
> virtual
> >    // destructors.
> >    for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size();
> > @@ -7217,44 +7209,33 @@
> >    DelayedDestructorExceptionSpecChecks.clear();
> >  }
> >
> > -void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,
> > -                                         CXXDestructorDecl *destructor,
> > -                                         bool WasDelayed) {
> > +void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
> > +                                         CXXDestructorDecl *Destructor)
> {
> > +  assert(getLangOpts().CPlusPlus0x &&
> > +         "adjusting dtor exception specs was introduced in c++11");
> > +
> >    // C++11 [class.dtor]p3:
> >    //   A declaration of a destructor that does not have an exception-
> >    //   specification is implicitly considered to have the same
> exception-
> >    //   specification as an implicit declaration.
> > -  const FunctionProtoType *dtorType = destructor->getType()->
> > +  const FunctionProtoType *DtorType = Destructor->getType()->
> >                                          getAs<FunctionProtoType>();
> > -  if (!WasDelayed && dtorType->hasExceptionSpec())
> > +  if (DtorType->hasExceptionSpec())
> >      return;
> >
> > -  ImplicitExceptionSpecification exceptSpec =
> > -      ComputeDefaultedDtorExceptionSpec(classDecl);
> > -
> >    // Replace the destructor's type, building off the existing one.
> Fortunately,
> >    // the only thing of interest in the destructor type is its extended
> info.
> >    // The return and arguments are fixed.
> > -  FunctionProtoType::ExtProtoInfo epi = dtorType->getExtProtoInfo();
> > -  epi.ExceptionSpecType = exceptSpec.getExceptionSpecType();
> > -  epi.NumExceptions = exceptSpec.size();
> > -  epi.Exceptions = exceptSpec.data();
> > -  QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi);
> > -
> > -  destructor->setType(ty);
> > -
> > -  // If we can't compute the exception specification for this
> destructor yet
> > -  // (because it depends on an exception specification which we have
> not parsed
> > -  // yet), make a note that we need to try again when the class is
> complete.
> > -  if (epi.ExceptionSpecType == EST_Delayed) {
> > -    assert(!WasDelayed && "couldn't compute destructor exception spec");
> > -    DelayedDestructorExceptionSpecs.push_back(destructor);
> > -  }
> > +  FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo();
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = Destructor;
> > +  Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0,
> EPI));
> >
> >    // FIXME: If the destructor has a body that could throw, and the
> newly created
> >    // spec doesn't allow exceptions, we should emit a warning, because
> this
> >    // change in behavior can break conforming C++03 programs at runtime.
> > -  // However, we don't have a body yet, so it needs to be done
> somewhere else.
> > +  // However, we don't have a body or an exception specification yet,
> so it
> > +  // needs to be done somewhere else.
> >  }
> >
> >  /// \brief Builds a statement that copies/moves the given entity from
> \p From to
> > @@ -7456,11 +7437,13 @@
> >                          Loc, Copy.take());
> >  }
> >
> > -std::pair<Sema::ImplicitExceptionSpecification, bool>
> > -Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
> > -                                                   CXXRecordDecl
> *ClassDecl) {
> > +/// Determine whether an implicit copy assignment operator for
> ClassDecl has a
> > +/// const argument.
> > +/// FIXME: It ought to be possible to store this on the record.
> > +static bool isImplicitCopyAssignmentArgConst(Sema &S,
> > +                                             CXXRecordDecl *ClassDecl) {
> >    if (ClassDecl->isInvalidDecl())
> > -    return std::make_pair(ImplicitExceptionSpecification(*this), true);
> > +    return true;
> >
> >    // C++ [class.copy]p10:
> >    //   If the class definition does not explicitly declare a copy
> > @@ -7471,37 +7454,34 @@
> >    //       X& X::operator=(const X&)
> >    //
> >    //   if
> > -  bool HasConstCopyAssignment = true;
> > -
> >    //       -- each direct base class B of X has a copy assignment
> operator
> >    //          whose parameter is of type const B&, const volatile B& or
> B,
> >    //          and
> >    for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->bases_begin(),
> >                                         BaseEnd = ClassDecl->bases_end();
> > -       HasConstCopyAssignment && Base != BaseEnd; ++Base) {
> > +       Base != BaseEnd; ++Base) {
> >      // We'll handle this below
> > -    if (LangOpts.CPlusPlus0x && Base->isVirtual())
> > +    if (S.getLangOpts().CPlusPlus0x && Base->isVirtual())
> >        continue;
> >
> >      assert(!Base->getType()->isDependentType() &&
> >             "Cannot generate implicit members for class with dependent
> bases.");
> >      CXXRecordDecl *BaseClassDecl =
> Base->getType()->getAsCXXRecordDecl();
> > -    HasConstCopyAssignment &=
> > -      (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
> > -                                    false, 0);
> > +    if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
> false, 0))
> > +      return false;
> >    }
> >
> >    // In C++11, the above citation has "or virtual" added
> > -  if (LangOpts.CPlusPlus0x) {
> > +  if (S.getLangOpts().CPlusPlus0x) {
> >      for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->vbases_begin(),
> >                                           BaseEnd =
> ClassDecl->vbases_end();
> > -         HasConstCopyAssignment && Base != BaseEnd; ++Base) {
> > +         Base != BaseEnd; ++Base) {
> >        assert(!Base->getType()->isDependentType() &&
> >               "Cannot generate implicit members for class with dependent
> bases.");
> >        CXXRecordDecl *BaseClassDecl =
> Base->getType()->getAsCXXRecordDecl();
> > -      HasConstCopyAssignment &=
> > -        (bool)LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
> > -                                      false, 0);
> > +      if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const,
> > +                                     false, 0))
> > +        return false;
> >      }
> >    }
> >
> > @@ -7511,23 +7491,36 @@
> >    //          const volatile M& or M.
> >    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
> >                                    FieldEnd = ClassDecl->field_end();
> > -       HasConstCopyAssignment && Field != FieldEnd;
> > -       ++Field) {
> > -    QualType FieldType = Context.getBaseElementType(Field->getType());
> > -    if (CXXRecordDecl *FieldClassDecl =
> FieldType->getAsCXXRecordDecl()) {
> > -      HasConstCopyAssignment &=
> > -        (bool)LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const,
> > -                                      false, 0);
> > -    }
> > +       Field != FieldEnd; ++Field) {
> > +    QualType FieldType = S.Context.getBaseElementType(Field->getType());
> > +    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl())
> > +      if (!S.LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const,
> > +                                     false, 0))
> > +        return false;
> >    }
> >
> >    //   Otherwise, the implicitly declared copy assignment operator will
> >    //   have the form
> >    //
> >    //       X& X::operator=(X&)
> > -
> > +
> > +  return true;
> > +}
> > +
> > +Sema::ImplicitExceptionSpecification
> > +Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> > +
> > +  ImplicitExceptionSpecification ExceptSpec(*this);
> > +  if (ClassDecl->isInvalidDecl())
> > +    return ExceptSpec;
> > +
> > +  const FunctionProtoType *T =
> MD->getType()->castAs<FunctionProtoType>();
> > +  assert(T->getNumArgs() == 1 && "not a copy assignment op");
> > +  unsigned ArgQuals =
> T->getArgType(0).getNonReferenceType().getCVRQualifiers();
> > +
> >    // C++ [except.spec]p14:
> > -  //   An implicitly declared special member function (Clause 12) shall
> have an
> > +  //   An implicitly declared special member function (Clause 12) shall
> have an
> >    //   exception-specification. [...]
> >
> >    // It is unspecified whether or not an implicit copy assignment
> operator
> > @@ -7536,8 +7529,6 @@
> >    // Based on a similar decision made for constness in C++0x, we're
> erring on
> >    // the side of assuming such calls to be made regardless of whether
> they
> >    // actually happen.
> > -  ImplicitExceptionSpecification ExceptSpec(*this);
> > -  unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
> >    for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->bases_begin(),
> >                                         BaseEnd = ClassDecl->bases_end();
> >         Base != BaseEnd; ++Base) {
> > @@ -7575,7 +7566,7 @@
> >      }
> >    }
> >
> > -  return std::make_pair(ExceptSpec, HasConstCopyAssignment);
> > +  return ExceptSpec;
> >  }
> >
> >  CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl
> *ClassDecl) {
> > @@ -7584,26 +7575,19 @@
> >    // for determining the argument type of the operator. Note also that
> >    // operators taking an object instead of a reference are allowed.
> >
> > -  ImplicitExceptionSpecification Spec(*this);
> > -  bool Const;
> > -  llvm::tie(Spec, Const) =
> > -    ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
> > -
> >    QualType ArgType = Context.getTypeDeclType(ClassDecl);
> >    QualType RetType = Context.getLValueReferenceType(ArgType);
> > -  if (Const)
> > +  if (isImplicitCopyAssignmentArgConst(*this, ClassDecl))
> >      ArgType = ArgType.withConst();
> >    ArgType = Context.getLValueReferenceType(ArgType);
> >
> >    //   An implicitly-declared copy assignment operator is an inline
> public
> >    //   member of its class.
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> >    DeclarationName Name =
> Context.DeclarationNames.getCXXOperatorName(OO_Equal);
> >    SourceLocation ClassLoc = ClassDecl->getLocation();
> >    DeclarationNameInfo NameInfo(Name, ClassLoc);
> >    CXXMethodDecl *CopyAssignment
> > -    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
> > -                            Context.getFunctionType(RetType, &ArgType,
> 1, EPI),
> > +    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
> QualType(),
> >                              /*TInfo=*/0, /*isStatic=*/false,
> >                              /*StorageClassAsWritten=*/SC_None,
> >                              /*isInline=*/true, /*isConstexpr=*/false,
> > @@ -7612,7 +7596,13 @@
> >    CopyAssignment->setDefaulted();
> >    CopyAssignment->setImplicit();
> >    CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());
> > -
> > +
> > +  // Build an exception specification pointing back at this member.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = CopyAssignment;
> > +  CopyAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1,
> EPI));
> > +
> >    // Add the parameter to the operator.
> >    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
> >                                                 ClassLoc, ClassLoc,
> /*Id=*/0,
> > @@ -7950,9 +7940,10 @@
> >  }
> >
> >  Sema::ImplicitExceptionSpecification
> > -Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl
> *ClassDecl) {
> > -  ImplicitExceptionSpecification ExceptSpec(*this);
> > +Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> >
> > +  ImplicitExceptionSpecification ExceptSpec(*this);
> >    if (ClassDecl->isInvalidDecl())
> >      return ExceptSpec;
> >
> > @@ -8120,22 +8111,17 @@
> >    // Note: The following rules are largely analoguous to the move
> >    // constructor rules.
> >
> > -  ImplicitExceptionSpecification Spec(
> > -      ComputeDefaultedMoveAssignmentExceptionSpec(ClassDecl));
> > -
> >    QualType ArgType = Context.getTypeDeclType(ClassDecl);
> >    QualType RetType = Context.getLValueReferenceType(ArgType);
> >    ArgType = Context.getRValueReferenceType(ArgType);
> >
> >    //   An implicitly-declared move assignment operator is an inline
> public
> >    //   member of its class.
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> >    DeclarationName Name =
> Context.DeclarationNames.getCXXOperatorName(OO_Equal);
> >    SourceLocation ClassLoc = ClassDecl->getLocation();
> >    DeclarationNameInfo NameInfo(Name, ClassLoc);
> >    CXXMethodDecl *MoveAssignment
> > -    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
> > -                            Context.getFunctionType(RetType, &ArgType,
> 1, EPI),
> > +    = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
> QualType(),
> >                              /*TInfo=*/0, /*isStatic=*/false,
> >                              /*StorageClassAsWritten=*/SC_None,
> >                              /*isInline=*/true,
> > @@ -8146,6 +8132,12 @@
> >    MoveAssignment->setImplicit();
> >    MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment());
> >
> > +  // Build an exception specification pointing back at this member.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = MoveAssignment;
> > +  MoveAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1,
> EPI));
> > +
> >    // Add the parameter to the operator.
> >    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
> >                                                 ClassLoc, ClassLoc,
> /*Id=*/0,
> > @@ -8496,10 +8488,12 @@
> >    }
> >  }
> >
> > -std::pair<Sema::ImplicitExceptionSpecification, bool>
> > -Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl
> *ClassDecl) {
> > +/// Determine whether an implicit copy constructor for ClassDecl has a
> const
> > +/// argument.
> > +/// FIXME: It ought to be possible to store this on the record.
> > +static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl
> *ClassDecl) {
> >    if (ClassDecl->isInvalidDecl())
> > -    return std::make_pair(ImplicitExceptionSpecification(*this), true);
> > +    return true;
> >
> >    // C++ [class.copy]p5:
> >    //   The implicitly-declared copy constructor for a class X will
> > @@ -8508,60 +8502,71 @@
> >    //       X::X(const X&)
> >    //
> >    //   if
> > -  // FIXME: It ought to be possible to store this on the record.
> > -  bool HasConstCopyConstructor = true;
> > -
> >    //     -- each direct or virtual base class B of X has a copy
> >    //        constructor whose first parameter is of type const B& or
> >    //        const volatile B&, and
> >    for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->bases_begin(),
> >                                         BaseEnd = ClassDecl->bases_end();
> > -       HasConstCopyConstructor && Base != BaseEnd;
> > -       ++Base) {
> > +       Base != BaseEnd; ++Base) {
> >      // Virtual bases are handled below.
> >      if (Base->isVirtual())
> >        continue;
> > -
> > +
> >      CXXRecordDecl *BaseClassDecl
> >        =
> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
> > -    HasConstCopyConstructor &=
> > -      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);
> > +    // FIXME: This lookup is wrong. If the copy ctor for a member or
> base is
> > +    // ambiguous, we should still produce a constructor with a
> const-qualified
> > +    // parameter.
> > +    if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const))
> > +      return false;
> >    }
> >
> >    for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->vbases_begin(),
> >                                         BaseEnd =
> ClassDecl->vbases_end();
> > -       HasConstCopyConstructor && Base != BaseEnd;
> > -       ++Base) {
> > +       Base != BaseEnd; ++Base) {
> >      CXXRecordDecl *BaseClassDecl
> >        =
> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
> > -    HasConstCopyConstructor &=
> > -      (bool)LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const);
> > +    if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const))
> > +      return false;
> >    }
> > -
> > +
> >    //     -- for all the nonstatic data members of X that are of a
> >    //        class type M (or array thereof), each such class type
> >    //        has a copy constructor whose first parameter is of type
> >    //        const M& or const volatile M&.
> >    for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
> >                                    FieldEnd = ClassDecl->field_end();
> > -       HasConstCopyConstructor && Field != FieldEnd;
> > -       ++Field) {
> > -    QualType FieldType = Context.getBaseElementType(Field->getType());
> > +       Field != FieldEnd; ++Field) {
> > +    QualType FieldType = S.Context.getBaseElementType(Field->getType());
> >      if (CXXRecordDecl *FieldClassDecl =
> FieldType->getAsCXXRecordDecl()) {
> > -      HasConstCopyConstructor &=
> > -        (bool)LookupCopyingConstructor(FieldClassDecl,
> Qualifiers::Const);
> > +      if (!S.LookupCopyingConstructor(FieldClassDecl,
> Qualifiers::Const))
> > +        return false;
> >      }
> >    }
> > +
> >    //   Otherwise, the implicitly declared copy constructor will have
> >    //   the form
> >    //
> >    //       X::X(X&)
> > -
> > +
> > +  return true;
> > +}
> > +
> > +Sema::ImplicitExceptionSpecification
> > +Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> > +
> > +  ImplicitExceptionSpecification ExceptSpec(*this);
> > +  if (ClassDecl->isInvalidDecl())
> > +    return ExceptSpec;
> > +
> > +  const FunctionProtoType *T =
> MD->getType()->castAs<FunctionProtoType>();
> > +  assert(T->getNumArgs() >= 1 && "not a copy ctor");
> > +  unsigned Quals =
> T->getArgType(0).getNonReferenceType().getCVRQualifiers();
> > +
> >    // C++ [except.spec]p14:
> >    //   An implicitly declared special member function (Clause 12) shall
> have an
> >    //   exception-specification. [...]
> > -  ImplicitExceptionSpecification ExceptSpec(*this);
> > -  unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
> >    for (CXXRecordDecl::base_class_iterator Base =
> ClassDecl->bases_begin(),
> >                                         BaseEnd = ClassDecl->bases_end();
> >         Base != BaseEnd;
> > @@ -8599,7 +8604,7 @@
> >      }
> >    }
> >
> > -  return std::make_pair(ExceptSpec, HasConstCopyConstructor);
> > +  return ExceptSpec;
> >  }
> >
> >  CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
> > @@ -8608,18 +8613,12 @@
> >    //   If the class definition does not explicitly declare a copy
> >    //   constructor, one is declared implicitly.
> >
> > -  ImplicitExceptionSpecification Spec(*this);
> > -  bool Const;
> > -  llvm::tie(Spec, Const) =
> > -    ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
> > -
> >    QualType ClassType = Context.getTypeDeclType(ClassDecl);
> >    QualType ArgType = ClassType;
> > +  bool Const = isImplicitCopyCtorArgConst(*this, ClassDecl);
> >    if (Const)
> >      ArgType = ArgType.withConst();
> >    ArgType = Context.getLValueReferenceType(ArgType);
> > -
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> >
> >    bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
> >                                                       CXXCopyConstructor,
> > @@ -8634,14 +8633,20 @@
> >    //   An implicitly-declared copy constructor is an inline public
> >    //   member of its class.
> >    CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
> > -      Context, ClassDecl, ClassLoc, NameInfo,
> > -      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI),
> /*TInfo=*/0,
> > +      Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
> >        /*isExplicit=*/false, /*isInline=*/true,
> /*isImplicitlyDeclared=*/true,
> >        Constexpr);
> >    CopyConstructor->setAccess(AS_public);
> >    CopyConstructor->setDefaulted();
> >    CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor());
> >
> > +  // Build an exception specification pointing back at this member.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = CopyConstructor;
> > +  CopyConstructor->setType(
> > +      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
> > +
> >    // Note that we have declared this constructor.
> >    ++ASTContext::NumImplicitCopyConstructorsDeclared;
> >
> > @@ -8705,7 +8710,9 @@
> >  }
> >
> >  Sema::ImplicitExceptionSpecification
> > -Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
> > +Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) {
> > +  CXXRecordDecl *ClassDecl = MD->getParent();
> > +
> >    // C++ [except.spec]p14:
> >    //   An implicitly declared special member function (Clause 12) shall
> have an
> >    //   exception-specification. [...]
> > @@ -8788,13 +8795,8 @@
> >      return 0;
> >    }
> >
> > -  ImplicitExceptionSpecification Spec(
> > -      ComputeDefaultedMoveCtorExceptionSpec(ClassDecl));
> > -
> >    QualType ClassType = Context.getTypeDeclType(ClassDecl);
> >    QualType ArgType = Context.getRValueReferenceType(ClassType);
> > -
> > -  FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
> >
> >    bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
> >                                                       CXXMoveConstructor,
> > @@ -8810,14 +8812,20 @@
> >    //   An implicitly-declared copy/move constructor is an inline public
> >    //   member of its class.
> >    CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
> > -      Context, ClassDecl, ClassLoc, NameInfo,
> > -      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI),
> /*TInfo=*/0,
> > +      Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/0,
> >        /*isExplicit=*/false, /*isInline=*/true,
> /*isImplicitlyDeclared=*/true,
> >        Constexpr);
> >    MoveConstructor->setAccess(AS_public);
> >    MoveConstructor->setDefaulted();
> >    MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor());
> >
> > +  // Build an exception specification pointing back at this member.
> > +  FunctionProtoType::ExtProtoInfo EPI;
> > +  EPI.ExceptionSpecType = EST_Unevaluated;
> > +  EPI.ExceptionSpecDecl = MoveConstructor;
> > +  MoveConstructor->setType(
> > +      Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI));
> > +
> >    // Add the parameter to the constructor.
> >    ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
> >                                                 ClassLoc, ClassLoc,
> > @@ -10427,10 +10435,11 @@
> >      if (Primary == Primary->getCanonicalDecl())
> >        return;
> >
> > +    CheckExplicitlyDefaultedSpecialMember(MD);
> > +
> >      switch (Member) {
> >      case CXXDefaultConstructor: {
> >        CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
> > -      CheckExplicitlyDefaultedSpecialMember(CD);
> >        if (!CD->isInvalidDecl())
> >          DefineImplicitDefaultConstructor(DefaultLoc, CD);
> >        break;
> > @@ -10438,14 +10447,12 @@
> >
> >      case CXXCopyConstructor: {
> >        CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
> > -      CheckExplicitlyDefaultedSpecialMember(CD);
> >        if (!CD->isInvalidDecl())
> >          DefineImplicitCopyConstructor(DefaultLoc, CD);
> >        break;
> >      }
> >
> >      case CXXCopyAssignment: {
> > -      CheckExplicitlyDefaultedSpecialMember(MD);
> >        if (!MD->isInvalidDecl())
> >          DefineImplicitCopyAssignment(DefaultLoc, MD);
> >        break;
> > @@ -10453,7 +10460,6 @@
> >
> >      case CXXDestructor: {
> >        CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD);
> > -      CheckExplicitlyDefaultedSpecialMember(DD);
> >        if (!DD->isInvalidDecl())
> >          DefineImplicitDestructor(DefaultLoc, DD);
> >        break;
> > @@ -10461,14 +10467,12 @@
> >
> >      case CXXMoveConstructor: {
> >        CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD);
> > -      CheckExplicitlyDefaultedSpecialMember(CD);
> >        if (!CD->isInvalidDecl())
> >          DefineImplicitMoveConstructor(DefaultLoc, CD);
> >        break;
> >      }
> >
> >      case CXXMoveAssignment: {
> > -      CheckExplicitlyDefaultedSpecialMember(MD);
> >        if (!MD->isInvalidDecl())
> >          DefineImplicitMoveAssignment(DefaultLoc, MD);
> >        break;
> > @@ -10753,7 +10757,7 @@
> >
> >    // Note: The VTableUses vector could grow as a result of marking
> >    // the members of a class as "used", so we check the size each
> > -  // time through the loop and prefer indices (with are stable) to
> > +  // time through the loop and prefer indices (which are stable) to
> >    // iterators (which are not).
> >    bool DefinedAnything = false;
> >    for (unsigned I = 0; I != VTableUses.size(); ++I) {
> > @@ -10763,6 +10767,8 @@
> >
> >      SourceLocation Loc = VTableUses[I].second;
> >
> > +    bool DefineVTable = true;
> > +
> >      // If this class has a key function, but that key function is
> >      // defined in another translation unit, we don't need to emit the
> >      // vtable even though we're using it.
> > @@ -10773,7 +10779,8 @@
> >        case TSK_ExplicitSpecialization:
> >        case TSK_ExplicitInstantiationDeclaration:
> >          // The key function is in another translation unit.
> > -        continue;
> > +        DefineVTable = false;
> > +        break;
> >
> >        case TSK_ExplicitInstantiationDefinition:
> >        case TSK_ImplicitInstantiation:
> > @@ -10802,7 +10809,15 @@
> >        }
> >
> >        if (IsExplicitInstantiationDeclaration)
> > -        continue;
> > +        DefineVTable = false;
> > +    }
> > +
> > +    // The exception specifications for all virtual members may be
> needed even
> > +    // if we are not providing an authoritative form of the vtable in
> this TU.
> > +    // We may choose to emit it available_externally anyway.
> > +    if (!DefineVTable) {
> > +      MarkVirtualMemberExceptionSpecsNeeded(Loc, Class);
> > +      continue;
> >      }
> >
> >      // Mark all of the virtual members of this class as referenced, so
> > @@ -10831,6 +10846,14 @@
> >    return DefinedAnything;
> >  }
> >
> > +void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
> > +                                                 const CXXRecordDecl
> *RD) {
> > +  for (CXXRecordDecl::method_iterator I = RD->method_begin(),
> > +                                      E = RD->method_end(); I != E; ++I)
> > +    if ((*I)->isVirtual() && !(*I)->isPure())
> > +      ResolveExceptionSpec(Loc,
> (*I)->getType()->castAs<FunctionProtoType>());
> > +}
> > +
> >  void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
> >                                          const CXXRecordDecl *RD) {
> >    // Mark all functions which will appear in RD's vtable as used.
> > @@ -11067,8 +11090,8 @@
> >
> >    switch (Proto->getExceptionSpecType()) {
> >    case EST_Uninstantiated:
> > +  case EST_Unevaluated:
> >    case EST_BasicNoexcept:
> > -  case EST_Delayed:
> >    case EST_DynamicNone:
> >    case EST_MSAny:
> >    case EST_None:
> >
> > Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Thu Jul 26 23:22:15 2012
> > @@ -100,20 +100,22 @@
> >
> >  const FunctionProtoType *
> >  Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType
> *FPT) {
> > -  // FIXME: If FD is a special member, we should delay computing its
> exception
> > -  // specification until this point.
> > -  if (FPT->getExceptionSpecType() != EST_Uninstantiated)
> > +  if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
> >      return FPT;
> >
> >    FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
> >    const FunctionProtoType *SourceFPT =
> >        SourceDecl->getType()->castAs<FunctionProtoType>();
> >
> > -  if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
> > +  // If the exception specification has already been resolved, just
> return it.
> > +  if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType()))
> >      return SourceFPT;
> >
> > -  // Instantiate the exception specification now.
> > -  InstantiateExceptionSpec(Loc, SourceDecl);
> > +  // Compute or instantiate the exception specification now.
> > +  if (FPT->getExceptionSpecType() == EST_Unevaluated)
> > +    EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl));
> > +  else
> > +    InstantiateExceptionSpec(Loc, SourceDecl);
> >
> >    return SourceDecl->getType()->castAs<FunctionProtoType>();
> >  }
> > @@ -346,8 +348,8 @@
> >    ExceptionSpecificationType OldEST = Old->getExceptionSpecType();
> >    ExceptionSpecificationType NewEST = New->getExceptionSpecType();
> >
> > -  assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
> > -         OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
> > +  assert(!isUnresolvedExceptionSpec(OldEST) &&
> > +         !isUnresolvedExceptionSpec(NewEST) &&
> >           "Shouldn't see unknown exception specifications here");
> >
> >    // Shortcut the case where both have no spec.
> > @@ -544,8 +546,8 @@
> >
> >    ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
> >
> > -  assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
> > -         SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated
> &&
> > +  assert(!isUnresolvedExceptionSpec(SuperEST) &&
> > +         !isUnresolvedExceptionSpec(SubEST) &&
> >           "Shouldn't see unknown exception specifications here");
> >
> >    // It does not. If the subset contains everything, we've failed.
> > @@ -808,15 +810,6 @@
> >    if (!FT)
> >      return CT_Can;
> >
> > -  if (FT->getExceptionSpecType() == EST_Delayed) {
> > -    // FIXME: Try to resolve a delayed exception spec in
> ResolveExceptionSpec.
> > -    assert(isa<CXXConstructorDecl>(D) &&
> > -           "only constructor exception specs can be unknown");
> > -    S.Diag(E->getLocStart(), diag::err_exception_spec_unknown)
> > -      << E->getSourceRange();
> > -    return CT_Can;
> > -  }
> > -
> >    return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
> >  }
> >
> >
> > Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 26 23:22:15 2012
> > @@ -10224,11 +10224,11 @@
> >    // FIXME: Is this really right?
> >    if (CurContext == Func) return;
> >
> > -  // Instantiate the exception specification for any function which is
> > +  // Resolve the exception specification for any function which is
> >    // used: CodeGen will need it.
> >    const FunctionProtoType *FPT =
> Func->getType()->getAs<FunctionProtoType>();
> > -  if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated)
> > -    InstantiateExceptionSpec(Loc, Func);
> > +  if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
> > +    ResolveExceptionSpec(Loc, FPT);
> >
> >    // Implicit instantiation of function templates and member functions
> of
> >    // class templates.
> >
> > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jul 26 23:22:15 2012
> > @@ -3190,8 +3190,6 @@
> >              CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
> >              if (!CPT)
> >                return false;
> > -            if (CPT->getExceptionSpecType() == EST_Delayed)
> > -              return false;
> >              if (!CPT->isNothrow(Self.Context))
> >                return false;
> >            }
> > @@ -3232,8 +3230,6 @@
> >            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
> >            if (!CPT)
> >              return false;
> > -          if (CPT->getExceptionSpecType() == EST_Delayed)
> > -            return false;
> >            // FIXME: check whether evaluating default arguments can
> throw.
> >            // For now, we'll be conservative and assume that they can
> throw.
> >            if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1)
> > @@ -3270,8 +3266,6 @@
> >            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
> >            if (!CPT)
> >              return false;
> > -          if (CPT->getExceptionSpecType() == EST_Delayed)
> > -            return false;
> >            // TODO: check whether evaluating default arguments can throw.
> >            // For now, we'll be conservative and assume that they can
> throw.
> >            return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0;
> >
> > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jul 26 23:22:15
> 2012
> > @@ -1996,8 +1996,7 @@
> >    Instantiator.disableLateAttributeInstantiation();
> >    LateAttrs.clear();
> >
> > -  if (!FieldsWithMemberInitializers.empty())
> > -    ActOnFinishDelayedMemberInitializers(Instantiation);
> > +  ActOnFinishDelayedMemberInitializers(Instantiation);
> >
> >    if (TSK == TSK_ImplicitInstantiation) {
> >      Instantiation->setLocation(Pattern->getLocation());
> >
> > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jul 26
> 23:22:15 2012
> > @@ -2395,8 +2395,17 @@
> >
> >    InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
> >
> InstantiatingTemplate::ExceptionSpecification());
> > -  if (Inst)
> > +  if (Inst) {
> > +    // We hit the instantiation depth limit. Clear the exception
> specification
> > +    // so that our callers don't have to cope with EST_Uninstantiated.
> > +    FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
> > +    EPI.ExceptionSpecType = EST_None;
> > +    Decl->setType(Context.getFunctionType(Proto->getResultType(),
> > +                                          Proto->arg_type_begin(),
> > +                                          Proto->getNumArgs(),
> > +                                          EPI));
> >      return;
> > +  }
> >
> >    // Enter the scope of this instantiation. We don't use
> >    // PushDeclContext because we don't have a scope.
> > @@ -2461,6 +2470,8 @@
> >        FunctionDecl *ExceptionSpecTemplate = Tmpl;
> >        if (EPI.ExceptionSpecType == EST_Uninstantiated)
> >          ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
> > +      assert(EPI.ExceptionSpecType != EST_Unevaluated &&
> > +             "instantiating implicitly-declared special member");
> >
> >        // Mark the function has having an uninstantiated exception
> specification.
> >        const FunctionProtoType *NewProto
> > @@ -3431,7 +3442,7 @@
> >  void Sema::PerformPendingInstantiations(bool LocalOnly) {
> >    // Load pending instantiations from the external source.
> >    if (!LocalOnly && ExternalSource) {
> > -    SmallVector<std::pair<ValueDecl *, SourceLocation>, 4> Pending;
> > +    SmallVector<PendingImplicitInstantiation, 4> Pending;
> >      ExternalSource->ReadPendingInstantiations(Pending);
> >      PendingInstantiations.insert(PendingInstantiations.begin(),
> >                                   Pending.begin(), Pending.end());
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Jul 26 23:22:15 2012
> > @@ -3906,6 +3906,8 @@
> >      } else if (EST == EST_Uninstantiated) {
> >        EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record,
> Idx);
> >        EPI.ExceptionSpecTemplate = ReadDeclAs<FunctionDecl>(*Loc.F,
> Record, Idx);
> > +    } else if (EST == EST_Unevaluated) {
> > +      EPI.ExceptionSpecDecl = ReadDeclAs<FunctionDecl>(*Loc.F, Record,
> Idx);
> >      }
> >      return Context.getFunctionType(ResultType, ParamTypes.data(),
> NumParams,
> >                                      EPI);
> >
> > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Jul 26 23:22:15 2012
> > @@ -198,6 +198,8 @@
> >    } else if (T->getExceptionSpecType() == EST_Uninstantiated) {
> >      Writer.AddDeclRef(T->getExceptionSpecDecl(), Record);
> >      Writer.AddDeclRef(T->getExceptionSpecTemplate(), Record);
> > +  } else if (T->getExceptionSpecType() == EST_Unevaluated) {
> > +    Writer.AddDeclRef(T->getExceptionSpecDecl(), Record);
> >    }
> >    Code = TYPE_FUNCTION_PROTO;
> >  }
> >
> > Modified:
> cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp
> (original)
> > +++
> cfe/trunk/test/CXX/dcl.decl/dcl.meaning/dcl.fct/dcl.fct.def.default/p1.cpp
> Thu Jul 26 23:22:15 2012
> > @@ -4,9 +4,11 @@
> >  // [...]
> >  //   -- not have default arguments
> >  struct DefArg {
> > +  static DefArg &&make();
> >    DefArg(int n = 5) = default; // expected-error {{an
> explicitly-defaulted constructor cannot have default arguments}}
> > -  DefArg(const DefArg &DA = DefArg(2)) = default; // expected-error
> {{an explicitly-defaulted constructor cannot have default arguments}}
> > +  DefArg(const DefArg &DA = make()) = default; // expected-error {{an
> explicitly-defaulted constructor cannot have default arguments}}
> >    DefArg(const DefArg &DA, int k = 3) = default; // expected-error {{an
> explicitly-defaulted copy constructor cannot have default arguments}}
> > +  DefArg(DefArg &&DA = make()) = default; // expected-error {{an
> explicitly-defaulted constructor cannot have default arguments}}
> >    DefArg(DefArg &&DA, int k = 3) = default; // expected-error {{an
> explicitly-defaulted move constructor cannot have default arguments}}
> >    DefArg &operator=(const DefArg&, int k = 4) = default; //
> expected-error {{parameter of overloaded 'operator=' cannot have a default
> argument}}
> >    DefArg &operator=(DefArg&&, int k = 4) = default; // expected-error
> {{parameter of overloaded 'operator=' cannot have a default argument}}
> >
> > Removed: cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp?rev=160846&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/member-init-ctor.cpp (removed)
> > @@ -1,14 +0,0 @@
> > -// RUN: %clang_cc1 %s -std=c++11 -emit-llvm -o - | FileCheck %s
> > -
> > -bool b();
> > -struct S {
> > -  int n = b() ? S().n + 1 : 0;
> > -};
> > -
> > -S s;
> > -
> > -// CHECK: define {{.*}} @_ZN1SC2Ev(
> > -// CHECK-NOT }
> > -// CHECK: call {{.*}} @_Z1bv()
> > -// CHECK-NOT }
> > -// CHECK: call {{.*}} @_ZN1SC1Ev(
> >
> > Modified: cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/cxx0x-defaulted-functions.cpp Thu Jul 26
> 23:22:15 2012
> > @@ -57,3 +57,63 @@
> >    friend S<bar>::S(const S&);
> >    friend S<bar>::S(S&&);
> >  };
> > +
> > +namespace DefaultedFnExceptionSpec {
> > +  // DR1330: The exception-specification of an implicitly-declared
> special
> > +  // member function is evaluated as needed.
> > +  template<typename T> T &&declval();
> > +  template<typename T> struct pair {
> > +    pair(const pair&) noexcept(noexcept(T(declval<T>())));
> > +  };
> > +
> > +  struct Y;
> > +  struct X { X(); X(const Y&); };
> > +  struct Y { pair<X> p; };
> > +
> > +  template<typename T>
> > +  struct A {
> > +    pair<T> p;
> > +  };
> > +  struct B {
> > +    B();
> > +    B(const A<B>&);
> > +  };
> > +
> > +  // Don't crash here.
> > +  void f() {
> > +    X x = X();
> > +    (void)noexcept(B(declval<B>()));
> > +  }
> > +
> > +  template<typename T>
> > +  struct Error {
> > +    // FIXME: Type canonicalization causes all the errors to point at
> the first
> > +    // declaration which has the type 'void () noexcept (T::error)'. We
> should
> > +    // get one error for 'Error<int>::Error()' and one for
> 'Error<int>::~Error()'.
> > +    void f() noexcept(T::error); // expected-error 2{{has no members}}
> > +
> > +    Error() noexcept(T::error);
> > +    Error(const Error&) noexcept(T::error);
> > +    Error(Error&&) noexcept(T::error);
> > +    Error &operator=(const Error&) noexcept(T::error);
> > +    Error &operator=(Error&&) noexcept(T::error);
> > +    ~Error() noexcept(T::error);
> > +  };
> > +
> > +  struct DelayImplicit {
> > +    Error<int> e;
> > +  };
> > +
> > +  // Don't instantiate the exception specification here.
> > +  void test1(decltype(declval<DelayImplicit>() =
> DelayImplicit(DelayImplicit())));
> > +  void test2(decltype(declval<DelayImplicit>() = declval<const
> DelayImplicit>()));
> > +  void test3(decltype(DelayImplicit(declval<const DelayImplicit>())));
> > +
> > +  // Any odr-use causes the exception specification to be evaluated.
> > +  struct OdrUse { // \
> > +    expected-note {{instantiation of exception specification for
> 'Error'}} \
> > +    expected-note {{instantiation of exception specification for
> '~Error'}}
> > +    Error<int> e;
> > +  };
> > +  OdrUse use; // expected-note {{implicit default constructor for
> 'DefaultedFnExceptionSpec::OdrUse' first required here}}
> > +}
> >
> > 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=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp Thu Jul 26
> 23:22:15 2012
> > @@ -17,7 +17,7 @@
> >    // is false.
> >    bool ThrowSomething() noexcept(false);
> >    struct ConstExpr {
> > -    bool b = noexcept(ConstExpr()) && ThrowSomething(); //
> expected-error {{exception specification is not available until end of
> class definition}}
> > +    bool b = noexcept(ConstExpr()) && ThrowSomething(); //
> expected-error {{cannot be used by non-static data member initializer}}
> >    };
> >    // We can use it now.
> >    bool w = noexcept(ConstExpr());
> > @@ -25,18 +25,27 @@
> >    // Much more obviously broken: we can't parse the initializer without
> already
> >    // knowing whether it produces a noexcept expression.
> >    struct TemplateArg {
> > -    int n = ExceptionIf<noexcept(TemplateArg())>::f(); //
> expected-error {{exception specification is not available until end of
> class definition}}
> > +    int n = ExceptionIf<noexcept(TemplateArg())>::f(); //
> expected-error {{cannot be used by non-static data member initializer}}
> >    };
> >    bool x = noexcept(TemplateArg());
> >
> >    // And within a nested class.
> > +  // FIXME: The diagnostic location is terrible here.
> >    struct Nested {
> >      struct Inner {
> > -      int n = ExceptionIf<noexcept(Nested())>::f(); // expected-error
> {{exception specification is not available until end of class definition}}
> > -    } inner;
> > +      int n = ExceptionIf<noexcept(Nested())>::f();
> > +    } inner; // expected-error {{cannot be used by non-static data
> member initializer}}
> >    };
> >    bool y = noexcept(Nested());
> >    bool z = noexcept(Nested::Inner());
> > +
> > +  struct Nested2 {
> > +    struct Inner;
> > +    int n = Inner().n; // expected-error {{cannot be used by non-static
> data member initializer}}
> > +    struct Inner {
> > +      int n = ExceptionIf<noexcept(Nested())>::f();
> > +    } inner;
> > +  };
> >  }
> >
> >  namespace ExceptionSpecification {
> >
> > Modified: cfe/trunk/test/SemaCXX/member-init.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-init.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/member-init.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/member-init.cpp Thu Jul 26 23:22:15 2012
> > @@ -14,7 +14,7 @@
> >  bool b();
> >  int k;
> >  struct Recurse {
> > -  int &n = b() ? Recurse().n : k; // ok
> > +  int &n = b() ? Recurse().n : k; // expected-error {{defaulted default
> constructor of 'Recurse' cannot be used by non-static data member
> initializer which appears before end of class definition}}
> >  };
> >
> >  struct UnknownBound {
> >
> > Modified: cfe/trunk/test/SemaCXX/type-traits.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaCXX/type-traits.cpp (original)
> > +++ cfe/trunk/test/SemaCXX/type-traits.cpp Thu Jul 26 23:22:15 2012
> > @@ -1384,9 +1384,6 @@
> >    { int arr[F(__has_nothrow_copy(cvoid))]; }
> >  }
> >
> > -template<bool b> struct assert_expr;
> > -template<> struct assert_expr<true> {};
> > -
> >  void has_nothrow_constructor() {
> >    { int arr[T(__has_nothrow_constructor(Int))]; }
> >    { int arr[T(__has_nothrow_constructor(IntAr))]; }
> > @@ -1415,11 +1412,6 @@
> >    { int arr[F(__has_nothrow_constructor(void))]; }
> >    { int arr[F(__has_nothrow_constructor(cvoid))]; }
> >    { int arr[F(__has_nothrow_constructor(HasTemplateCons))]; }
> > -
> > -  // While parsing an in-class initializer, the constructor is not
> known to be
> > -  // non-throwing yet.
> > -  struct HasInClassInit { int n =
> (assert_expr<!__has_nothrow_constructor(HasInClassInit)>(), 0); };
> > -  { int arr[T(__has_nothrow_constructor(HasInClassInit))]; }
> >  }
> >
> >  void has_virtual_destructor() {
> >
> > Modified: cfe/trunk/test/SemaTemplate/instantiation-depth.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiation-depth.cpp?rev=160847&r1=160846&r2=160847&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/SemaTemplate/instantiation-depth.cpp (original)
> > +++ cfe/trunk/test/SemaTemplate/instantiation-depth.cpp Thu Jul 26
> 23:22:15 2012
> > @@ -2,12 +2,30 @@
> >  // RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth-5
> -ftemplate-backtrace-limit=4 %s
> >  // RUN: %clang -fsyntax-only -Xclang -verify -ftemplate-depth=5
> -ftemplate-backtrace-limit=4 %s
> >
> > +#ifndef NOEXCEPT
> > +
> >  template<typename T> struct X : X<T*> { }; \
> >  // expected-error{{recursive template instantiation exceeded maximum
> depth of 5}} \
> >  // expected-note 3 {{instantiation of template class}} \
> >  // expected-note {{skipping 2 contexts in backtrace}} \
> >  // expected-note {{use -ftemplate-depth=N to increase recursive
> template instantiation depth}}
> >
> > -void test() {
> > +void test() {
> >    (void)sizeof(X<int>); // expected-note {{instantiation of template
> class}}
> >  }
> > +
> > +#else
> > +
> > +// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-depth 5
> -ftemplate-backtrace-limit 4 -std=c++11 -DNOEXCEPT %s
> > +
> > +template<typename T> struct S {
> > +  S() noexcept(noexcept(T()));
> > +};
> > +struct T : S<T> {}; \
> > +// expected-error{{recursive template instantiation exceeded maximum
> depth of 5}} \
> > +// expected-note 4 {{in instantiation of exception spec}} \
> > +// expected-note {{skipping 2 contexts in backtrace}} \
> > +// expected-note {{use -ftemplate-depth=N to increase recursive
> template instantiation depth}}
> > +T t; // expected-note {{implicit default constructor for 'T' first
> required here}}
> > +
> > +#endif
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120726/0cf01d77/attachment.html>


More information about the cfe-commits mailing list