[cfe-commits] r155076 - in /cfe/trunk: include/clang/AST/Type.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/cxx11-exception-spec.cpp test/SemaTemplate/instantiate-exceptio
Douglas Gregor
dgregor at apple.com
Thu Apr 19 07:45:49 PDT 2012
Approved.
On Apr 18, 2012, at 6:25 PM, Richard Smith wrote:
> This fixes release blocker PR12586. Requesting branch merge approval! :)
>
> On Wed, Apr 18, 2012 at 5:08 PM, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> Author: rsmith
> Date: Wed Apr 18 19:08:28 2012
> New Revision: 155076
>
> URL: http://llvm.org/viewvc/llvm-project?rev=155076&view=rev
> Log:
> PR 12586: Fix assert while running libc++ testsuite: deal with exception
> specifications on member function templates of class templates and other such
> nested beasties. Store the function template from which we are to instantiate
> an exception specification rather than trying to deduce it. Plus some
> additional test cases.
>
> Modified:
> cfe/trunk/include/clang/AST/Type.h
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/Type.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
> cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
>
> Modified: cfe/trunk/include/clang/AST/Type.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Type.h (original)
> +++ cfe/trunk/include/clang/AST/Type.h Wed Apr 18 19:08:28 2012
> @@ -2701,7 +2701,8 @@
> ExtProtoInfo() :
> Variadic(false), HasTrailingReturn(false), TypeQuals(0),
> ExceptionSpecType(EST_None), RefQualifier(RQ_None),
> - NumExceptions(0), Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0),
> + NumExceptions(0), Exceptions(0), NoexceptExpr(0),
> + ExceptionSpecDecl(0), ExceptionSpecTemplate(0),
> ConsumedArguments(0) {}
>
> FunctionType::ExtInfo ExtInfo;
> @@ -2714,6 +2715,7 @@
> const QualType *Exceptions;
> Expr *NoexceptExpr;
> FunctionDecl *ExceptionSpecDecl;
> + FunctionDecl *ExceptionSpecTemplate;
> const bool *ConsumedArguments;
> };
>
> @@ -2759,9 +2761,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.
> + // ExceptionSpecDecl, ExceptionSpecTemplate - Instead of Exceptions, there may
> + // be a pair of FunctionDecl* pointing to the function which should be used to
> + // instantiate this function type's exception specification, and the function
> + // from which it should be instantiated.
>
> // ConsumedArgs - A variable size array, following Exceptions
> // and of length NumArgs, holding flags indicating which arguments
> @@ -2804,6 +2807,7 @@
> EPI.NoexceptExpr = getNoexceptExpr();
> } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
> EPI.ExceptionSpecDecl = getExceptionSpecDecl();
> + EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
> }
> if (hasAnyConsumedArgs())
> EPI.ConsumedArguments = getConsumedArgsBuffer();
> @@ -2847,10 +2851,22 @@
> // NoexceptExpr sits where the arguments end.
> return *reinterpret_cast<Expr *const *>(arg_type_end());
> }
> + /// \brief If this function type has an uninstantiated exception
> + /// specification, this is the function whose exception specification
> + /// is represented by this type.
> FunctionDecl *getExceptionSpecDecl() const {
> if (getExceptionSpecType() != EST_Uninstantiated)
> return 0;
> - return *reinterpret_cast<FunctionDecl * const *>(arg_type_end());
> + return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[0];
> + }
> + /// \brief If this function type has an uninstantiated exception
> + /// specification, this is the function whose exception specification
> + /// should be instantiated to find the exception specification for
> + /// this type.
> + FunctionDecl *getExceptionSpecTemplate() const {
> + if (getExceptionSpecType() != EST_Uninstantiated)
> + return 0;
> + return reinterpret_cast<FunctionDecl * const *>(arg_type_end())[1];
> }
> bool isNothrow(ASTContext &Ctx) const {
> ExceptionSpecificationType EST = getExceptionSpecType();
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Apr 18 19:08:28 2012
> @@ -2195,7 +2195,7 @@
> else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
> Size += sizeof(Expr*);
> } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
> - Size += sizeof(FunctionDecl*);
> + Size += 2 * sizeof(FunctionDecl*);
> }
> if (EPI.ConsumedArguments)
> Size += NumArgs * sizeof(bool);
>
> Modified: cfe/trunk/lib/AST/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Type.cpp (original)
> +++ cfe/trunk/lib/AST/Type.cpp Wed Apr 18 19:08:28 2012
> @@ -1550,7 +1550,8 @@
> // Store the function decl from which we will resolve our
> // exception specification.
> FunctionDecl **slot = reinterpret_cast<FunctionDecl**>(argSlot + numArgs);
> - *slot = epi.ExceptionSpecDecl;
> + slot[0] = epi.ExceptionSpecDecl;
> + slot[1] = epi.ExceptionSpecTemplate;
> // This exception specification doesn't make the type dependent, because
> // it's not instantiated as part of instantiating the type.
> }
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Apr 18 19:08:28 2012
> @@ -9776,9 +9776,8 @@
>
> // Instantiate the exception specification for any function which is
> // used: CodeGen will need it.
> - if (Func->getTemplateInstantiationPattern() &&
> - Func->getType()->castAs<FunctionProtoType>()->getExceptionSpecType()
> - == EST_Uninstantiated)
> + const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
> + if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated)
> InstantiateExceptionSpec(Loc, Func);
>
> // Implicit instantiation of function templates and member functions of
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Apr 18 19:08:28 2012
> @@ -2251,6 +2251,8 @@
> static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
> const FunctionProtoType *Proto,
> const MultiLevelTemplateArgumentList &TemplateArgs) {
> + assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
> +
> // 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
> @@ -2377,20 +2379,8 @@
>
> void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
> FunctionDecl *Decl) {
> - // Find the template declaration which contains the exception specification.
> - // Per [except.spec]p4, prefer the exception spec on the primary template
> - // if this is an explicit instantiation.
> - FunctionDecl *Tmpl = 0;
> - if (Decl->getPrimaryTemplate())
> - Tmpl = Decl->getPrimaryTemplate()->getTemplatedDecl();
> - else if (FunctionDecl *MemTmpl = Decl->getInstantiatedFromMemberFunction())
> - Tmpl = MemTmpl;
> - else
> - Tmpl = Decl->getTemplateInstantiationPattern();
> - assert(Tmpl && "can't instantiate non-template");
> -
> - if (Decl->getType()->castAs<FunctionProtoType>()->getExceptionSpecType()
> - != EST_Uninstantiated)
> + const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();
> + if (Proto->getExceptionSpecType() != EST_Uninstantiated)
> return;
>
> InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
> @@ -2406,10 +2396,12 @@
> MultiLevelTemplateArgumentList TemplateArgs =
> getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
>
> - addInstantiatedParametersToScope(*this, Decl, Tmpl, Scope, TemplateArgs);
> + FunctionDecl *Template = Proto->getExceptionSpecTemplate();
> + addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
>
> - const FunctionProtoType *Proto = Tmpl->getType()->castAs<FunctionProtoType>();
> - ::InstantiateExceptionSpec(*this, Decl, Proto, TemplateArgs);
> + ::InstantiateExceptionSpec(*this, Decl,
> + Template->getType()->castAs<FunctionProtoType>(),
> + TemplateArgs);
> }
>
> /// \brief Initializes the common fields of an instantiation function
> @@ -2457,6 +2449,10 @@
> EPI.ExceptionSpecType != EST_None &&
> EPI.ExceptionSpecType != EST_DynamicNone &&
> EPI.ExceptionSpecType != EST_BasicNoexcept) {
> + FunctionDecl *ExceptionSpecTemplate = Tmpl;
> + if (EPI.ExceptionSpecType == EST_Uninstantiated)
> + ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
> +
> // Mark the function has having an uninstantiated exception specification.
> const FunctionProtoType *NewProto
> = New->getType()->getAs<FunctionProtoType>();
> @@ -2464,6 +2460,7 @@
> EPI = NewProto->getExtProtoInfo();
> EPI.ExceptionSpecType = EST_Uninstantiated;
> EPI.ExceptionSpecDecl = New;
> + EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
> New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
> NewProto->arg_type_begin(),
> NewProto->getNumArgs(),
>
> Modified: cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp?rev=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/cxx11-exception-spec.cpp Wed Apr 18 19:08:28 2012
> @@ -3,9 +3,11 @@
> void h();
>
> template<typename T> void f() noexcept(sizeof(T) == 4) { h(); }
> +template<typename T> void g() noexcept(sizeof(T) == 4);
>
> template<typename T> struct S {
> static void f() noexcept(sizeof(T) == 4) { h(); }
> + static void g() noexcept(sizeof(T) == 4);
> };
>
> // CHECK: define {{.*}} @_Z1fIsEvv() {
> @@ -30,7 +32,7 @@
> // CHECK: define {{.*}} @_ZN1SIA2_DsE1fEv() nounwind
> template void S<char16_t[2]>::f();
>
> -void g() {
> +void h() {
> // CHECK: define {{.*}} @_Z1fIiEvv() nounwind {
> f<int>();
> // CHECK: define {{.*}} @_Z1fIA2_iEvv() {
> @@ -64,3 +66,55 @@
> // CHECK-NOT: nounwind
> (void)&S<char>::f;
> }
> +
> +// CHECK: define {{.*}} @_Z1iv
> +void i() {
> + // CHECK: declare {{.*}} @_Z1gIiEvv() nounwind
> + g<int>();
> + // CHECK: declare {{.*}} @_Z1gIA2_iEvv()
> + // CHECK-NOT: nounwind
> + g<int[2]>();
> +
> + // CHECK: declare {{.*}} @_ZN1SIiE1gEv() nounwind
> + S<int>::g();
> + // CHECK: declare {{.*}} @_ZN1SIA2_iE1gEv()
> + // CHECK-NOT: nounwind
> + S<int[2]>::g();
> +
> + // CHECK: declare {{.*}} @_Z1gIfEvv() nounwind
> + void (*g1)() = &g<float>;
> + // CHECK: declare {{.*}} @_Z1gIdEvv()
> + // CHECK-NOT: nounwind
> + void (*g2)() = &g<double>;
> +
> + // CHECK: declare {{.*}} @_ZN1SIfE1gEv() nounwind
> + void (*g3)() = &S<float>::g;
> + // CHECK: declare {{.*}} @_ZN1SIdE1gEv()
> + // CHECK-NOT: nounwind
> + void (*g4)() = &S<double>::g;
> +
> + // CHECK: declare {{.*}} @_Z1gIA4_cEvv() nounwind
> + (void)&g<char[4]>;
> + // CHECK: declare {{.*}} @_Z1gIcEvv()
> + // CHECK-NOT: nounwind
> + (void)&g<char>;
> +
> + // CHECK: declare {{.*}} @_ZN1SIA4_cE1gEv() nounwind
> + (void)&S<char[4]>::g;
> + // CHECK: declare {{.*}} @_ZN1SIcE1gEv()
> + // CHECK-NOT: nounwind
> + (void)&S<char>::g;
> +}
> +
> +template<typename T> struct Nested {
> + template<bool b, typename U> void f() noexcept(sizeof(T) == sizeof(U));
> +};
> +
> +// CHECK: define {{.*}} @_Z1jv
> +void j() {
> + // CHECK: declare {{.*}} @_ZN6NestedIiE1fILb1EcEEvv(
> + // CHECK-NOT: nounwind
> + Nested<int>().f<true, char>();
> + // CHECK: declare {{.*}} @_ZN6NestedIlE1fILb0ElEEvv({{.*}}) nounwind
> + Nested<long>().f<false, long>();
> +}
>
> Modified: 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=155076&r1=155075&r2=155076&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Wed Apr 18 19:08:28 2012
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -ftemplate-depth 16 %s
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -ftemplate-depth 16 -fcxx-exceptions -fexceptions %s
>
> // DR1330: an exception specification for a function template is only
> // instantiated when it is needed.
> @@ -31,7 +31,7 @@
> 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}}
> +void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of exception spec}} expected-error {{not superset}}
>
>
> template<typename T> T go(T a) noexcept(noexcept(go(a))); // \
> @@ -118,3 +118,16 @@
> f2(0); // expected-error {{ambiguous}}
> }
> }
> +
> +struct Exc1 { char c[4]; };
> +struct Exc2 { double x, y, z; };
> +struct Base {
> + virtual void f() noexcept; // expected-note {{overridden}}
> +};
> +template<typename T> struct Derived : Base {
> + void f() noexcept (sizeof(T) == 4); // expected-error {{is more lax}}
> + void g() noexcept (T::error);
> +};
> +
> +Derived<Exc1> d1; // ok
> +Derived<Exc2> d2; // expected-note {{in instantiation of}}
>
>
> _______________________________________________
> 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/20120419/707f37f4/attachment.html>
More information about the cfe-commits
mailing list