[cfe-commits] r87000 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiate.cpp test/SemaTemplate/instantiate-member-pointers.cpp

Douglas Gregor dgregor at apple.com
Thu Nov 12 09:40:13 PST 2009


Author: dgregor
Date: Thu Nov 12 11:40:13 2009
New Revision: 87000

URL: http://llvm.org/viewvc/llvm-project?rev=87000&view=rev
Log:
When instantiating a reference to a non-type template parameter of pointer to
member type (e.g., T Class::*Member), build a pointer-to-member
constant expression. Previously, we we just building a simple
declaration reference expression, which meant that the expression was
not treated as a pointer to member.


Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=87000&r1=86999&r2=87000&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Nov 12 11:40:13 2009
@@ -700,7 +700,6 @@
   NamedDecl *D = E->getDecl();
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     if (NTTP->getDepth() < TemplateArgs.getNumLevels()) {
-      
       // If the corresponding template argument is NULL or non-existent, it's
       // because we are performing instantiation from explicitly-specified
       // template arguments in a function template, but there were some
@@ -725,7 +724,38 @@
         if (!VD)
           return SemaRef.ExprError();
 
-        return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+        if (VD->getDeclContext()->isRecord()) {
+          // If the value is a class member, we might have a pointer-to-member.
+          // Determine whether the non-type template template parameter is of
+          // pointer-to-member type. If so, we need to build an appropriate
+          // expression for a pointer-to-member, since a "normal" DeclRefExpr
+          // would refer to the member itself.
+          if (NTTP->getType()->isMemberPointerType()) {
+            QualType ClassType
+              = SemaRef.Context.getTypeDeclType(
+                                        cast<RecordDecl>(VD->getDeclContext()));
+            NestedNameSpecifier *Qualifier
+              = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
+                                            ClassType.getTypePtr());
+            CXXScopeSpec SS;
+            SS.setScopeRep(Qualifier);
+            OwningExprResult RefExpr 
+              = SemaRef.BuildDeclRefExpr(VD, 
+                                         VD->getType().getNonReferenceType(), 
+                                         E->getLocation(), 
+                                         /*FIXME:*/false, /*FIXME:*/false,
+                                         &SS);
+            if (RefExpr.isInvalid())
+              return SemaRef.ExprError();
+              
+            return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), 
+                                                UnaryOperator::AddrOf, 
+                                                move(RefExpr));
+          }
+        }
+
+        return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+                                        E->getLocation(),
                                         /*FIXME:*/false, /*FIXME:*/false);
       }
 

Modified: cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp?rev=87000&r1=86999&r2=87000&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp Thu Nov 12 11:40:13 2009
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 struct Y {
   int x;
 };
@@ -25,3 +24,12 @@
 template struct X2<int, Y>;
 template struct X2<int&, Y>; // expected-note{{instantiation}}
 template struct X2<const void, Y>; // expected-note{{instantiation}}
+
+template<typename T, typename Class, T Class::*Ptr>
+struct X3 {
+  X3<T, Class, Ptr> &operator=(const T& value) {
+    return *this;
+  }
+};
+
+X3<int, Y, &Y::x> x3;





More information about the cfe-commits mailing list