From cafeb948e6067b8dc897c441da522367917b06f9 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 7 Jun 2013 02:33:37 +0000 Subject: [PATCH] PR16243: Use CXXThisOverride during template instantiation, and fix up the places which weren't setting it up properly. This allows us to get the right cv-qualifiers for 'this' when it appears outside a method body in a class template. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183483 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDecl.cpp | 5 ++- lib/Sema/SemaTemplateInstantiate.cpp | 8 +++++ lib/Sema/SemaTemplateInstantiateDecl.cpp | 12 +++++-- lib/Sema/TreeTransform.h | 13 +------- .../expr.prim/expr.prim.general/p3-0x.cpp | 32 +++++++++++++++++-- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index cb0dc374ae..03e4879db6 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1063,9 +1063,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, RecordDecl *RD = dyn_cast_or_null(D->getDeclContext()); // Allow 'this' within late-parsed attributes. - Sema::CXXThisScopeRAII ThisScope(Actions, RD, - /*TypeQuals=*/0, - ND && RD && ND->isCXXInstanceMember()); + Sema::CXXThisScopeRAII ThisScope(Actions, RD, /*TypeQuals=*/0, + ND && ND->isCXXInstanceMember()); if (LA.Decls.size() == 1) { // If the Decl is templatized, add template parameters to scope. diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 60f447711e..5e3ced47f4 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -2080,6 +2080,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, E = LateAttrs.end(); I != E; ++I) { assert(CurrentInstantiationScope == Instantiator.getStartingScope()); CurrentInstantiationScope = I->Scope; + + // Allow 'this' within late-parsed attributes. + NamedDecl *ND = dyn_cast(I->NewDecl); + CXXRecordDecl *ThisContext = + dyn_cast_or_null(ND->getDeclContext()); + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + ND && ND->isCXXInstanceMember()); + Attr *NewAttr = instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs); I->NewDecl->addAttr(NewAttr); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 09ddd9db65..9d1757d878 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -142,6 +142,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); } else { + // Allow 'this' within late-parsed attributes. + NamedDecl *ND = dyn_cast(New); + CXXRecordDecl *ThisContext = + dyn_cast_or_null(ND->getDeclContext()); + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0, + ND && ND->isCXXInstanceMember()); + Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); if (NewAttr) @@ -2449,7 +2456,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, CXXRecordDecl *ThisContext = 0; unsigned ThisTypeQuals = 0; if (CXXMethodDecl *Method = dyn_cast(D)) { - ThisContext = Method->getParent(); + ThisContext = cast(Owner); ThisTypeQuals = Method->getTypeQualifiers(); } @@ -2585,8 +2592,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, bool Expand = false; bool RetainExpansion = false; - Optional NumExpansions - = PackExpansion->getNumExpansions(); + Optional NumExpansions = PackExpansion->getNumExpansions(); if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), SourceRange(), Unexpanded, diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7d225cc792..fe49153d99 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7265,18 +7265,7 @@ TreeTransform::TransformCXXNullPtrLiteralExpr( template ExprResult TreeTransform::TransformCXXThisExpr(CXXThisExpr *E) { - DeclContext *DC = getSema().getFunctionLevelDeclContext(); - QualType T; - if (CXXMethodDecl *MD = dyn_cast(DC)) - T = MD->getThisType(getSema().Context); - else if (CXXRecordDecl *Record = dyn_cast(DC)) { - T = getSema().Context.getPointerType( - getSema().Context.getRecordType(Record)); - } else { - assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() && - "this in the wrong scope?"); - return ExprError(); - } + QualType T = getSema().getCurrentThisType(); if (!getDerived().AlwaysRebuild() && T == E->getType()) { // Make sure that we capture 'this'. diff --git a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp index 66579915c7..fd90482ae8 100644 --- a/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp @@ -30,16 +30,44 @@ struct C { float &f(T*) const noexcept; T* ptr; - auto g1() noexcept(noexcept(f(ptr))) -> decltype(f((*this).ptr)); + auto g1() noexcept(noexcept(f(ptr))) -> decltype(f(ptr)); auto g2() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(ptr)); + auto g3() noexcept(noexcept(f(this->ptr))) -> decltype(f((*this).ptr)); + auto g4() const noexcept(noexcept(f(((this))->ptr))) -> decltype(f(this->ptr)); + auto g5() noexcept(noexcept(this->f(ptr))) -> decltype(this->f(ptr)); + auto g6() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(ptr)); + auto g7() noexcept(noexcept(this->f(this->ptr))) -> decltype(this->f((*this).ptr)); + auto g8() const noexcept(noexcept(this->f(((this))->ptr))) -> decltype(this->f(this->ptr)); }; void test_C(C ci) { - int *p = 0; int &ir = ci.g1(); float &fr = ci.g2(); + int &ir2 = ci.g3(); + float &fr2 = ci.g4(); + int &ir3 = ci.g5(); + float &fr3 = ci.g6(); + int &ir4 = ci.g7(); + float &fr4 = ci.g8(); static_assert(!noexcept(ci.g1()), "exception-specification failure"); static_assert(noexcept(ci.g2()), "exception-specification failure"); + static_assert(!noexcept(ci.g3()), "exception-specification failure"); + static_assert(noexcept(ci.g4()), "exception-specification failure"); + static_assert(!noexcept(ci.g5()), "exception-specification failure"); + static_assert(noexcept(ci.g6()), "exception-specification failure"); + static_assert(!noexcept(ci.g7()), "exception-specification failure"); + static_assert(noexcept(ci.g8()), "exception-specification failure"); +} + +namespace PR14263 { + template struct X { + void f(); + T f() const; + + auto g() -> decltype(this->f()) { return f(); } + auto g() const -> decltype(this->f()) { return f(); } + }; + template struct X; } namespace PR10036 { -- 2.40.0