[cfe-commits] r73151 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaType.cpp test/SemaCXX/member-pointer.cpp test/SemaTemplate/instantiate-member-pointers.cpp test/SemaTemplate/temp_class_spec.cpp

Douglas Gregor dgregor at apple.com
Tue Jun 9 15:17:39 PDT 2009


Author: dgregor
Date: Tue Jun  9 17:17:39 2009
New Revision: 73151

URL: http://llvm.org/viewvc/llvm-project?rev=73151&view=rev
Log:
Handle member pointer types with dependent class types (e.g., int
T::*) and implement template instantiation for member pointer types.

Added:
    cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/test/SemaTemplate/temp_class_spec.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=73151&r1=73150&r2=73151&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun  9 17:17:39 2009
@@ -1001,6 +1001,8 @@
   "'%0' declared as a member pointer to void">;
 def err_illegal_decl_mempointer_in_nonclass : Error<
   "'%0' does not point into a class">;
+def err_mempointer_in_nonclass_type : Error<
+  "member pointer refers into non-class type %0">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_qualified_block_pointer_type : Error<
   "qualifier specification on block pointer type not allowed">;

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun  9 17:17:39 2009
@@ -349,6 +349,9 @@
                              QualType *ParamTypes, unsigned NumParamTypes,
                              bool Variadic, unsigned Quals,
                              SourceLocation Loc, DeclarationName Entity);
+  QualType BuildMemberPointerType(QualType T, QualType Class, 
+                                  unsigned Quals, SourceLocation Loc, 
+                                  DeclarationName Entity);
   QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0,
                                 TagDecl **OwnedDecl = 0);
   DeclarationName GetNameForDeclarator(Declarator &D);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Jun  9 17:17:39 2009
@@ -265,9 +265,16 @@
 TemplateTypeInstantiator::
 InstantiateMemberPointerType(const MemberPointerType *T,
                              unsigned Quals) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate MemberPointerType yet");
-  return QualType();
+  QualType PointeeType = Instantiate(T->getPointeeType());
+  if (PointeeType.isNull())
+    return QualType();
+
+  QualType ClassType = Instantiate(QualType(T->getClass(), 0));
+  if (ClassType.isNull())
+    return QualType();
+
+  return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Quals, Loc, 
+                                        Entity);
 }
 
 QualType 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Tue Jun  9 17:17:39 2009
@@ -600,7 +600,67 @@
   return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic, 
                                  Quals);
 }
-                                 
+ 
+/// \brief Build a member pointer type \c T Class::*.
+///
+/// \param T the type to which the member pointer refers.
+/// \param Class the class type into which the member pointer points.
+/// \param Quals Qualifiers applied to the member pointer type
+/// \param Loc the location where this type begins
+/// \param Entity the name of the entity that will have this member pointer type
+///
+/// \returns a member pointer type, if successful, or a NULL type if there was
+/// an error.
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class, 
+                                      unsigned Quals, SourceLocation Loc, 
+                                      DeclarationName Entity) {
+  // Verify that we're not building a pointer to pointer to function with
+  // exception specification.
+  if (CheckDistantExceptionSpec(T)) {
+    Diag(Loc, diag::err_distant_exception_spec);
+
+    // FIXME: If we're doing this as part of template instantiation,
+    // we should return immediately.
+
+    // Build the type anyway, but use the canonical type so that the
+    // exception specifiers are stripped off.
+    T = Context.getCanonicalType(T);
+  }
+
+  // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
+  //   with reference type, or "cv void."
+  if (T->isReferenceType()) {
+    Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
+      << (Entity? Entity.getAsString() : "type name");
+    return QualType();
+  }
+
+  if (T->isVoidType()) {
+    Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
+      << (Entity? Entity.getAsString() : "type name");
+    return QualType();
+  }
+
+  // Enforce C99 6.7.3p2: "Types other than pointer types derived from
+  // object or incomplete types shall not be restrict-qualified."
+  if ((Quals & QualType::Restrict) && !T->isIncompleteOrObjectType()) {
+    Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
+      << T;
+
+    // FIXME: If we're doing this as part of template instantiation,
+    // we should return immediately.
+    Quals &= ~QualType::Restrict;
+  }
+
+  if (!Class->isDependentType() && !Class->isRecordType()) {
+    Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+    return QualType();
+  }
+
+  return Context.getMemberPointerType(T, Class.getTypePtr())
+           .getQualifiedType(Quals);  
+}
+                              
 /// GetTypeForDeclarator - Convert the type for the specified
 /// declarator to Type instances. Skip the outermost Skip type
 /// objects.
@@ -870,57 +930,32 @@
       break;
     }
     case DeclaratorChunk::MemberPointer:
