llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Matheus Izvekov (mizvekov)

<details>
<summary>Changes</summary>

This moves the diagnostic for member pointers pointing into non-class into 
BuildMemberPointer, so that it can be used from RebuildMemberPointer, when 
instantiating templates.

Also adds a minor tweak to the diagnostic when the member pointer is anonymous, 
which was previously untested.

Also reverts https://github.com/llvm/llvm-project/pull/132501, which disabled a 
failing test due to the regression which is now fixed.

No changelog, since this fixes a regression which has not been released yet.

Fixes https://github.com/llvm/llvm-project/issues/132494

---
Full diff: https://github.com/llvm/llvm-project/pull/132516.diff


6 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1) 
- (modified) clang/include/clang/Sema/Sema.h (+1-1) 
- (modified) clang/lib/Sema/SemaType.cpp (+22-20) 
- (modified) clang/lib/Sema/TreeTransform.h (+8-7) 
- (modified) clang/test/SemaCXX/member-pointer.cpp (+11) 
- (modified) libc/test/src/__support/CPP/type_traits_test.cpp (+1-3) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0cee58d8de513..c77cde297dc32 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6976,7 +6976,7 @@ def err_illegal_decl_mempointer_to_reference : Error<
 def err_illegal_decl_mempointer_to_void : Error<
   "'%0' declared as a member pointer to void">;
 def err_illegal_decl_mempointer_in_nonclass
