[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