-      // Verify that we're not building a pointer to pointer to function with
-      // exception specification.
-      if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) {
-        Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
-        D.setInvalidType(true);
-        // Build the type anyway.
-      }
       // The scope spec must refer to a class, or be dependent.
-      DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
       QualType ClsType;
-      // FIXME: Extend for dependent types when it's actually supported.
-      // See ActOnCXXNestedNameSpecifier.
-      if (CXXRecordDecl *RD = dyn_cast_or_null<CXXRecordDecl>(DC)) {
+      if (isDependentScopeSpecifier(DeclType.Mem.Scope())) {
+        NestedNameSpecifier *NNS 
+          = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
+        assert(NNS->getAsType() && "Nested-name-specifier must name a type");
+        ClsType = QualType(NNS->getAsType(), 0);
+      } else if (CXXRecordDecl *RD 
+                   = dyn_cast_or_null<CXXRecordDecl>(
+                                    computeDeclContext(DeclType.Mem.Scope()))) {
         ClsType = Context.getTagDeclType(RD);
       } else {
-        if (DC) {
-          Diag(DeclType.Mem.Scope().getBeginLoc(),
-               diag::err_illegal_decl_mempointer_in_nonclass)
-            << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
-            << DeclType.Mem.Scope().getRange();
-        }
+        Diag(DeclType.Mem.Scope().getBeginLoc(),
+             diag::err_illegal_decl_mempointer_in_nonclass)
+          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
+          << DeclType.Mem.Scope().getRange();
         D.setInvalidType(true);
-        ClsType = Context.IntTy;
       }
 
-      // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member
-      //   with reference type, or "cv void."
-      if (T->isReferenceType()) {
-        Diag(DeclType.Loc, diag::err_illegal_decl_pointer_to_reference)
-          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
-        D.setInvalidType(true);
-        T = Context.IntTy;
-      }
-      if (T->isVoidType()) {
-        Diag(DeclType.Loc, diag::err_illegal_decl_mempointer_to_void)
-          << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name");
+      if (!ClsType.isNull())
+        T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,
+                                   DeclType.Loc, D.getIdentifier());
+      if (T.isNull()) {
         T = Context.IntTy;
+        D.setInvalidType(true);
       }
-
-      // Enforce C99 6.7.3p2: "Types other than pointer types derived from
-      // object or incomplete types shall not be restrict-qualified."
-      if ((DeclType.Mem.TypeQuals & QualType::Restrict) &&
-          !T->isIncompleteOrObjectType()) {
-        Diag(DeclType.Loc, diag::err_typecheck_invalid_restrict_invalid_pointee)
-          << T;
-        DeclType.Mem.TypeQuals &= ~QualType::Restrict;
-      }
-
-      T = Context.getMemberPointerType(T, ClsType.getTypePtr()).
-                    getQualifiedType(DeclType.Mem.TypeQuals);
-
       break;
     }
 

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=73151&r1=73150&r2=73151&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Tue Jun  9 17:17:39 2009
@@ -12,7 +12,8 @@
 int (::A::*pdi2);
 int (A::*pfi)(int);
 
-int B::*pbi; // expected-error {{expected a class or namespace}}
+int B::*pbi; // expected-error {{expected a class or namespace}} \
+             // expected-error{{does not point into a class}}
 int C::*pci; // expected-error {{'pci' does not point into a class}}
 void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}}
 int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}}

Added: cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp?rev=73151&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp (added)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp Tue Jun  9 17:17:39 2009
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Y {
+  int x;
+};
+
+template<typename T>
+struct X1 {
+  int f(T* ptr, int T::*pm) { // expected-error{{member pointer}}
+    return ptr->*pm;
+  }
+};
+
+template struct X1<Y>;
+template struct X1<int>; // expected-note{{instantiation}}
+
+template<typename T, typename Class>
+struct X2 {
+  T f(Class &obj, T Class::*pm) { // expected-error{{to a reference}} \
+                      // expected-error{{member pointer to void}}
+    return obj.*pm; 
+  }
+};
+
+template struct X2<int, Y>;
+template struct X2<int&, Y>; // expected-note{{instantiation}}
+template struct X2<const void, Y>; // expected-note{{instantiation}}

Propchange: cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/instantiate-member-pointers.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: cfe/trunk/test/SemaTemplate/temp_class_spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_class_spec.cpp?rev=73151&r1=73150&r2=73151&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_class_spec.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_class_spec.cpp Tue Jun  9 17:17:39 2009
@@ -148,3 +148,13 @@
 };
 
 int is_binary_function0[is_binary_function<int(float, double)>::value? 1 : -1];
+
+template<typename T>
+struct is_member_pointer {
+  static const bool value = false;
+};
+
+template<typename T, typename Class>
+struct is_member_pointer<T Class::*> {
+  static const bool value = true;
+};





More information about the cfe-commits mailing list