[cfe-commits] r154886 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ lib/AST/ lib/Analysis/ lib/Sema/ test/CXX/except/except.spec/ test/CodeGenCXX/ test/SemaTemplate/

Richard Smith richard at metafoo.co.uk
Wed Apr 18 13:24:51 PDT 2012


Yes, this change was before the branch was cut.

On Wed, Apr 18, 2012 at 11:37 AM, Matthieu Monrocq <
matthieu.monrocq at gmail.com> wrote:

>
>
> Le 17 avril 2012 02:58, Richard Smith <richard-llvm at metafoo.co.uk> a
> écrit :
>
>> Author: rsmith
>> Date: Mon Apr 16 19:58:00 2012
>> New Revision: 154886
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=154886&view=rev
>> Log:
>> Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
>>
>> We have a new flavor of exception specification, EST_Uninstantiated. A
>> function
>> type with this exception specification carries a pointer to a
>> FunctionDecl, and
>> the exception specification for that FunctionDecl is instantiated (if
>> needed)
>> and used in the place of the function type's exception specification.
>>
>> When a function template declaration with a non-trivial exception
>> specification
>> is instantiated, the specialization's exception specification is set to
>> this
>> new 'uninstantiated' kind rather than being instantiated immediately.
>>
>> Expr::CanThrow has migrated onto Sema, so it can instantiate exception
>> specs
>> on-demand. Also, any odr-use of a function triggers the instantiation of
>> its
>> exception specification (the exception specification could be needed by
>> IRGen).
>> In passing, fix two places where a DeclRefExpr was created but the
>> corresponding
>> function was not actually marked odr-used. We used to get away with this,
>> but
>> don't any more.
>>
>> Also fix a bug where instantiating an exception specification which
>> refers to
>> function parameters resulted in a crash. We still have the same bug in
>> default
>> arguments, which I'll be looking into next.
>>
>> This, plus a tiny patch to fix libstdc++'s common_type, is enough for
>> clang to
>> parse (and, in very limited testing, support) all of libstdc++4.7's
>> standard
>> headers.
>>
>>
> Will it be available in Clang 3.1 ?
>
>
>> Added:
>>    cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
>>    cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
>> Modified:
>>    cfe/trunk/include/clang/AST/Expr.h
>>    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/Sema.h
>>    cfe/trunk/lib/AST/ASTContext.cpp
>>    cfe/trunk/lib/AST/Expr.cpp
>>    cfe/trunk/lib/AST/Type.cpp
>>    cfe/trunk/lib/Analysis/CFG.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/SemaOverload.cpp
>>    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
>>    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>>    cfe/trunk/lib/Sema/TreeTransform.h
>>    cfe/trunk/test/CXX/except/except.spec/p1.cpp
>>    cfe/trunk/test/SemaTemplate/instantiate-declref.cpp
>>
>> Modified: cfe/trunk/include/clang/AST/Expr.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/AST/Expr.h (original)
>> +++ cfe/trunk/include/clang/AST/Expr.h Mon Apr 16 19:58:00 2012
>> @@ -581,16 +581,6 @@
>>   /// member expression.
>>   static QualType findBoundMemberType(const Expr *expr);
>>
>> -  /// \brief Result type of CanThrow().
>> -  enum CanThrowResult {
>> -    CT_Cannot,
>> -    CT_Dependent,
>> -    CT_Can
>> -  };
>> -  /// \brief Test if this expression, if evaluated, might throw,
>> according to
>> -  ///        the rules of C++ [expr.unary.noexcept].
>> -  CanThrowResult CanThrow(ASTContext &C) const;
>> -
>>   /// IgnoreImpCasts - Skip past any implicit casts which might
>>   /// surround this expression.  Only skips ImplicitCastExprs.
>>   Expr *IgnoreImpCasts() LLVM_READONLY;
>>
>> Modified: cfe/trunk/include/clang/AST/Type.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/AST/Type.h (original)
>> +++ cfe/trunk/include/clang/AST/Type.h Mon Apr 16 19:58:00 2012
>> @@ -79,6 +79,7 @@
>>   class CXXRecordDecl;
>>   class EnumDecl;
>>   class FieldDecl;
>> +  class FunctionDecl;
>>   class ObjCInterfaceDecl;
>>   class ObjCProtocolDecl;
>>   class ObjCMethodDecl;
>> @@ -2700,7 +2701,8 @@
>>     ExtProtoInfo() :
>>       Variadic(false), HasTrailingReturn(false), TypeQuals(0),
>>       ExceptionSpecType(EST_None), RefQualifier(RQ_None),
>> -      NumExceptions(0), Exceptions(0), NoexceptExpr(0),
>> ConsumedArguments(0) {}
>> +      NumExceptions(0), Exceptions(0), NoexceptExpr(0),
>> ExceptionSpecDecl(0),
>> +      ConsumedArguments(0) {}
>>
>>     FunctionType::ExtInfo ExtInfo;
>>     bool Variadic : 1;
>> @@ -2711,6 +2713,7 @@
>>     unsigned NumExceptions;
>>     const QualType *Exceptions;
>>     Expr *NoexceptExpr;
>> +    FunctionDecl *ExceptionSpecDecl;
>>     const bool *ConsumedArguments;
>>   };
>>
>> @@ -2756,6 +2759,10 @@
>>   // NoexceptExpr - Instead of Exceptions, there may be a single Expr*
>> pointing
>>   // to the expression in the noexcept() specifier.
>>
>> +  // ExceptionSpecDecl - Instead of Exceptions, there may be a single
>> +  // FunctionDecl* pointing to the function which should be used to
>> resolve
>> +  // this function type's exception specification.
>> +
>>   // ConsumedArgs - A variable size array, following Exceptions
>>   // and of length NumArgs, holding flags indicating which arguments
>>   // are consumed.  This only appears if HasAnyConsumedArgs is true.
>> @@ -2795,6 +2802,8 @@
>>       EPI.Exceptions = exception_begin();
>>     } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
>>       EPI.NoexceptExpr = getNoexceptExpr();
>> +    } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
>> +      EPI.ExceptionSpecDecl = getExceptionSpecDecl();
>>     }
>>     if (hasAnyConsumedArgs())
>>       EPI.ConsumedArguments = getConsumedArgsBuffer();
>> @@ -2838,9 +2847,14 @@
>>     // NoexceptExpr sits where the arguments end.
>>     return *reinterpret_cast<Expr *const *>(arg_type_end());
>>   }
>> +  FunctionDecl *getExceptionSpecDecl() const {
>> +    if (getExceptionSpecType() != EST_Uninstantiated)
>> +      return 0;
>> +    return *reinterpret_cast<FunctionDecl * const *>(arg_type_end());
>> +  }
>>   bool isNothrow(ASTContext &Ctx) const {
>>     ExceptionSpecificationType EST = getExceptionSpecType();
>> -    assert(EST != EST_Delayed);
>> +    assert(EST != EST_Delayed && 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=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Apr 16
>> 19:58:00 2012
>> @@ -2583,6 +2583,8 @@
>>   "in instantiation of enumeration %q0 requested here">;
>>  def note_template_type_alias_instantiation_here : Note<
>>   "in instantiation of template type alias %0 requested here">;
>> +def note_template_exception_spec_instantiation_here : Note<
>> +  "in instantiation of exception specification for %0 requested here">;
>>
>>  def note_default_arg_instantiation_here : Note<
>>   "in instantiation of default argument for '%0' required here">;
>>
>> Modified: cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h (original)
>> +++ cfe/trunk/include/clang/Basic/ExceptionSpecificationType.h Mon Apr 16
>> 19:58:00 2012
>> @@ -16,7 +16,7 @@
>>
>>  namespace clang {
>>
>> -/// \brief The various types of exception specifications that exist in
>> C++0x.
>> +/// \brief The various types of exception specifications that exist in
>> C++11.
>>  enum ExceptionSpecificationType {
>>   EST_None,             ///< no exception specification
>>   EST_DynamicNone,      ///< throw()
>> @@ -24,7 +24,8 @@
>>   EST_MSAny,            ///< Microsoft throw(...) extension
>>   EST_BasicNoexcept,    ///< noexcept
>>   EST_ComputedNoexcept, ///< noexcept(expression)
>> -  EST_Delayed           ///< not known yet
>> +  EST_Delayed,          ///< not known yet
>> +  EST_Uninstantiated    ///< not instantiated yet
>>  };
>>
>>  inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType)
>> {
>> @@ -35,6 +36,19 @@
>>   return ESpecType == EST_BasicNoexcept || ESpecType ==
>> EST_ComputedNoexcept;
>>  }
>>
>> +/// \brief Possible results from evaluation of a noexcept expression.
>> +enum CanThrowResult {
>> +  CT_Cannot,
>> +  CT_Dependent,
>> +  CT_Can
>> +};
>> +
>> +inline CanThrowResult mergeCanThrow(CanThrowResult CT1, CanThrowResult
>> CT2) {
>> +  // CanThrowResult constants are ordered so that the maximum is the
>> correct
>> +  // merge result.
>> +  return CT1 > CT2 ? CT1 : CT2;
>> +}
>> +
>>  } // end namespace clang
>>
>>  #endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
>>
>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>> +++ cfe/trunk/include/clang/Sema/Sema.h Mon Apr 16 19:58:00 2012
>> @@ -907,6 +907,9 @@
>>   DeclarationNameInfo GetNameForDeclarator(Declarator &D);
>>   DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
>>   static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo
>> = 0);
>> +  CanThrowResult canThrow(const Expr *E);
>> +  const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
>> +                                                const FunctionProtoType
>> *FPT);
>>   bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
>>   bool CheckDistantExceptionSpec(QualType T);
>>   bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
>> @@ -3050,7 +3053,7 @@
>>   /// implicitly-declared special member functions.
>>   class ImplicitExceptionSpecification {
>>     // Pointer to allow copying
>> -    ASTContext *Context;
>> +    Sema *Self;
>>     // We order exception specifications thus:
>>     // noexcept is the most restrictive, but is only used in C++0x.
>>     // throw() comes next.
>> @@ -3074,9 +3077,9 @@
>>     }
>>
>>   public:
>> -    explicit ImplicitExceptionSpecification(ASTContext &Context)
>> -      : Context(&Context), ComputedEST(EST_BasicNoexcept) {
>> -      if (!Context.getLangOpts().CPlusPlus0x)
>> +    explicit ImplicitExceptionSpecification(Sema &Self)
>> +      : Self(&Self), ComputedEST(EST_BasicNoexcept) {
>> +      if (!Self.Context.getLangOpts().CPlusPlus0x)
>>         ComputedEST = EST_DynamicNone;
>>     }
>>
>> @@ -3094,7 +3097,7 @@
>>     const QualType *data() const { return Exceptions.data(); }
>>
>>     /// \brief Integrate another called method into the collected data.
>> -    void CalledDecl(CXXMethodDecl *Method);
>> +    void CalledDecl(SourceLocation CallLoc, CXXMethodDecl *Method);
>>
>>     /// \brief Integrate an invoked expression into the collected data.
>>     void CalledExpr(Expr *E);
>> @@ -5194,7 +5197,11 @@
>>
>>       /// We are checking the validity of a default template argument that
>>       /// has been used when naming a template-id.
>> -      DefaultTemplateArgumentChecking
>> +      DefaultTemplateArgumentChecking,
>> +
>> +      /// We are instantiating the exception specification for a function
>> +      /// template which was deferred until it was needed.
>> +      ExceptionSpecInstantiation
>>     } Kind;
>>
>>     /// \brief The point of instantiation within the source code.
>> @@ -5242,6 +5249,7 @@
>>
>>       switch (X.Kind) {
>>       case TemplateInstantiation:
>> +      case ExceptionSpecInstantiation:
>>         return true;
>>
>>       case PriorTemplateArgumentSubstitution:
>> @@ -5359,6 +5367,13 @@
>>                           Decl *Entity,
>>                           SourceRange InstantiationRange = SourceRange());
>>
>> +    struct ExceptionSpecification {};
>> +    /// \brief Note that we are instantiating an exception specification
>> +    /// of a function template.
>> +    InstantiatingTemplate(Sema &SemaRef, SourceLocation
>> PointOfInstantiation,
>> +                          FunctionDecl *Entity, ExceptionSpecification,
>> +                          SourceRange InstantiationRange =
>> SourceRange());
>> +
>>     /// \brief Note that we are instantiating a default argument in a
>>     /// template-id.
>>     InstantiatingTemplate(Sema &SemaRef, SourceLocation
>> PointOfInstantiation,
>> @@ -5658,6 +5673,8 @@
>>              TemplateArgumentListInfo &Result,
>>              const MultiLevelTemplateArgumentList &TemplateArgs);
>>
>> +  void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
>> +                                FunctionDecl *Function);
>>   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
>>                                      FunctionDecl *Function,
>>                                      bool Recursive = false,
>>
>> Modified: cfe/trunk/lib/AST/ASTContext.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
>> +++ cfe/trunk/lib/AST/ASTContext.cpp Mon Apr 16 19:58:00 2012
>> @@ -2194,6 +2194,8 @@
>>     Size += EPI.NumExceptions * sizeof(QualType);
>>   else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
>>     Size += sizeof(Expr*);
>> +  } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
>> +    Size += sizeof(FunctionDecl*);
>>   }
>>   if (EPI.ConsumedArguments)
>>     Size += NumArgs * sizeof(bool);
>>
>> Modified: cfe/trunk/lib/AST/Expr.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/AST/Expr.cpp (original)
>> +++ cfe/trunk/lib/AST/Expr.cpp Mon Apr 16 19:58:00 2012
>> @@ -1996,331 +1996,6 @@
>>   return QualType();
>>  }
>>
>> -static Expr::CanThrowResult MergeCanThrow(Expr::CanThrowResult CT1,
>> -                                          Expr::CanThrowResult CT2) {
>> -  // CanThrowResult constants are ordered so that the maximum is the
>> correct
>> -  // merge result.
>> -  return CT1 > CT2 ? CT1 : CT2;
>> -}
>> -
>> -static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr
>> *CE) {
>> -  Expr *E = const_cast<Expr*>(CE);
>> -  Expr::CanThrowResult R = Expr::CT_Cannot;
>> -  for (Expr::child_range I = E->children(); I && R != Expr::CT_Can; ++I)
>> {
>> -    R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C));
>> -  }
>> -  return R;
>> -}
>> -
>> -static Expr::CanThrowResult CanCalleeThrow(ASTContext &Ctx, const Expr
>> *E,
>> -                                           const Decl *D,
>> -                                           bool NullThrows = true) {
>> -  if (!D)
>> -    return NullThrows ? Expr::CT_Can : Expr::CT_Cannot;
>> -
>> -  // See if we can get a function type from the decl somehow.
>> -  const ValueDecl *VD = dyn_cast<ValueDecl>(D);
>> -  if (!VD) // If we have no clue what we're calling, assume the worst.
>> -    return Expr::CT_Can;
>> -
>> -  // As an extension, we assume that __attribute__((nothrow)) functions
>> don't
>> -  // throw.
>> -  if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
>> -    return Expr::CT_Cannot;
>> -
>> -  QualType T = VD->getType();
>> -  const FunctionProtoType *FT;
>> -  if ((FT = T->getAs<FunctionProtoType>())) {
>> -  } else if (const PointerType *PT = T->getAs<PointerType>())
>> -    FT = PT->getPointeeType()->getAs<FunctionProtoType>();
>> -  else if (const ReferenceType *RT = T->getAs<ReferenceType>())
>> -    FT = RT->getPointeeType()->getAs<FunctionProtoType>();
>> -  else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
>> -    FT = MT->getPointeeType()->getAs<FunctionProtoType>();
>> -  else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
>> -    FT = BT->getPointeeType()->getAs<FunctionProtoType>();
>> -
>> -  if (!FT)
>> -    return Expr::CT_Can;
>> -
>> -  if (FT->getExceptionSpecType() == EST_Delayed) {
>> -    assert(isa<CXXConstructorDecl>(D) &&
>> -           "only constructor exception specs can be unknown");
>> -    Ctx.getDiagnostics().Report(E->getLocStart(),
>> -                                diag::err_exception_spec_unknown)
>> -      << E->getSourceRange();
>> -    return Expr::CT_Can;
>> -  }
>> -
>> -  return FT->isNothrow(Ctx) ? Expr::CT_Cannot : Expr::CT_Can;
>> -}
>> -
>> -static Expr::CanThrowResult CanDynamicCastThrow(const CXXDynamicCastExpr
>> *DC) {
>> -  if (DC->isTypeDependent())
>> -    return Expr::CT_Dependent;
>> -
>> -  if (!DC->getTypeAsWritten()->isReferenceType())
>> -    return Expr::CT_Cannot;
>> -
>> -  if (DC->getSubExpr()->isTypeDependent())
>> -    return Expr::CT_Dependent;
>> -
>> -  return DC->getCastKind() == clang::CK_Dynamic? Expr::CT_Can :
>> Expr::CT_Cannot;
>> -}
>> -
>> -static Expr::CanThrowResult CanTypeidThrow(ASTContext &C,
>> -                                           const CXXTypeidExpr *DC) {
>> -  if (DC->isTypeOperand())
>> -    return Expr::CT_Cannot;
>> -
>> -  Expr *Op = DC->getExprOperand();
>> -  if (Op->isTypeDependent())
>> -    return Expr::CT_Dependent;
>> -
>> -  const RecordType *RT = Op->getType()->getAs<RecordType>();
>> -  if (!RT)
>> -    return Expr::CT_Cannot;
>> -
>> -  if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
>> -    return Expr::CT_Cannot;
>> -
>> -  if (Op->Classify(C).isPRValue())
>> -    return Expr::CT_Cannot;
>> -
>> -  return Expr::CT_Can;
>> -}
>> -
>> -Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
>> -  // C++ [expr.unary.noexcept]p3:
>> -  //   [Can throw] if in a potentially-evaluated context the expression
>> would
>> -  //   contain:
>> -  switch (getStmtClass()) {
>> -  case CXXThrowExprClass:
>> -    //   - a potentially evaluated throw-expression
>> -    return CT_Can;
>> -
>> -  case CXXDynamicCastExprClass: {
>> -    //   - a potentially evaluated dynamic_cast expression
>> dynamic_cast<T>(v),
>> -    //     where T is a reference type, that requires a run-time check
>> -    CanThrowResult CT =
>> CanDynamicCastThrow(cast<CXXDynamicCastExpr>(this));
>> -    if (CT == CT_Can)
>> -      return CT;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -  case CXXTypeidExprClass:
>> -    //   - a potentially evaluated typeid expression applied to a glvalue
>> -    //     expression whose type is a polymorphic class type
>> -    return CanTypeidThrow(C, cast<CXXTypeidExpr>(this));
>> -
>> -    //   - a potentially evaluated call to a function, member function,
>> function
>> -    //     pointer, or member function pointer that does not have a
>> non-throwing
>> -    //     exception-specification
>> -  case CallExprClass:
>> -  case CXXMemberCallExprClass:
>> -  case CXXOperatorCallExprClass:
>> -  case UserDefinedLiteralClass: {
>> -    const CallExpr *CE = cast<CallExpr>(this);
>> -    CanThrowResult CT;
>> -    if (isTypeDependent())
>> -      CT = CT_Dependent;
>> -    else if
>> (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
>> -      CT = CT_Cannot;
>> -    else
>> -      CT = CanCalleeThrow(C, this, CE->getCalleeDecl());
>> -    if (CT == CT_Can)
>> -      return CT;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -  case CXXConstructExprClass:
>> -  case CXXTemporaryObjectExprClass: {
>> -    CanThrowResult CT = CanCalleeThrow(C, this,
>> -        cast<CXXConstructExpr>(this)->getConstructor());
>> -    if (CT == CT_Can)
>> -      return CT;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -  case LambdaExprClass: {
>> -    const LambdaExpr *Lambda = cast<LambdaExpr>(this);
>> -    CanThrowResult CT = Expr::CT_Cannot;
>> -    for (LambdaExpr::capture_init_iterator Cap =
>> Lambda->capture_init_begin(),
>> -                                        CapEnd =
>> Lambda->capture_init_end();
>> -         Cap != CapEnd; ++Cap)
>> -      CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
>> -    return CT;
>> -  }
>> -
>> -  case CXXNewExprClass: {
>> -    CanThrowResult CT;
>> -    if (isTypeDependent())
>> -      CT = CT_Dependent;
>> -    else
>> -      CT = CanCalleeThrow(C, this,
>> cast<CXXNewExpr>(this)->getOperatorNew());
>> -    if (CT == CT_Can)
>> -      return CT;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -  case CXXDeleteExprClass: {
>> -    CanThrowResult CT;
>> -    QualType DTy = cast<CXXDeleteExpr>(this)->getDestroyedType();
>> -    if (DTy.isNull() || DTy->isDependentType()) {
>> -      CT = CT_Dependent;
>> -    } else {
>> -      CT = CanCalleeThrow(C, this,
>> -
>>  cast<CXXDeleteExpr>(this)->getOperatorDelete());
>> -      if (const RecordType *RT = DTy->getAs<RecordType>()) {
>> -        const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
>> -        CT = MergeCanThrow(CT, CanCalleeThrow(C, this,
>> RD->getDestructor()));
>> -      }
>> -      if (CT == CT_Can)
>> -        return CT;
>> -    }
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -  case CXXBindTemporaryExprClass: {
>> -    // The bound temporary has to be destroyed again, which might throw.
>> -    CanThrowResult CT = CanCalleeThrow(C, this,
>> -      cast<CXXBindTemporaryExpr>(this)->getTemporary()->getDestructor());
>> -    if (CT == CT_Can)
>> -      return CT;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -    // ObjC message sends are like function calls, but never have
>> exception
>> -    // specs.
>> -  case ObjCMessageExprClass:
>> -  case ObjCPropertyRefExprClass:
>> -  case ObjCSubscriptRefExprClass:
>> -    return CT_Can;
>> -
>> -    // All the ObjC literals that are implemented as calls are
>> -    // potentially throwing unless we decide to close off that
>> -    // possibility.
>> -  case ObjCArrayLiteralClass:
>> -  case ObjCDictionaryLiteralClass:
>> -  case ObjCNumericLiteralClass:
>> -    return CT_Can;
>> -
>> -    // Many other things have subexpressions, so we have to test those.
>> -    // Some are simple:
>> -  case ConditionalOperatorClass:
>> -  case CompoundLiteralExprClass:
>> -  case CXXConstCastExprClass:
>> -  case CXXDefaultArgExprClass:
>> -  case CXXReinterpretCastExprClass:
>> -  case DesignatedInitExprClass:
>> -  case ExprWithCleanupsClass:
>> -  case ExtVectorElementExprClass:
>> -  case InitListExprClass:
>> -  case MemberExprClass:
>> -  case ObjCIsaExprClass:
>> -  case ObjCIvarRefExprClass:
>> -  case ParenExprClass:
>> -  case ParenListExprClass:
>> -  case ShuffleVectorExprClass:
>> -  case VAArgExprClass:
>> -    return CanSubExprsThrow(C, this);
>> -
>> -    // Some might be dependent for other reasons.
>> -  case ArraySubscriptExprClass:
>> -  case BinaryOperatorClass:
>> -  case CompoundAssignOperatorClass:
>> -  case CStyleCastExprClass:
>> -  case CXXStaticCastExprClass:
>> -  case CXXFunctionalCastExprClass:
>> -  case ImplicitCastExprClass:
>> -  case MaterializeTemporaryExprClass:
>> -  case UnaryOperatorClass: {
>> -    CanThrowResult CT = isTypeDependent() ? CT_Dependent : CT_Cannot;
>> -    return MergeCanThrow(CT, CanSubExprsThrow(C, this));
>> -  }
>> -
>> -    // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of
>> worms.
>> -  case StmtExprClass:
>> -    return CT_Can;
>> -
>> -  case ChooseExprClass:
>> -    if (isTypeDependent() || isValueDependent())
>> -      return CT_Dependent;
>> -    return cast<ChooseExpr>(this)->getChosenSubExpr(C)->CanThrow(C);
>> -
>> -  case GenericSelectionExprClass:
>> -    if (cast<GenericSelectionExpr>(this)->isResultDependent())
>> -      return CT_Dependent;
>> -    return
>> cast<GenericSelectionExpr>(this)->getResultExpr()->CanThrow(C);
>> -
>> -    // Some expressions are always dependent.
>> -  case CXXDependentScopeMemberExprClass:
>> -  case CXXUnresolvedConstructExprClass:
>> -  case DependentScopeDeclRefExprClass:
>> -    return CT_Dependent;
>> -
>> -  case AtomicExprClass:
>> -  case AsTypeExprClass:
>> -  case BinaryConditionalOperatorClass:
>> -  case BlockExprClass:
>> -  case CUDAKernelCallExprClass:
>> -  case DeclRefExprClass:
>> -  case ObjCBridgedCastExprClass:
>> -  case ObjCIndirectCopyRestoreExprClass:
>> -  case ObjCProtocolExprClass:
>> -  case ObjCSelectorExprClass:
>> -  case OffsetOfExprClass:
>> -  case PackExpansionExprClass:
>> -  case PseudoObjectExprClass:
>> -  case SubstNonTypeTemplateParmExprClass:
>> -  case SubstNonTypeTemplateParmPackExprClass:
>> -  case UnaryExprOrTypeTraitExprClass:
>> -  case UnresolvedLookupExprClass:
>> -  case UnresolvedMemberExprClass:
>> -    // FIXME: Can any of the above throw?  If so, when?
>> -    return CT_Cannot;
>> -
>> -  case AddrLabelExprClass:
>> -  case ArrayTypeTraitExprClass:
>> -  case BinaryTypeTraitExprClass:
>> -  case TypeTraitExprClass:
>> -  case CXXBoolLiteralExprClass:
>> -  case CXXNoexceptExprClass:
>> -  case CXXNullPtrLiteralExprClass:
>> -  case CXXPseudoDestructorExprClass:
>> -  case CXXScalarValueInitExprClass:
>> -  case CXXThisExprClass:
>> -  case CXXUuidofExprClass:
>> -  case CharacterLiteralClass:
>> -  case ExpressionTraitExprClass:
>> -  case FloatingLiteralClass:
>> -  case GNUNullExprClass:
>> -  case ImaginaryLiteralClass:
>> -  case ImplicitValueInitExprClass:
>> -  case IntegerLiteralClass:
>> -  case ObjCEncodeExprClass:
>> -  case ObjCStringLiteralClass:
>> -  case ObjCBoolLiteralExprClass:
>> -  case OpaqueValueExprClass:
>> -  case PredefinedExprClass:
>> -  case SizeOfPackExprClass:
>> -  case StringLiteralClass:
>> -  case UnaryTypeTraitExprClass:
>> -    // These expressions can never throw.
>> -    return CT_Cannot;
>> -
>> -#define STMT(CLASS, PARENT) case CLASS##Class:
>> -#define STMT_RANGE(Base, First, Last)
>> -#define LAST_STMT_RANGE(BASE, FIRST, LAST)
>> -#define EXPR(CLASS, PARENT)
>> -#define ABSTRACT_STMT(STMT)
>> -#include "clang/AST/StmtNodes.inc"
>> -  case NoStmtClass:
>> -    llvm_unreachable("Invalid class for expression");
>> -  }
>> -  llvm_unreachable("Bogus StmtClass");
>> -}
>> -
>>  Expr* Expr::IgnoreParens() {
>>   Expr* E = this;
>>   while (true) {
>>
>> Modified: cfe/trunk/lib/AST/Type.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/AST/Type.cpp (original)
>> +++ cfe/trunk/lib/AST/Type.cpp Mon Apr 16 19:58:00 2012
>> @@ -1546,6 +1546,13 @@
>>       else if (epi.NoexceptExpr->isInstantiationDependent())
>>         setInstantiationDependent();
>>     }
>> +  } else if (getExceptionSpecType() == EST_Uninstantiated) {
>> +    // Store the function decl from which we will resolve our
>> +    // exception specification.
>> +    FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot +
>> numArgs);
>> +    *slot = epi.ExceptionSpecDecl;
>> +    // This exception specification doesn't make the type dependent,
>> because
>> +    // it's not instantiated as part of instantiating the type.
>>   }
>>
>>   if (epi.ConsumedArguments) {
>> @@ -1629,6 +1636,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) {
>> +    ID.AddPointer(epi.ExceptionSpecDecl->getCanonicalDecl());
>>   }
>>   if (epi.ConsumedArguments) {
>>     for (unsigned i = 0; i != NumArgs; ++i)
>>
>> Modified: cfe/trunk/lib/Analysis/CFG.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Analysis/CFG.cpp (original)
>> +++ cfe/trunk/lib/Analysis/CFG.cpp Mon Apr 16 19:58:00 2012
>> @@ -1284,7 +1284,8 @@
>>   const FunctionType *FT = Ty->getAs<FunctionType>();
>>   if (FT) {
>>     if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
>> -      if (Proto->isNothrow(Ctx))
>> +      if (Proto->getExceptionSpecType() != EST_Uninstantiated &&
>> +          Proto->isNothrow(Ctx))
>>         return false;
>>   }
>>   return true;
>>
>> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Apr 16 19:58:00 2012
>> @@ -125,14 +125,17 @@
>>   }
>>  }
>>
>> -void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl
>> *Method) {
>> -  assert(Context && "ImplicitExceptionSpecification without an
>> ASTContext");
>> +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)
>>     return;
>>
>>   const FunctionProtoType *Proto
>>     = Method->getType()->getAs<FunctionProtoType>();
>> +  Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
>> +  if (!Proto)
>> +    return;
>>
>>   ExceptionSpecificationType EST = Proto->getExceptionSpecType();
>>
>> @@ -164,7 +167,8 @@
>>
>>   // Check out noexcept specs.
>>   if (EST == EST_ComputedNoexcept) {
>> -    FunctionProtoType::NoexceptResult NR =
>> Proto->getNoexceptSpec(*Context);
>> +    FunctionProtoType::NoexceptResult NR =
>> +        Proto->getNoexceptSpec(Self->Context);
>>     assert(NR != FunctionProtoType::NR_NoNoexcept &&
>>            "Must have noexcept result for EST_ComputedNoexcept.");
>>     assert(NR != FunctionProtoType::NR_Dependent &&
>> @@ -188,7 +192,7 @@
>>   for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
>>                                           EEnd = Proto->exception_end();
>>        E != EEnd; ++E)
>> -    if (ExceptionsSeen.insert(Context->getCanonicalType(*E)))
>> +    if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
>>       Exceptions.push_back(*E);
>>  }
>>
>> @@ -217,7 +221,7 @@
>>   // implicit definition. For now, we assume that any non-nothrow
>> expression can
>>   // throw any exception.
>>
>> -  if (E->CanThrow(*Context))
>> +  if (Self->canThrow(E))
>>     ComputedEST = EST_None;
>>  }
>>
>> @@ -3922,7 +3926,7 @@
>>     HadError = true;
>>   }
>>
>> -  ImplicitExceptionSpecification Spec(Context);
>> +  ImplicitExceptionSpecification Spec(*this);
>>   bool Const;
>>   llvm::tie(Spec, Const) =
>>     ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent());
>> @@ -4031,7 +4035,7 @@
>>     HadError = true;
>>   }
>>
>> -  ImplicitExceptionSpecification Spec(Context);
>> +  ImplicitExceptionSpecification Spec(*this);
>>   bool Const;
>>   llvm::tie(Spec, Const) =
>>     ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent());
>> @@ -6814,7 +6818,7 @@
>>   // C++ [except.spec]p14:
>>   //   An implicitly declared special member function (Clause 12) shall
>> have an
>>   //   exception-specification. [...]
>> -  ImplicitExceptionSpecification ExceptSpec(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>   if (ClassDecl->isInvalidDecl())
>>     return ExceptSpec;
>>
>> @@ -6831,7 +6835,7 @@
>>       // If this is a deleted function, add it anyway. This might be
>> conformant
>>       // with the standard. This might not. I'm not sure. It might not
>> matter.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
>>     }
>>   }
>>
>> @@ -6845,7 +6849,7 @@
>>       // If this is a deleted function, add it anyway. This might be
>> conformant
>>       // with the standard. This might not. I'm not sure. It might not
>> matter.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
>>     }
>>   }
>>
>> @@ -6868,7 +6872,7 @@
>>       // might just be ill-formed because this function attempts to refer
>> to
>>       // a deleted function here.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
>>     }
>>   }
>>
>> @@ -6990,6 +6994,7 @@
>>   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();
>> @@ -7190,7 +7195,7 @@
>>   // C++ [except.spec]p14:
>>   //   An implicitly declared special member function (Clause 12) shall
>> have
>>   //   an exception-specification.
>> -  ImplicitExceptionSpecification ExceptSpec(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>   if (ClassDecl->isInvalidDecl())
>>     return ExceptSpec;
>>
>> @@ -7202,7 +7207,7 @@
>>       continue;
>>
>>     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
>> -      ExceptSpec.CalledDecl(
>> +      ExceptSpec.CalledDecl(B->getLocStart(),
>>
>>  LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
>>   }
>>
>> @@ -7211,7 +7216,7 @@
>>                                        BEnd = ClassDecl->vbases_end();
>>        B != BEnd; ++B) {
>>     if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
>> -      ExceptSpec.CalledDecl(
>> +      ExceptSpec.CalledDecl(B->getLocStart(),
>>
>> LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
>>   }
>>
>> @@ -7221,7 +7226,7 @@
>>        F != FEnd; ++F) {
>>     if (const RecordType *RecordTy
>>         = Context.getBaseElementType(F->getType())->getAs<RecordType>())
>> -      ExceptSpec.CalledDecl(
>> +      ExceptSpec.CalledDecl(F->getLocation(),
>>
>> LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
>>   }
>>
>> @@ -7546,7 +7551,7 @@
>>  Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
>>                                                    CXXRecordDecl
>> *ClassDecl) {
>>   if (ClassDecl->isInvalidDecl())
>> -    return std::make_pair(ImplicitExceptionSpecification(Context),
>> false);
>> +    return std::make_pair(ImplicitExceptionSpecification(*this), false);
>>
>>   // C++ [class.copy]p10:
>>   //   If the class definition does not explicitly declare a copy
>> @@ -7619,7 +7624,7 @@
>>   // 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(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>   unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
>>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
>>                                        BaseEnd = ClassDecl->bases_end();
>> @@ -7631,7 +7636,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
>>                                                             ArgQuals,
>> false, 0))
>> -      ExceptSpec.CalledDecl(CopyAssign);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
>>   }
>>
>>   for (CXXRecordDecl::base_class_iterator Base =
>> ClassDecl->vbases_begin(),
>> @@ -7641,7 +7646,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
>>                                                             ArgQuals,
>> false, 0))
>> -      ExceptSpec.CalledDecl(CopyAssign);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
>>   }
>>
>>   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
>> @@ -7652,7 +7657,7 @@
>>     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
>>       if (CXXMethodDecl *CopyAssign =
>>           LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
>> -        ExceptSpec.CalledDecl(CopyAssign);
>> +        ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
>>     }
>>   }
>>
>> @@ -7665,7 +7670,7 @@
>>   // for determining the argument type of the operator. Note also that
>>   // operators taking an object instead of a reference are allowed.
>>
>> -  ImplicitExceptionSpecification Spec(Context);
>> +  ImplicitExceptionSpecification Spec(*this);
>>   bool Const;
>>   llvm::tie(Spec, Const) =
>>     ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
>> @@ -8032,7 +8037,7 @@
>>
>>  Sema::ImplicitExceptionSpecification
>>  Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl
>> *ClassDecl) {
>> -  ImplicitExceptionSpecification ExceptSpec(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>
>>   if (ClassDecl->isInvalidDecl())
>>     return ExceptSpec;
>> @@ -8059,7 +8064,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
>>                                                            false, 0))
>> -      ExceptSpec.CalledDecl(MoveAssign);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
>>   }
>>
>>   for (CXXRecordDecl::base_class_iterator Base =
>> ClassDecl->vbases_begin(),
>> @@ -8069,7 +8074,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
>>                                                            false, 0))
>> -      ExceptSpec.CalledDecl(MoveAssign);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
>>   }
>>
>>   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
>> @@ -8080,7 +8085,7 @@
>>     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
>>       if (CXXMethodDecl *MoveAssign =
>> LookupMovingAssignment(FieldClassDecl,
>>                                                              false, 0))
>> -        ExceptSpec.CalledDecl(MoveAssign);
>> +        ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
>>     }
>>   }
>>
>> @@ -8578,7 +8583,7 @@
>>  std::pair<Sema::ImplicitExceptionSpecification, bool>
>>  Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl
>> *ClassDecl) {
>>   if (ClassDecl->isInvalidDecl())
>> -    return std::make_pair(ImplicitExceptionSpecification(Context),
>> false);
>> +    return std::make_pair(ImplicitExceptionSpecification(*this), false);
>>
>>   // C++ [class.copy]p5:
>>   //   The implicitly-declared copy constructor for a class X will
>> @@ -8639,7 +8644,7 @@
>>   // C++ [except.spec]p14:
>>   //   An implicitly declared special member function (Clause 12) shall
>> have an
>>   //   exception-specification. [...]
>> -  ImplicitExceptionSpecification ExceptSpec(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>   unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
>>   for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
>>                                        BaseEnd = ClassDecl->bases_end();
>> @@ -8653,7 +8658,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXConstructorDecl *CopyConstructor =
>>           LookupCopyingConstructor(BaseClassDecl, Quals))
>> -      ExceptSpec.CalledDecl(CopyConstructor);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
>>   }
>>   for (CXXRecordDecl::base_class_iterator Base =
>> ClassDecl->vbases_begin(),
>>                                        BaseEnd = ClassDecl->vbases_end();
>> @@ -8663,7 +8668,7 @@
>>       =
>> cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
>>     if (CXXConstructorDecl *CopyConstructor =
>>           LookupCopyingConstructor(BaseClassDecl, Quals))
>> -      ExceptSpec.CalledDecl(CopyConstructor);
>> +      ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
>>   }
>>   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
>>                                   FieldEnd = ClassDecl->field_end();
>> @@ -8673,7 +8678,7 @@
>>     if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
>>       if (CXXConstructorDecl *CopyConstructor =
>>         LookupCopyingConstructor(FieldClassDecl, Quals))
>> -      ExceptSpec.CalledDecl(CopyConstructor);
>> +      ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
>>     }
>>   }
>>
>> @@ -8686,7 +8691,7 @@
>>   //   If the class definition does not explicitly declare a copy
>>   //   constructor, one is declared implicitly.
>>
>> -  ImplicitExceptionSpecification Spec(Context);
>> +  ImplicitExceptionSpecification Spec(*this);
>>   bool Const;
>>   llvm::tie(Spec, Const) =
>>     ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
>> @@ -8784,7 +8789,7 @@
>>   // C++ [except.spec]p14:
>>   //   An implicitly declared special member function (Clause 12) shall
>> have an
>>   //   exception-specification. [...]
>> -  ImplicitExceptionSpecification ExceptSpec(Context);
>> +  ImplicitExceptionSpecification ExceptSpec(*this);
>>   if (ClassDecl->isInvalidDecl())
>>     return ExceptSpec;
>>
>> @@ -8801,7 +8806,7 @@
>>       // If this is a deleted function, add it anyway. This might be
>> conformant
>>       // with the standard. This might not. I'm not sure. It might not
>> matter.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
>>     }
>>   }
>>
>> @@ -8815,7 +8820,7 @@
>>       // If this is a deleted function, add it anyway. This might be
>> conformant
>>       // with the standard. This might not. I'm not sure. It might not
>> matter.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
>>     }
>>   }
>>
>> @@ -8833,7 +8838,7 @@
>>       // might just be ill-formed because this function attempts to refer
>> to
>>       // a deleted function here.
>>       if (Constructor)
>> -        ExceptSpec.CalledDecl(Constructor);
>> +        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
>>     }
>>   }
>>
>> @@ -11116,6 +11121,7 @@
>>   FindCXXThisExpr Finder(*this);
>>
>>   switch (Proto->getExceptionSpecType()) {
>> +  case EST_Uninstantiated:
>>   case EST_BasicNoexcept:
>>   case EST_Delayed:
>>   case EST_DynamicNone:
>>
>> Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Mon Apr 16 19:58:00 2012
>> @@ -96,6 +96,26 @@
>>   return FnT->hasExceptionSpec();
>>  }
>>
>> +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)
>> +    return FPT;
>> +
>> +  FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
>> +  const FunctionProtoType *SourceFPT =
>> +      SourceDecl->getType()->castAs<FunctionProtoType>();
>> +
>> +  if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
>> +    return SourceFPT;
>> +
>> +  // Instantiate the exception specification now.
>> +  InstantiateExceptionSpec(Loc, SourceDecl);
>> +
>> +  return SourceDecl->getType()->castAs<FunctionProtoType>();
>> +}
>> +
>>  bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl
>> *New) {
>>   OverloadedOperatorKind OO =
>> New->getDeclName().getCXXOverloadedOperator();
>>   bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
>> @@ -104,7 +124,7 @@
>>   unsigned DiagID = diag::err_mismatched_exception_spec;
>>   if (getLangOpts().MicrosoftExt)
>>     DiagID = diag::warn_mismatched_exception_spec;
>> -
>> +
>>   if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
>>
>> PDiag(diag::note_previous_declaration),
>>
>> Old->getType()->getAs<FunctionProtoType>(),
>> @@ -295,6 +315,13 @@
>>   if (MissingEmptyExceptionSpecification)
>>     *MissingEmptyExceptionSpecification = false;
>>
>> +  Old = ResolveExceptionSpec(NewLoc, Old);
>> +  if (!Old)
>> +    return false;
>> +  New = ResolveExceptionSpec(NewLoc, New);
>> +  if (!New)
>> +    return false;
>> +
>>   // C++0x [except.spec]p3: Two exception-specifications are compatible
>> if:
>>   //   - both are non-throwing, regardless of their form,
>>   //   - both have the form noexcept(constant-expression) and the
>> constant-
>> @@ -318,6 +345,7 @@
>>   ExceptionSpecificationType NewEST = New->getExceptionSpecType();
>>
>>   assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
>> +         OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
>>          "Shouldn't see unknown exception specifications here");
>>
>>   // Shortcut the case where both have no spec.
>> @@ -483,6 +511,14 @@
>>   if (!SubLoc.isValid())
>>     SubLoc = SuperLoc;
>>
>> +  // Resolve the exception specifications, if needed.
>> +  Superset = ResolveExceptionSpec(SuperLoc, Superset);
>> +  if (!Superset)
>> +    return false;
>> +  Subset = ResolveExceptionSpec(SubLoc, Subset);
>> +  if (!Subset)
>> +    return false;
>> +
>>   ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
>>
>>   // If superset contains everything, we're done.
>> @@ -507,6 +543,7 @@
>>   ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
>>
>>   assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
>> +         SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated
>> &&
>>          "Shouldn't see unknown exception specifications here");
>>
>>   // It does not. If the subset contains everything, we've failed.
>> @@ -726,4 +763,324 @@
>>                                   New->getLocation());
>>  }
>>
>> +static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
>> +  Expr *E = const_cast<Expr*>(CE);
>> +  CanThrowResult R = CT_Cannot;
>> +  for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
>> +    R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
>> +  return R;
>> +}
>> +
>> +static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
>> +                                           const Decl *D,
>> +                                           bool NullThrows = true) {
>> +  if (!D)
>> +    return NullThrows ? CT_Can : CT_Cannot;
>> +
>> +  // See if we can get a function type from the decl somehow.
>> +  const ValueDecl *VD = dyn_cast<ValueDecl>(D);
>> +  if (!VD) // If we have no clue what we're calling, assume the worst.
>> +    return CT_Can;
>> +
>> +  // As an extension, we assume that __attribute__((nothrow)) functions
>> don't
>> +  // throw.
>> +  if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
>> +    return CT_Cannot;
>> +
>> +  QualType T = VD->getType();
>> +  const FunctionProtoType *FT;
>> +  if ((FT = T->getAs<FunctionProtoType>())) {
>> +  } else if (const PointerType *PT = T->getAs<PointerType>())
>> +    FT = PT->getPointeeType()->getAs<FunctionProtoType>();
>> +  else if (const ReferenceType *RT = T->getAs<ReferenceType>())
>> +    FT = RT->getPointeeType()->getAs<FunctionProtoType>();
>> +  else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
>> +    FT = MT->getPointeeType()->getAs<FunctionProtoType>();
>> +  else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
>> +    FT = BT->getPointeeType()->getAs<FunctionProtoType>();
>> +
>> +  if (!FT)
>> +    return CT_Can;
>> +
>> +  FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
>> +  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;
>> +}
>> +
>> +static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
>> +  if (DC->isTypeDependent())
>> +    return CT_Dependent;
>> +
>> +  if (!DC->getTypeAsWritten()->isReferenceType())
>> +    return CT_Cannot;
>> +
>> +  if (DC->getSubExpr()->isTypeDependent())
>> +    return CT_Dependent;
>> +
>> +  return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
>> +}
>> +
>> +static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
>> +  if (DC->isTypeOperand())
>> +    return CT_Cannot;
>> +
>> +  Expr *Op = DC->getExprOperand();
>> +  if (Op->isTypeDependent())
>> +    return CT_Dependent;
>> +
>> +  const RecordType *RT = Op->getType()->getAs<RecordType>();
>> +  if (!RT)
>> +    return CT_Cannot;
>> +
>> +  if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
>> +    return CT_Cannot;
>> +
>> +  if (Op->Classify(S.Context).isPRValue())
>> +    return CT_Cannot;
>> +
>> +  return CT_Can;
>> +}
>> +
>> +CanThrowResult Sema::canThrow(const Expr *E) {
>> +  // C++ [expr.unary.noexcept]p3:
>> +  //   [Can throw] if in a potentially-evaluated context the expression
>> would
>> +  //   contain:
>> +  switch (E->getStmtClass()) {
>> +  case Expr::CXXThrowExprClass:
>> +    //   - a potentially evaluated throw-expression
>> +    return CT_Can;
>> +
>> +  case Expr::CXXDynamicCastExprClass: {
>> +    //   - a potentially evaluated dynamic_cast expression
>> dynamic_cast<T>(v),
>> +    //     where T is a reference type, that requires a run-time check
>> +    CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E));
>> +    if (CT == CT_Can)
>> +      return CT;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +  case Expr::CXXTypeidExprClass:
>> +    //   - a potentially evaluated typeid expression applied to a glvalue
>> +    //     expression whose type is a polymorphic class type
>> +    return canTypeidThrow(*this, cast<CXXTypeidExpr>(E));
>> +
>> +    //   - a potentially evaluated call to a function, member function,
>> function
>> +    //     pointer, or member function pointer that does not have a
>> non-throwing
>> +    //     exception-specification
>> +  case Expr::CallExprClass:
>> +  case Expr::CXXMemberCallExprClass:
>> +  case Expr::CXXOperatorCallExprClass:
>> +  case Expr::UserDefinedLiteralClass: {
>> +    const CallExpr *CE = cast<CallExpr>(E);
>> +    CanThrowResult CT;
>> +    if (E->isTypeDependent())
>> +      CT = CT_Dependent;
>> +    else if
>> (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
>> +      CT = CT_Cannot;
>> +    else
>> +      CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
>> +    if (CT == CT_Can)
>> +      return CT;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +  case Expr::CXXConstructExprClass:
>> +  case Expr::CXXTemporaryObjectExprClass: {
>> +    CanThrowResult CT = canCalleeThrow(*this, E,
>> +        cast<CXXConstructExpr>(E)->getConstructor());
>> +    if (CT == CT_Can)
>> +      return CT;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +  case Expr::LambdaExprClass: {
>> +    const LambdaExpr *Lambda = cast<LambdaExpr>(E);
>> +    CanThrowResult CT = CT_Cannot;
>> +    for (LambdaExpr::capture_init_iterator Cap =
>> Lambda->capture_init_begin(),
>> +                                        CapEnd =
>> Lambda->capture_init_end();
>> +         Cap != CapEnd; ++Cap)
>> +      CT = mergeCanThrow(CT, canThrow(*Cap));
>> +    return CT;
>> +  }
>> +
>> +  case Expr::CXXNewExprClass: {
>> +    CanThrowResult CT;
>> +    if (E->isTypeDependent())
>> +      CT = CT_Dependent;
>> +    else
>> +      CT = canCalleeThrow(*this, E,
>> cast<CXXNewExpr>(E)->getOperatorNew());
>> +    if (CT == CT_Can)
>> +      return CT;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +  case Expr::CXXDeleteExprClass: {
>> +    CanThrowResult CT;
>> +    QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType();
>> +    if (DTy.isNull() || DTy->isDependentType()) {
>> +      CT = CT_Dependent;
>> +    } else {
>> +      CT = canCalleeThrow(*this, E,
>> +                          cast<CXXDeleteExpr>(E)->getOperatorDelete());
>> +      if (const RecordType *RT = DTy->getAs<RecordType>()) {
>> +        const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
>> +        CT = mergeCanThrow(CT, canCalleeThrow(*this, E,
>> RD->getDestructor()));
>> +      }
>> +      if (CT == CT_Can)
>> +        return CT;
>> +    }
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +  case Expr::CXXBindTemporaryExprClass: {
>> +    // The bound temporary has to be destroyed again, which might throw.
>> +    CanThrowResult CT = canCalleeThrow(*this, E,
>> +      cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor());
>> +    if (CT == CT_Can)
>> +      return CT;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +    // ObjC message sends are like function calls, but never have
>> exception
>> +    // specs.
>> +  case Expr::ObjCMessageExprClass:
>> +  case Expr::ObjCPropertyRefExprClass:
>> +  case Expr::ObjCSubscriptRefExprClass:
>> +    return CT_Can;
>> +
>> +    // All the ObjC literals that are implemented as calls are
>> +    // potentially throwing unless we decide to close off that
>> +    // possibility.
>> +  case Expr::ObjCArrayLiteralClass:
>> +  case Expr::ObjCDictionaryLiteralClass:
>> +  case Expr::ObjCNumericLiteralClass:
>> +    return CT_Can;
>> +
>> +    // Many other things have subexpressions, so we have to test those.
>> +    // Some are simple:
>> +  case Expr::ConditionalOperatorClass:
>> +  case Expr::CompoundLiteralExprClass:
>> +  case Expr::CXXConstCastExprClass:
>> +  case Expr::CXXDefaultArgExprClass:
>> +  case Expr::CXXReinterpretCastExprClass:
>> +  case Expr::DesignatedInitExprClass:
>> +  case Expr::ExprWithCleanupsClass:
>> +  case Expr::ExtVectorElementExprClass:
>> +  case Expr::InitListExprClass:
>> +  case Expr::MemberExprClass:
>> +  case Expr::ObjCIsaExprClass:
>> +  case Expr::ObjCIvarRefExprClass:
>> +  case Expr::ParenExprClass:
>> +  case Expr::ParenListExprClass:
>> +  case Expr::ShuffleVectorExprClass:
>> +  case Expr::VAArgExprClass:
>> +    return canSubExprsThrow(*this, E);
>> +
>> +    // Some might be dependent for other reasons.
>> +  case Expr::ArraySubscriptExprClass:
>> +  case Expr::BinaryOperatorClass:
>> +  case Expr::CompoundAssignOperatorClass:
>> +  case Expr::CStyleCastExprClass:
>> +  case Expr::CXXStaticCastExprClass:
>> +  case Expr::CXXFunctionalCastExprClass:
>> +  case Expr::ImplicitCastExprClass:
>> +  case Expr::MaterializeTemporaryExprClass:
>> +  case Expr::UnaryOperatorClass: {
>> +    CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot;
>> +    return mergeCanThrow(CT, canSubExprsThrow(*this, E));
>> +  }
>> +
>> +    // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of
>> worms.
>> +  case Expr::StmtExprClass:
>> +    return CT_Can;
>> +
>> +  case Expr::ChooseExprClass:
>> +    if (E->isTypeDependent() || E->isValueDependent())
>> +      return CT_Dependent;
>> +    return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
>> +
>> +  case Expr::GenericSelectionExprClass:
>> +    if (cast<GenericSelectionExpr>(E)->isResultDependent())
>> +      return CT_Dependent;
>> +    return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr());
>> +
>> +    // Some expressions are always dependent.
>> +  case Expr::CXXDependentScopeMemberExprClass:
>> +  case Expr::CXXUnresolvedConstructExprClass:
>> +  case Expr::DependentScopeDeclRefExprClass:
>> +    return CT_Dependent;
>> +
>> +  case Expr::AsTypeExprClass:
>> +  case Expr::BinaryConditionalOperatorClass:
>> +  case Expr::BlockExprClass:
>> +  case Expr::CUDAKernelCallExprClass:
>> +  case Expr::DeclRefExprClass:
>> +  case Expr::ObjCBridgedCastExprClass:
>> +  case Expr::ObjCIndirectCopyRestoreExprClass:
>> +  case Expr::ObjCProtocolExprClass:
>> +  case Expr::ObjCSelectorExprClass:
>> +  case Expr::OffsetOfExprClass:
>> +  case Expr::PackExpansionExprClass:
>> +  case Expr::PseudoObjectExprClass:
>> +  case Expr::SubstNonTypeTemplateParmExprClass:
>> +  case Expr::SubstNonTypeTemplateParmPackExprClass:
>> +  case Expr::UnaryExprOrTypeTraitExprClass:
>> +  case Expr::UnresolvedLookupExprClass:
>> +  case Expr::UnresolvedMemberExprClass:
>> +    // FIXME: Can any of the above throw?  If so, when?
>> +    return CT_Cannot;
>> +
>> +  case Expr::AddrLabelExprClass:
>> +  case Expr::ArrayTypeTraitExprClass:
>> +  case Expr::AtomicExprClass:
>> +  case Expr::BinaryTypeTraitExprClass:
>> +  case Expr::TypeTraitExprClass:
>> +  case Expr::CXXBoolLiteralExprClass:
>> +  case Expr::CXXNoexceptExprClass:
>> +  case Expr::CXXNullPtrLiteralExprClass:
>> +  case Expr::CXXPseudoDestructorExprClass:
>> +  case Expr::CXXScalarValueInitExprClass:
>> +  case Expr::CXXThisExprClass:
>> +  case Expr::CXXUuidofExprClass:
>> +  case Expr::CharacterLiteralClass:
>> +  case Expr::ExpressionTraitExprClass:
>> +  case Expr::FloatingLiteralClass:
>> +  case Expr::GNUNullExprClass:
>> +  case Expr::ImaginaryLiteralClass:
>> +  case Expr::ImplicitValueInitExprClass:
>> +  case Expr::IntegerLiteralClass:
>> +  case Expr::ObjCEncodeExprClass:
>> +  case Expr::ObjCStringLiteralClass:
>> +  case Expr::ObjCBoolLiteralExprClass:
>> +  case Expr::OpaqueValueExprClass:
>> +  case Expr::PredefinedExprClass:
>> +  case Expr::SizeOfPackExprClass:
>> +  case Expr::StringLiteralClass:
>> +  case Expr::UnaryTypeTraitExprClass:
>> +    // These expressions can never throw.
>> +    return CT_Cannot;
>> +
>> +#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
>> +#define STMT_RANGE(Base, First, Last)
>> +#define LAST_STMT_RANGE(BASE, FIRST, LAST)
>> +#define EXPR(CLASS, PARENT)
>> +#define ABSTRACT_STMT(STMT)
>> +#include "clang/AST/StmtNodes.inc"
>> +  case Expr::NoStmtClass:
>> +    llvm_unreachable("Invalid class for expression");
>> +  }
>> +  llvm_unreachable("Bogus StmtClass");
>> +}
>> +
>>  } // end namespace clang
>>
>> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Apr 16 19:58:00 2012
>> @@ -9773,6 +9773,13 @@
>>   // FIXME: Is this really right?
>>   if (CurContext == Func) return;
>>
>> +  // Instantiate the exception specification for any function which is
>> +  // used: CodeGen will need it.
>> +  if (Func->getTemplateInstantiationPattern() &&
>> +
>>  Func->getType()->castAs<FunctionProtoType>()->getExceptionSpecType()
>> +        == EST_Uninstantiated)
>> +    InstantiateExceptionSpec(Loc, Func);
>> +
>>   // Implicit instantiation of function templates and member functions of
>>   // class templates.
>>   if (Func->isImplicitlyInstantiable()) {
>>
>> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Apr 16 19:58:00 2012
>> @@ -3135,6 +3135,9 @@
>>             FoundAssign = true;
>>             const FunctionProtoType *CPT
>>                 = Operator->getType()->getAs<FunctionProtoType>();
>> +            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
>> +            if (!CPT)
>> +              return false;
>>             if (CPT->getExceptionSpecType() == EST_Delayed)
>>               return false;
>>             if (!CPT->isNothrow(Self.Context))
>> @@ -3174,6 +3177,9 @@
>>           FoundConstructor = true;
>>           const FunctionProtoType *CPT
>>               = Constructor->getType()->getAs<FunctionProtoType>();
>> +          CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
>> +          if (!CPT)
>> +            return false;
>>           if (CPT->getExceptionSpecType() == EST_Delayed)
>>             return false;
>>           // FIXME: check whether evaluating default arguments can throw.
>> @@ -3209,6 +3215,9 @@
>>         if (Constructor->isDefaultConstructor()) {
>>           const FunctionProtoType *CPT
>>               = Constructor->getType()->getAs<FunctionProtoType>();
>> +          CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
>> +          if (!CPT)
>> +            return false;
>>           if (CPT->getExceptionSpecType() == EST_Delayed)
>>             return false;
>>           // TODO: check whether evaluating default arguments can throw.
>> @@ -5203,9 +5212,9 @@
>>
>>  ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr
>> *Operand,
>>                                       SourceLocation RParen) {
>> +  CanThrowResult CanThrow = canThrow(Operand);
>>   return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
>> -                                             Operand->CanThrow(Context),
>> -                                             KeyLoc, RParen));
>> +                                             CanThrow, KeyLoc, RParen));
>>  }
>>
>>  ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
>>
>> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Apr 16 19:58:00 2012
>> @@ -11150,6 +11150,7 @@
>>                                            VK_LValue,
>>                                            Found.getDecl(),
>>                                            TemplateArgs);
>> +    MarkDeclRefReferenced(DRE);
>>     DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
>>     return DRE;
>>   }
>> @@ -11178,6 +11179,7 @@
>>                                                VK_LValue,
>>                                                Found.getDecl(),
>>                                                TemplateArgs);
>> +        MarkDeclRefReferenced(DRE);
>>         DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
>>         return DRE;
>>       } else {
>>
>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Apr 16 19:58:00
>> 2012
>> @@ -153,6 +153,7 @@
>>  bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
>>   switch (Kind) {
>>   case TemplateInstantiation:
>> +  case ExceptionSpecInstantiation:
>>   case DefaultTemplateArgumentInstantiation:
>>   case DefaultFunctionArgumentInstantiation:
>>     return true;
>> @@ -190,6 +191,29 @@
>>   }
>>  }
>>
>> +Sema::InstantiatingTemplate::
>> +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
>> +                      FunctionDecl *Entity, ExceptionSpecification,
>> +                      SourceRange InstantiationRange)
>> +  : SemaRef(SemaRef),
>> +    SavedInNonInstantiationSFINAEContext(
>> +
>>  SemaRef.InNonInstantiationSFINAEContext)
>> +{
>> +  Invalid = CheckInstantiationDepth(PointOfInstantiation,
>> +                                    InstantiationRange);
>> +  if (!Invalid) {
>> +    ActiveTemplateInstantiation Inst;
>> +    Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
>> +    Inst.PointOfInstantiation = PointOfInstantiation;
>> +    Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
>> +    Inst.TemplateArgs = 0;
>> +    Inst.NumTemplateArgs = 0;
>> +    Inst.InstantiationRange = InstantiationRange;
>> +    SemaRef.InNonInstantiationSFINAEContext = false;
>> +    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
>> +  }
>> +}
>> +
>>  Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
>>                                          SourceLocation
>> PointOfInstantiation,
>>                                          TemplateDecl *Template,
>> @@ -592,6 +616,13 @@
>>         << Active->InstantiationRange;
>>       break;
>>     }
>> +
>> +    case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
>> +      Diags.Report(Active->PointOfInstantiation,
>> +                   diag::note_template_exception_spec_instantiation_here)
>> +        << cast<FunctionDecl>((Decl *)Active->Entity)
>> +        << Active->InstantiationRange;
>> +      break;
>>     }
>>   }
>>  }
>> @@ -609,6 +640,7 @@
>>     switch(Active->Kind) {
>>     case
>> ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
>>     case ActiveTemplateInstantiation::TemplateInstantiation:
>> +    case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
>>       // This is a template instantiation, so there is no SFINAE.
>>       return llvm::Optional<TemplateDeductionInfo *>();
>>
>>
>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Apr 16
>> 19:58:00 2012
>> @@ -2215,6 +2215,194 @@
>>   return NewTInfo;
>>  }
>>
>> +/// Introduce the instantiated function parameters into the local
>> +/// instantiation scope, and set the parameter names to those used
>> +/// in the template.
>> +static void addInstantiatedParametersToScope(Sema &S, FunctionDecl
>> *Function,
>> +                                             const FunctionDecl
>> *PatternDecl,
>> +                                             LocalInstantiationScope
>> &Scope,
>> +                           const MultiLevelTemplateArgumentList
>> &TemplateArgs) {
>> +  unsigned FParamIdx = 0;
>> +  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
>> +    const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
>> +    if (!PatternParam->isParameterPack()) {
>> +      // Simple case: not a parameter pack.
>> +      assert(FParamIdx < Function->getNumParams());
>> +      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
>> +      FunctionParam->setDeclName(PatternParam->getDeclName());
>> +      Scope.InstantiatedLocal(PatternParam, FunctionParam);
>> +      ++FParamIdx;
>> +      continue;
>> +    }
>> +
>> +    // Expand the parameter pack.
>> +    Scope.MakeInstantiatedLocalArgPack(PatternParam);
>> +    unsigned NumArgumentsInExpansion
>> +      = S.getNumArgumentsInExpansion(PatternParam->getType(),
>> TemplateArgs);
>> +    for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
>> +      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
>> +      FunctionParam->setDeclName(PatternParam->getDeclName());
>> +      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
>> +      ++FParamIdx;
>> +    }
>> +  }
>> +}
>> +
>> +static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
>> +                                     const FunctionProtoType *Proto,
>> +                           const MultiLevelTemplateArgumentList
>> &TemplateArgs) {
>> +  // 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.
>> +  CXXRecordDecl *ThisContext = 0;
>> +  unsigned ThisTypeQuals = 0;
>> +  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
>> +    ThisContext = Method->getParent();
>> +    ThisTypeQuals = Method->getTypeQualifiers();
>> +  }
>> +  Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
>> +                                   SemaRef.getLangOpts().CPlusPlus0x);
>> +
>> +  // The function has an exception specification or a "noreturn"
>> +  // attribute. Substitute into each of the exception types.
>> +  SmallVector<QualType, 4> Exceptions;
>> +  for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
>> +    // FIXME: Poor location information!
>> +    if (const PackExpansionType *PackExpansion
>> +          = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
>> +      // We have a pack expansion. Instantiate it.
>> +      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
>> +
>>  SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
>> +                                              Unexpanded);
>> +      assert(!Unexpanded.empty() &&
>> +             "Pack expansion without parameter packs?");
>> +
>> +      bool Expand = false;
>> +      bool RetainExpansion = false;
>> +      llvm::Optional<unsigned> NumExpansions
>> +                                        =
>> PackExpansion->getNumExpansions();
>> +      if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
>> +                                                  SourceRange(),
>> +                                                  Unexpanded,
>> +                                                  TemplateArgs,
>> +                                                  Expand,
>> +                                                  RetainExpansion,
>> +                                                  NumExpansions))
>> +        break;
>> +
>> +      if (!Expand) {
>> +        // We can't expand this pack expansion into separate arguments
>> yet;
>> +        // just substitute into the pattern and create a new pack
>> expansion
>> +        // type.
>> +        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
>> +        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
>> +                                       TemplateArgs,
>> +                                     New->getLocation(),
>> New->getDeclName());
>> +        if (T.isNull())
>> +          break;
>> +
>> +        T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
>> +        Exceptions.push_back(T);
>> +        continue;
>> +      }
>> +
>> +      // Substitute into the pack expansion pattern for each template
>> +      bool Invalid = false;
>> +      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
>> +        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef,
>> ArgIdx);
>> +
>> +        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
>> +                                       TemplateArgs,
>> +                                     New->getLocation(),
>> New->getDeclName());
>> +        if (T.isNull()) {
>> +          Invalid = true;
>> +          break;
>> +        }
>> +
>> +        Exceptions.push_back(T);
>> +      }
>> +
>> +      if (Invalid)
>> +        break;
>> +
>> +      continue;
>> +    }
>> +
>> +    QualType T
>> +      = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
>> +                          New->getLocation(), New->getDeclName());
>> +    if (T.isNull() ||
>> +        SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
>> +      continue;
>> +
>> +    Exceptions.push_back(T);
>> +  }
>> +  Expr *NoexceptExpr = 0;
>> +  if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
>> +    EnterExpressionEvaluationContext Unevaluated(SemaRef,
>> +
>> Sema::ConstantEvaluated);
>> +    ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
>> +    if (E.isUsable())
>> +      E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
>> +
>> +    if (E.isUsable()) {
>> +      NoexceptExpr = E.take();
>> +      if (!NoexceptExpr->isTypeDependent() &&
>> +          !NoexceptExpr->isValueDependent())
>> +        NoexceptExpr =
>> SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
>> +          0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
>> +          /*AllowFold*/ false).take();
>> +    }
>> +  }
>> +
>> +  // Rebuild the function type
>> +  const FunctionProtoType *NewProto
>> +    = New->getType()->getAs<FunctionProtoType>();
>> +  assert(NewProto && "Template instantiation without function
>> prototype?");
>> +
>> +  FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
>> +  EPI.ExceptionSpecType = Proto->getExceptionSpecType();
>> +  EPI.NumExceptions = Exceptions.size();
>> +  EPI.Exceptions = Exceptions.data();
>> +  EPI.NoexceptExpr = NoexceptExpr;
>> +
>> +  New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
>> +
>> NewProto->arg_type_begin(),
>> +                                               NewProto->getNumArgs(),
>> +                                               EPI));
>> +}
>> +
>> +void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
>> +                                    FunctionDecl *Decl) {
>> +  FunctionDecl *Tmpl = Decl->getTemplateInstantiationPattern();
>> +  assert(Tmpl && "can't instantiate non-template");
>> +
>> +  if
>> (Decl->getType()->castAs<FunctionProtoType>()->getExceptionSpecType()
>> +        != EST_Uninstantiated)
>> +    return;
>> +
>> +  InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
>> +
>> InstantiatingTemplate::ExceptionSpecification());
>> +  if (Inst)
>> +    return;
>> +
>> +  // Enter the scope of this instantiation. We don't use
>> +  // PushDeclContext because we don't have a scope.
>> +  Sema::ContextRAII savedContext(*this, Decl);
>> +  LocalInstantiationScope Scope(*this);
>> +
>> +  MultiLevelTemplateArgumentList TemplateArgs =
>> +    getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
>> +
>> +  addInstantiatedParametersToScope(*this, Decl, Tmpl, Scope,
>> TemplateArgs);
>> +
>> +  const FunctionProtoType *Proto =
>> Tmpl->getType()->castAs<FunctionProtoType>();
>> +  ::InstantiateExceptionSpec(*this, Decl, Proto, TemplateArgs);
>> +}
>> +
>>  /// \brief Initializes the common fields of an instantiation function
>>  /// declaration (New) from the corresponding fields of its template
>> (Tmpl).
>>  ///
>> @@ -2252,135 +2440,32 @@
>>   assert(Proto && "Function template without prototype?");
>>
>>   if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
>> -    // 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.
>> -    CXXRecordDecl *ThisContext = 0;
>> -    unsigned ThisTypeQuals = 0;
>> -    if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
>> -      ThisContext = Method->getParent();
>> -      ThisTypeQuals = Method->getTypeQualifiers();
>> -    }
>> -    Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
>> -                                     SemaRef.getLangOpts().CPlusPlus0x);
>> -
>> -
>> -    // The function has an exception specification or a "noreturn"
>> -    // attribute. Substitute into each of the exception types.
>> -    SmallVector<QualType, 4> Exceptions;
>> -    for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
>> -      // FIXME: Poor location information!
>> -      if (const PackExpansionType *PackExpansion
>> -            = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
>> -        // We have a pack expansion. Instantiate it.
>> -        SmallVector<UnexpandedParameterPack, 2> Unexpanded;
>> -
>>  SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
>> -                                                Unexpanded);
>> -        assert(!Unexpanded.empty() &&
>> -               "Pack expansion without parameter packs?");
>> -
>> -        bool Expand = false;
>> -        bool RetainExpansion = false;
>> -        llvm::Optional<unsigned> NumExpansions
>> -                                          =
>> PackExpansion->getNumExpansions();
>> -        if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
>> -                                                    SourceRange(),
>> -                                                    Unexpanded,
>> -                                                    TemplateArgs,
>> -                                                    Expand,
>> -                                                    RetainExpansion,
>> -                                                    NumExpansions))
>> -          break;
>> -
>> -        if (!Expand) {
>> -          // We can't expand this pack expansion into separate arguments
>> yet;
>> -          // just substitute into the pattern and create a new pack
>> expansion
>> -          // type.
>> -          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef,
>> -1);
>> -          QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
>> -                                         TemplateArgs,
>> -                                       New->getLocation(),
>> New->getDeclName());
>> -          if (T.isNull())
>> -            break;
>> -
>> -          T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
>> -          Exceptions.push_back(T);
>> -          continue;
>> -        }
>> -
>> -        // Substitute into the pack expansion pattern for each template
>> -        bool Invalid = false;
>> -        for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
>> -          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef,
>> ArgIdx);
>> -
>> -          QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
>> -                                         TemplateArgs,
>> -                                       New->getLocation(),
>> New->getDeclName());
>> -          if (T.isNull()) {
>> -            Invalid = true;
>> -            break;
>> -          }
>> -
>> -          Exceptions.push_back(T);
>> -        }
>> -
>> -        if (Invalid)
>> -          break;
>> -
>> -        continue;
>> -      }
>> -
>> -      QualType T
>> -        = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
>> -                            New->getLocation(), New->getDeclName());
>> -      if (T.isNull() ||
>> -          SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
>> -        continue;
>> +    FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
>>
>> -      Exceptions.push_back(T);
>> -    }
>> -    Expr *NoexceptExpr = 0;
>> -    if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
>> -      EnterExpressionEvaluationContext Unevaluated(SemaRef,
>> -
>> Sema::ConstantEvaluated);
>> -      ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
>> -      if (E.isUsable())
>> -        E = SemaRef.CheckBooleanCondition(E.get(),
>> E.get()->getLocStart());
>> -
>> -      if (E.isUsable()) {
>> -        NoexceptExpr = E.take();
>> -        if (!NoexceptExpr->isTypeDependent() &&
>> -            !NoexceptExpr->isValueDependent())
>> -          NoexceptExpr =
>> SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
>> -            0,
>> SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
>> -            /*AllowFold*/ false).take();
>> -      }
>> +    // DR1330: In C++11, defer instantiation of a non-trivial
>> +    // exception specification.
>> +    if (SemaRef.getLangOpts().CPlusPlus0x &&
>> +        EPI.ExceptionSpecType != EST_None &&
>> +        EPI.ExceptionSpecType != EST_DynamicNone &&
>> +        EPI.ExceptionSpecType != EST_BasicNoexcept) {
>> +      // Mark the function has having an uninstantiated exception
>> specification.
>> +      const FunctionProtoType *NewProto
>> +        = New->getType()->getAs<FunctionProtoType>();
>> +      assert(NewProto && "Template instantiation without function
>> prototype?");
>> +      EPI = NewProto->getExtProtoInfo();
>> +      EPI.ExceptionSpecType = EST_Uninstantiated;
>> +      EPI.ExceptionSpecDecl = New;
>> +
>>  New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
>> +
>> NewProto->arg_type_begin(),
>> +
>> NewProto->getNumArgs(),
>> +                                                   EPI));
>> +    } else {
>> +      ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
>>     }
>> -
>> -    // Rebuild the function type
>> -
>> -    FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
>> -    EPI.ExceptionSpecType = Proto->getExceptionSpecType();
>> -    EPI.NumExceptions = Exceptions.size();
>> -    EPI.Exceptions = Exceptions.data();
>> -    EPI.NoexceptExpr = NoexceptExpr;
>> -    EPI.ExtInfo = Proto->getExtInfo();
>> -
>> -    const FunctionProtoType *NewProto
>> -      = New->getType()->getAs<FunctionProtoType>();
>> -    assert(NewProto && "Template instantiation without function
>> prototype?");
>> -
>>  New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
>> -
>> NewProto->arg_type_begin(),
>> -                                                 NewProto->getNumArgs(),
>> -                                                 EPI));
>>   }
>>
>> -  const FunctionDecl* Definition = Tmpl;
>> -
>>   // Get the definition. Leaves the variable unchanged if undefined.
>> +  const FunctionDecl *Definition = Tmpl;
>>   Tmpl->isDefined(Definition);
>>
>>   SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
>> @@ -2538,33 +2623,8 @@
>>   MultiLevelTemplateArgumentList TemplateArgs =
>>     getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
>>
>> -  // Introduce the instantiated function parameters into the local
>> -  // instantiation scope, and set the parameter names to those used
>> -  // in the template.
>> -  unsigned FParamIdx = 0;
>> -  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
>> -    const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
>> -    if (!PatternParam->isParameterPack()) {
>> -      // Simple case: not a parameter pack.
>> -      assert(FParamIdx < Function->getNumParams());
>> -      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
>> -      FunctionParam->setDeclName(PatternParam->getDeclName());
>> -      Scope.InstantiatedLocal(PatternParam, FunctionParam);
>> -      ++FParamIdx;
>> -      continue;
>> -    }
>> -
>> -    // Expand the parameter pack.
>> -    Scope.MakeInstantiatedLocalArgPack(PatternParam);
>> -    unsigned NumArgumentsInExpansion
>> -      = getNumArgumentsInExpansion(PatternParam->getType(),
>> TemplateArgs);
>> -    for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
>> -      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
>> -      FunctionParam->setDeclName(PatternParam->getDeclName());
>> -      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
>> -      ++FParamIdx;
>> -    }
>> -  }
>> +  addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
>> +                                   TemplateArgs);
>>
>>   if (PatternDecl->isDefaulted()) {
>>     ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
>>
>> Modified: cfe/trunk/lib/Sema/TreeTransform.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>> +++ cfe/trunk/lib/Sema/TreeTransform.h Mon Apr 16 19:58:00 2012
>> @@ -4181,10 +4181,7 @@
>>                                                    unsigned
>> ThisTypeQuals) {
>>   // Transform the parameters and return type.
>>   //
>> -  // We instantiate in source order, with the return type first followed
>> by
>> -  // the parameters, because users tend to expect this (even if they
>> shouldn't
>> -  // rely on it!).
>> -  //
>> +  // We are required to instantiate the params and return type in source
>> order.
>>   // When the function has a trailing return type, we instantiate the
>>   // parameters before the return type,  since the return type can then
>> refer
>>   // to the parameters themselves (via decltype, sizeof, etc.).
>> @@ -4230,6 +4227,8 @@
>>       return QualType();
>>   }
>>
>> +  // FIXME: Need to transform the exception-specification too.
>> +
>>   QualType Result = TL.getType();
>>   if (getDerived().AlwaysRebuild() ||
>>       ResultType != T->getResultType() ||
>>
>> Modified: cfe/trunk/test/CXX/except/except.spec/p1.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/except/except.spec/p1.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CXX/except/except.spec/p1.cpp (original)
>> +++ cfe/trunk/test/CXX/except/except.spec/p1.cpp Mon Apr 16 19:58:00 2012
>> @@ -65,7 +65,7 @@
>>   }
>>
>>   template<typename T>
>> -  void g(T x) noexcept((sizeof(T) == sizeof(int)) || f(x)) { }
>> +  void g(T x) noexcept((sizeof(T) == sizeof(int)) || noexcept(f(x))) { }
>>
>>   void h() {
>>     g(1);
>> @@ -77,5 +77,5 @@
>>     static int f() noexcept(1/X) { return 10; }  //
>> expected-error{{argument to noexcept specifier must be a constant
>> expression}} expected-note{{division by zero}}
>>   };
>>
>> -  void g() { A<0>::f(); } // expected-note{{in instantiation of template
>> class 'PR11084::A<0>' requested here}}
>> +  void g() { A<0>::f(); } // expected-note{{in instantiation of
>> exception specification for 'f' requested here}}
>>  }
>>
>> Added: cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp?rev=154886&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp (added)
>> +++ cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp Mon Apr 16
>> 19:58:00 2012
>> @@ -0,0 +1,18 @@
>> +// RUN: %clang_cc1 -std=c++11 -verify -emit-llvm %s -o - | FileCheck %s
>> +
>> +template<typename T> void f() noexcept(sizeof(T) == 4);
>> +
>> +void g() {
>> +  // CHECK: declare void @_Z1fIiEvv() nounwind
>> +  f<int>();
>> +  // CHECK: declare void @_Z1fIA2_iEvv()
>> +  f<int[2]>();
>> +  // CHECK: declare void @_Z1fIfEvv() nounwind
>> +  void (*f1)() = &f<float>;
>> +  // CHECK: declare void @_Z1fIdEvv()
>> +  void (*f2)() = &f<double>;
>> +  // CHECK: declare void @_Z1fIA4_cEvv() nounwind
>> +  (void)&f<char[4]>;
>> +  // CHECK: declare void @_Z1fIcEvv()
>> +  (void)&f<char>;
>> +}
>>
>> Modified: cfe/trunk/test/SemaTemplate/instantiate-declref.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-declref.cpp?rev=154886&r1=154885&r2=154886&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/SemaTemplate/instantiate-declref.cpp (original)
>> +++ cfe/trunk/test/SemaTemplate/instantiate-declref.cpp Mon Apr 16
>> 19:58:00 2012
>> @@ -105,3 +105,13 @@
>>   }
>>   template void f(int const &); // expected-note {{requested here}}
>>  }
>> +
>> +namespace test2 {
>> +  template<typename T> void f() {
>> +    T::error; // expected-error {{no member}}
>> +  }
>> +  void g() {
>> +    // This counts as an odr-use, so should trigger the instantiation of
>> f<int>.
>> +    (void)&f<int>; // expected-note {{here}}
>> +  }
>> +}
>>
>> Added: cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=154886&view=auto
>>
>> ==============================================================================
>> --- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
>> (added)
>> +++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Mon
>> Apr 16 19:58:00 2012
>> @@ -0,0 +1,107 @@
>> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -ftemplate-depth 16
>> %s
>> +
>> +// DR1330: an exception specification for a function template is only
>> +// instantiated when it is needed.
>> +
>> +template<typename T> void f1(T*) throw(T); // expected-error{{incomplete
>> type 'Incomplete' is not allowed in exception specification}}
>> +struct Incomplete; // expected-note{{forward}}
>> +
>> +void test_f1(Incomplete *incomplete_p, int *int_p) {
>> +  f1(int_p);
>> +  f1(incomplete_p); // expected-note{{instantiation of exception spec}}
>> +}
>> +
>> +template<typename T> struct A {
>> +  template<typename U> struct B {
>> +    static void f() noexcept(A<U>().n);
>> +  };
>> +
>> +  constexpr A() : n(true) {}
>> +  bool n;
>> +};
>> +
>> +static_assert(noexcept(A<int>::B<char>::f()), "");
>> +
>> +template<unsigned N> struct S {
>> +  static void recurse() noexcept(noexcept(S<N+1>::recurse())); // \
>> +  // expected-error {{no member named 'recurse'}} \
>> +  // expected-note 9{{instantiation of exception spec}}
>> +};
>> +decltype(S<0>::recurse()) *pVoid1 = 0; // ok, exception spec not needed
>> +decltype(&S<0>::recurse) pFn = 0; // ok, exception spec not needed
>> +
>> +template<> struct S<10> {};
>> +void (*pFn2)() noexcept = &S<0>::recurse; // expected-note
>> {{instantiation of exception spec}}
>> +
>> +
>> +template<typename T> T go(T a) noexcept(noexcept(go(a))); // \
>> +// expected-error 16{{call to function 'go' that is neither visible}} \
>> +// expected-note 16{{'go' should be declared prior to the call site}} \
>> +// expected-error {{recursive template instantiation exceeded maximum
>> depth of 16}} \
>> +// expected-error {{use of undeclared identifier 'go'}} \
>> +
>> +void f() {
>> +  int k = go(0); // \
>> +  // expected-note {{in instantiation of exception specification for
>> 'go<int>' requested here}}
>> +}
>> +
>> +
>> +namespace dr1330_example {
>> +  template <class T> struct A {
>> +    void f(...) throw (typename T::X); // expected-error {{'int'}}
>> +    void f(int);
>> +  };
>> +
>> +  int main() {
>> +    A<int>().f(42);
>> +  }
>> +
>> +  int test2() {
>> +    struct S {
>> +      template<typename T>
>> +      static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; }
>> // \
>> +      // expected-note {{instantiation of exception spec}}
>> +      typedef decltype(f<S>()) X;
>> +    };
>> +    S().f<S>(); // ok
>> +    S().f<int>(); // expected-note {{instantiation of exception spec}}
>> +  }
>> +}
>> +
>> +namespace core_19754_example {
>> +  template<typename T> T declval() noexcept;
>> +
>> +  template<typename T, typename = decltype(T(declval<T&&>()))>
>> +  struct is_movable { static const bool value = true; };
>> +
>> +  template<typename T>
>> +  struct wrap {
>> +    T val;
>> +    void irrelevant(wrap &p) noexcept(is_movable<T>::value);
>> +  };
>> +
>> +  template<typename T>
>> +  struct base {
>> +     base() {}
>> +     base(const typename T::type1 &);
>> +     base(const typename T::type2 &);
>> +  };
>> +
>> +  template<typename T>
>> +  struct type1 {
>> +     wrap<typename T::base> base;
>> +  };
>> +
>> +  template<typename T>
>> +  struct type2 {
>> +     wrap<typename T::base> base;
>> +  };
>> +
>> +  struct types {
>> +     typedef base<types> base;
>> +     typedef type1<types> type1;
>> +     typedef type2<types> type2;
>> +  };
>> +
>> +  base<types> val = base<types>();
>> +}
>>
>>
>> _______________________________________________
>> 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/20120418/8d57a2ff/attachment.html>


More information about the cfe-commits mailing list