r183483 - PR16243: Use CXXThisOverride during template instantiation, and fix up the

Richard Smith richard-llvm at metafoo.co.uk
Thu Jun 6 19:33:37 PDT 2013


Author: rsmith
Date: Thu Jun  6 21:33:37 2013
New Revision: 183483

URL: http://llvm.org/viewvc/llvm-project?rev=183483&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=183483&r1=183482&r2=183483&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Jun  6 21:33:37 2013
@@ -1063,9 +1063,8 @@ void Parser::ParseLexedAttribute(LatePar
     RecordDecl *RD = dyn_cast_or_null<RecordDecl>(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.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=183483&r1=183482&r2=183483&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Jun  6 21:33:37 2013
@@ -2080,6 +2080,14 @@ Sema::InstantiateClass(SourceLocation Po
        E = LateAttrs.end(); I != E; ++I) {
     assert(CurrentInstantiationScope == Instantiator.getStartingScope());
     CurrentInstantiationScope = I->Scope;
+
+    // Allow 'this' within late-parsed attributes.
+    NamedDecl *ND = dyn_cast<NamedDecl>(I->NewDecl);
+    CXXRecordDecl *ThisContext =
+        dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext());
+    CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/0,
+                               ND && ND->isCXXInstanceMember());
+
     Attr *NewAttr =
       instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
     I->NewDecl->addAttr(NewAttr);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=183483&r1=183482&r2=183483&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Jun  6 21:33:37 2013
@@ -142,6 +142,13 @@ void Sema::InstantiateAttrs(const MultiL
         Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
       LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
     } else {
+      // Allow 'this' within late-parsed attributes.
+      NamedDecl *ND = dyn_cast<NamedDecl>(New);
+      CXXRecordDecl *ThisContext =
+          dyn_cast_or_null<CXXRecordDecl>(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::SubstFunctionT
   CXXRecordDecl *ThisContext = 0;
   unsigned ThisTypeQuals = 0;
   if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
-    ThisContext = Method->getParent();
+    ThisContext = cast<CXXRecordDecl>(Owner);
     ThisTypeQuals = Method->getTypeQualifiers();
   }
   
@@ -2585,8 +2592,7 @@ static void InstantiateExceptionSpec(Sem
 
       bool Expand = false;
       bool RetainExpansion = false;
-      Optional<unsigned> NumExpansions
-                                        = PackExpansion->getNumExpansions();
+      Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
       if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
                                                   SourceRange(),
                                                   Unexpanded,

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183483&r1=183482&r2=183483&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jun  6 21:33:37 2013
@@ -7265,18 +7265,7 @@ TreeTransform<Derived>::TransformCXXNull
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
-  DeclContext *DC = getSema().getFunctionLevelDeclContext();
-  QualType T;
-  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC))
-    T = MD->getThisType(getSema().Context);
-  else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(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'.

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp?rev=183483&r1=183482&r2=183483&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp Thu Jun  6 21:33:37 2013
@@ -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<int> 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<typename T> 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<int>;
 }
 
 namespace PR10036 {





More information about the cfe-commits mailing list