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

Douglas Gregor dgregor at apple.com
Thu Nov 12 10:38:13 PST 2009


Author: dgregor
Date: Thu Nov 12 12:38:13 2009
New Revision: 87010

URL: http://llvm.org/viewvc/llvm-project?rev=87010&view=rev
Log:
Recognize (and check) pointer-to-member template arguments that are
non-type template parameters or constants of pointer-to-member
type. Once checked, be sure to retain those pointer-to-member
constants as expressions if they are dependent, or as declarations if
they are not dependent.


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

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=87010&r1=87009&r2=87010&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Nov 12 12:38:13 2009
@@ -2615,7 +2615,8 @@
                              DeclaratorInfo *Arg);
   bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
                                                       NamedDecl *&Entity);
-  bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
+  bool CheckTemplateArgumentPointerToMember(Expr *Arg, 
+                                            TemplateArgument &Converted);
   bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                              QualType InstantiatedParamType, Expr *&Arg,
                              TemplateArgument &Converted);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Nov 12 12:38:13 2009
@@ -1187,11 +1187,10 @@
 
   QualType CanonType;
 
-  if (TemplateSpecializationType::anyDependentTemplateArguments(
+  if (Name.isDependent() ||
+      TemplateSpecializationType::anyDependentTemplateArguments(
                                                       TemplateArgs,
-                                                      NumTemplateArgs) ||
-      isa<TemplateTemplateParmDecl>(Template) || 
-      Template->getDeclContext()->isDependentContext()) {
+                                                      NumTemplateArgs)) {
     // This class template specialization is a dependent
     // type. Therefore, its canonical type is another class template
     // specialization type that contains all of the converted
@@ -2088,8 +2087,8 @@
 
 /// \brief Checks whether the given template argument is a pointer to
 /// member constant according to C++ [temp.arg.nontype]p1.
-bool
-Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
+bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, 
+                                                TemplateArgument &Converted) {
   bool Invalid = false;
 
   // See through any implicit casts we added to fix the type.
@@ -2120,13 +2119,33 @@
     Arg = Parens->getSubExpr();
   }
 
-  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg))
+  // A pointer-to-member constant written &Class::member.
+  if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) {
     if (UnOp->getOpcode() == UnaryOperator::AddrOf) {
       DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr());
       if (DRE && !DRE->getQualifier())
         DRE = 0;
     }
-
+  } 
+  // A constant of pointer-to-member type.
+  else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) {
+    if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) {
+      if (VD->getType()->isMemberPointerType()) {
+        if (isa<NonTypeTemplateParmDecl>(VD) ||
+            (isa<VarDecl>(VD) && 
+             Context.getCanonicalType(VD->getType()).isConstQualified())) {
+          if (Arg->isTypeDependent() || Arg->isValueDependent())
+            Converted = TemplateArgument(Arg->Retain());
+          else
+            Converted = TemplateArgument(VD->getCanonicalDecl());
+          return Invalid;
+        }
+      }
+    }
+    
+    DRE = 0;
+  }
+  
   if (!DRE)
     return Diag(Arg->getSourceRange().getBegin(),
                 diag::err_template_arg_not_pointer_to_member_form)
@@ -2139,7 +2158,10 @@
 
     // Okay: this is the address of a non-static member, and therefore
     // a member pointer constant.
-    Member = DRE->getDecl();
+    if (Arg->isTypeDependent() || Arg->isValueDependent())
+      Converted = TemplateArgument(Arg->Retain());
+    else
+      Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl());
     return Invalid;
   }
 
@@ -2343,16 +2365,8 @@
       return true;
     }
 
-    if (ParamType->isMemberPointerType()) {
-      NamedDecl *Member = 0;
-      if (CheckTemplateArgumentPointerToMember(Arg, Member))
-        return true;
-
-      if (Member)
-        Member = cast<NamedDecl>(Member->getCanonicalDecl());
-      Converted = TemplateArgument(Member);
-      return false;
-    }
+    if (ParamType->isMemberPointerType())
+      return CheckTemplateArgumentPointerToMember(Arg, Converted);
 
     NamedDecl *Entity = 0;
     if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity))
@@ -2465,14 +2479,7 @@
     return true;
   }
 
-  NamedDecl *Member = 0;
-  if (CheckTemplateArgumentPointerToMember(Arg, Member))
-    return true;
-
-  if (Member)
-    Member = cast<NamedDecl>(Member->getCanonicalDecl());
-  Converted = TemplateArgument(Member);
-  return false;
+  return CheckTemplateArgumentPointerToMember(Arg, Converted);
 }
 
 /// \brief Check a template argument against its corresponding

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=87010&r1=87009&r2=87010&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp Thu Nov 12 12:38:13 2009
@@ -33,3 +33,16 @@
 };
 
 X3<int, Y, &Y::x> x3;
+
+typedef int Y::*IntMember;
+
+template<IntMember Member>
+struct X4 {
+  X3<int, Y, Member> member;
+  
+  int &getMember(Y& y) { return y.*Member; }
+};
+
+int &get_X4(X4<&Y::x> x4, Y& y) { 
+  return x4.getMember(y); 
+}





More information about the cfe-commits mailing list