-    : Error<"'%0' does not point into a class">;
+    : Error<"%0 does not point into a class">;
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e215f07e2bf0a..04c25121f4c23 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14885,7 +14885,7 @@ class Sema final : public SemaBase {
   ///
   /// \returns a member pointer type, if successful, or a NULL type if there 
was
   /// an error.
-  QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+  QualType BuildMemberPointerType(QualType T, const CXXScopeSpec &SS,
                                   CXXRecordDecl *Cls, SourceLocation Loc,
                                   DeclarationName Entity);
 
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 39717386b0d08..aec33303780a0 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2685,10 +2685,23 @@ QualType Sema::BuildFunctionType(QualType T,
   return Context.getFunctionType(T, ParamTypes, EPI);
 }
 
-QualType Sema::BuildMemberPointerType(QualType T,
-                                      NestedNameSpecifier *Qualifier,
+QualType Sema::BuildMemberPointerType(QualType T, const CXXScopeSpec &SS,
                                       CXXRecordDecl *Cls, SourceLocation Loc,
                                       DeclarationName Entity) {
+  if (!Cls && !isDependentScopeSpecifier(SS)) {
+    Cls = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS));
+    if (!Cls) {
+      auto D =
+          Diag(SS.getBeginLoc(), diag::err_illegal_decl_mempointer_in_nonclass)
+          << SS.getRange();
+      if (const IdentifierInfo *II = Entity.getAsIdentifierInfo())
+        D << II;
+      else
+        D << "member pointer";
+      return QualType();
+    }
+  }
+
   // Verify that we're not building a pointer to pointer to function with
   // exception specification.
   if (CheckDistantExceptionSpec(T)) {
@@ -2730,7 +2743,7 @@ QualType Sema::BuildMemberPointerType(QualType T,
   if (T->isFunctionType())
     adjustMemberFunctionCC(T, /*HasThisPointer=*/true, IsCtorOrDtor, Loc);
 
-  return Context.getMemberPointerType(T, Qualifier, Cls);
+  return Context.getMemberPointerType(T, SS.getScopeRep(), Cls);
 }
 
 QualType Sema::BuildBlockPointerType(QualType T,
@@ -5344,20 +5357,9 @@ static TypeSourceInfo 
*GetFullTypeForDeclarator(TypeProcessingState &state,
         // Avoid emitting extra errors if we already errored on the scope.
         D.setInvalidType(true);
         AreDeclaratorChunksValid = false;
-      } else if (auto *RD =
-                     dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS));
-                 RD || S.isDependentScopeSpecifier(SS)) {
-        T = S.BuildMemberPointerType(T, SS.getScopeRep(), RD, DeclType.Loc,
-                                     D.getIdentifier());
       } else {
-        S.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);
-        AreDeclaratorChunksValid = false;
-        // FIXME: Maybe we could model these as as a MemberPointerType with a
-        // non-dependent, non-class qualifier anyway.
+        T = S.BuildMemberPointerType(T, SS, /*Cls=*/nullptr, DeclType.Loc,
+                                     D.getIdentifier());
       }
 
       if (T.isNull()) {
@@ -9255,10 +9257,10 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, 
QualType T,
   //         "Can't ask whether a dependent type is complete");
 
   if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
-    if (!MPTy->getQualifier()->isDependent()) {
-      QualType T = Context.getTypeDeclType(MPTy->getMostRecentCXXRecordDecl());
-      if (getLangOpts().CompleteMemberPointers &&
-          !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() &&
+    if (CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl();
+        RD && !RD->isDependentType()) {
+      QualType T = Context.getTypeDeclType(RD);
+      if (getLangOpts().CompleteMemberPointers && !RD->isBeingDefined() &&
           RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete))
         return true;
 
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 71fc0f30845cb..0ba6a195b7052 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -864,8 +864,8 @@ class TreeTransform {
   /// By default, performs semantic analysis when building the member pointer
   /// type. Subclasses may override this routine to provide different behavior.
   QualType RebuildMemberPointerType(QualType PointeeType,
-                                    NestedNameSpecifier *Qualifier,
-                                    CXXRecordDecl *Cls, SourceLocation Sigil);
+                                    const CXXScopeSpec &SS, CXXRecordDecl *Cls,
+                                    SourceLocation Sigil);
 
   QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
                                     SourceLocation ProtocolLAngleLoc,
@@ -5631,9 +5631,10 @@ 
TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
       NewQualifierLoc.getNestedNameSpecifier() !=
           OldQualifierLoc.getNestedNameSpecifier() ||
       NewCls != OldCls) {
-    Result = getDerived().RebuildMemberPointerType(
-        PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls,
-        TL.getStarLoc());
+    CXXScopeSpec SS;
+    SS.Adopt(NewQualifierLoc);
+    Result = getDerived().RebuildMemberPointerType(PointeeType, SS, NewCls,
+                                                   TL.getStarLoc());
     if (Result.isNull())
       return QualType();
   }
@@ -17044,9 +17045,9 @@ TreeTransform<Derived>::RebuildReferenceType(QualType 
ReferentType,
 
 template <typename Derived>
 QualType TreeTransform<Derived>::RebuildMemberPointerType(
-    QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls,
+    QualType PointeeType, const CXXScopeSpec &SS, CXXRecordDecl *Cls,
     SourceLocation Sigil) {
-  return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil,
+  return SemaRef.BuildMemberPointerType(PointeeType, SS, Cls, Sigil,
                                         getDerived().getBaseEntity());
 }
 
diff --git a/clang/test/SemaCXX/member-pointer.cpp 
b/clang/test/SemaCXX/member-pointer.cpp
index 81a3a3f2df315..b6ab7d38610c8 100644
--- a/clang/test/SemaCXX/member-pointer.cpp
+++ b/clang/test/SemaCXX/member-pointer.cpp
@@ -333,3 +333,14 @@ namespace test9 {
   struct C { int BAR::*mp; };
   // expected-error@-1 {{'BAR' is not a class, namespace, or enumeration}}
 } // namespace test9
+
+namespace GH132494 {
+  enum E {};
+
+  void f(int E::*); // expected-error {{member pointer does not point into a 
class}}
+
+  template <class T> struct A {
+    int T::*foo; // expected-error {{'foo' does not point into a class}}
+  };
+  template struct A<E>; // expected-note {{requested here}}
+} // namespace GH132494
diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp 
b/libc/test/src/__support/CPP/type_traits_test.cpp
index 85e71f9d90026..4b3e48c6a6c0f 100644
--- a/libc/test/src/__support/CPP/type_traits_test.cpp
+++ b/libc/test/src/__support/CPP/type_traits_test.cpp
@@ -334,9 +334,7 @@ TEST(LlvmLibcTypeTraitsTest, is_class) {
   // Neither other types.
   EXPECT_FALSE((is_class_v<Union>));
   EXPECT_FALSE((is_class_v<int>));
-  // TODO: Re-enable the test after
-  // https://github.com/llvm/llvm-project/issues/132494 is fixed.
-  // EXPECT_FALSE((is_class_v<EnumClass>));
+  EXPECT_FALSE((is_class_v<EnumClass>));
 }
 
 TYPED_TEST(LlvmLibcTypeTraitsTest, is_const, UnqualObjectTypes) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/132516
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to