This fixes release blocker PR12586. Requesting branch merge approval! :) On Wed, Apr 18, 2012 at 5:08 PM, Richard Smith <[email protected]>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 > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
