[llvm-branch-commits] [clang] [clang-tools-extra] [clang] improve class type sugar preservation in pointers to members (PR #130537)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Mar 9 18:56:43 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
This changes the MemberPointerType representation to use a NestedNameSpecifier instead of a Type to represent the class.
Since the qualifiers are always parsed as nested names, there was an impedance mismatch when converting these back and forth into types, and this led to issues in preserving sugar.
The nested names are indeed a better match for these, as the differences which a QualType can represent cannot be expressed syntactically, and it also represents the use case more exactly, being either dependent or referring to a CXXRecord, unqualified.
This patch also makes the MemberPointerType able to represent sugar for a {up/downcast}cast conversion of the base class, although for now the underlying type is canonical, as preserving the sugar up to that point requires further work.
As usual, includes a few drive-by fixes in order to make use of the improvements, and removing some duplications, for example CheckBaseClassAccess is deduplicated from across SemaAccess and SemaCast.
---
Patch is 183.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/130537.diff
81 Files Affected:
- (modified) clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp (+1-4)
- (modified) clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp (+1-2)
- (modified) clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp (+5-3)
- (modified) clang-tools-extra/clangd/unittests/FindTargetTests.cpp (+1-1)
- (modified) clang/docs/ReleaseNotes.rst (+3-2)
- (modified) clang/include/clang/AST/ASTContext.h (+3-4)
- (modified) clang/include/clang/AST/ASTNodeTraverser.h (+5-2)
- (modified) clang/include/clang/AST/CanonicalType.h (+3-1)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+5-4)
- (modified) clang/include/clang/AST/Type.h (+15-13)
- (modified) clang/include/clang/AST/TypeLoc.h (+18-14)
- (modified) clang/include/clang/AST/TypeProperties.td (+6-3)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-4)
- (modified) clang/include/clang/Sema/Sema.h (+28-11)
- (modified) clang/lib/AST/ASTContext.cpp (+160-34)
- (modified) clang/lib/AST/ASTImporter.cpp (+9-5)
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+2-2)
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+6-4)
- (modified) clang/lib/AST/ExprConstant.cpp (+3-2)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+10-1)
- (modified) clang/lib/AST/MicrosoftMangle.cpp (+5-5)
- (modified) clang/lib/AST/NestedNameSpecifier.cpp (+1)
- (modified) clang/lib/AST/ODRHash.cpp (+1-1)
- (modified) clang/lib/AST/QualTypeNames.cpp (+4-3)
- (modified) clang/lib/AST/Type.cpp (+39-12)
- (modified) clang/lib/AST/TypePrinter.cpp (+2-2)
- (modified) clang/lib/CodeGen/CGCXXABI.cpp (+3-4)
- (modified) clang/lib/CodeGen/CGClass.cpp (+3-4)
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+2-1)
- (modified) clang/lib/CodeGen/CGExprCXX.cpp (+4-4)
- (modified) clang/lib/CodeGen/CGPointerAuth.cpp (+2-2)
- (modified) clang/lib/CodeGen/CGVTables.cpp (+2-3)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+1-1)
- (modified) clang/lib/CodeGen/CodeGenTypes.cpp (+1-1)
- (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+11-10)
- (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+4-3)
- (modified) clang/lib/Sema/SemaAccess.cpp (+26-19)
- (modified) clang/lib/Sema/SemaCast.cpp (+16-66)
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+23-25)
- (modified) clang/lib/Sema/SemaExpr.cpp (+4-6)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+35-19)
- (modified) clang/lib/Sema/SemaLookup.cpp (+2-5)
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+2-3)
- (modified) clang/lib/Sema/SemaOverload.cpp (+121-73)
- (modified) clang/lib/Sema/SemaStmt.cpp (+2-1)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+6-2)
- (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+16-5)
- (modified) clang/lib/Sema/SemaType.cpp (+22-100)
- (modified) clang/lib/Sema/TreeTransform.h (+29-30)
- (modified) clang/lib/Serialization/ASTReader.cpp (+1-1)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+1-1)
- (modified) clang/lib/Serialization/TemplateArgumentHasher.cpp (+3-1)
- (modified) clang/test/AST/ast-dump-template-json-win32-mangler-crash.cpp (+3-1)
- (modified) clang/test/AST/ast-dump-templates.cpp (+238)
- (modified) clang/test/AST/ast-dump-types-json.cpp (+338-44)
- (modified) clang/test/AST/attr-print-emit.cpp (+1-1)
- (modified) clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (+5-5)
- (modified) clang/test/CXX/class.access/p6.cpp (+2-2)
- (modified) clang/test/CXX/drs/cwg0xx.cpp (+6-6)
- (modified) clang/test/CXX/drs/cwg13xx.cpp (+2-2)
- (modified) clang/test/CXX/drs/cwg26xx.cpp (+3-3)
- (modified) clang/test/CXX/drs/cwg2xx.cpp (+2-2)
- (modified) clang/test/CXX/drs/cwg4xx.cpp (+1-1)
- (modified) clang/test/CXX/drs/cwg7xx.cpp (+1-2)
- (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp (+1-1)
- (modified) clang/test/CXX/temp/temp.arg/temp.arg.nontype/p5.cpp (+3-3)
- (modified) clang/test/Index/print-type.cpp (+1-1)
- (modified) clang/test/SemaCXX/addr-of-overloaded-function.cpp (+13-13)
- (modified) clang/test/SemaCXX/builtin-ptrtomember-ambig.cpp (+2-2)
- (modified) clang/test/SemaCXX/calling-conv-compat.cpp (+21-21)
- (modified) clang/test/SemaCXX/err_init_conversion_failed.cpp (+1-1)
- (modified) clang/test/SemaCXX/member-pointer.cpp (+13-4)
- (modified) clang/test/SemaCXX/sugar-common-types.cpp (+2-2)
- (modified) clang/test/SemaOpenACC/combined-construct-if-ast.cpp (+2-2)
- (modified) clang/test/SemaOpenACC/combined-construct-num_workers-ast.cpp (+2-2)
- (modified) clang/test/SemaOpenACC/compute-construct-clause-ast.cpp (+2-2)
- (modified) clang/test/SemaOpenACC/compute-construct-intexpr-clause-ast.cpp (+2-2)
- (modified) clang/test/SemaOpenACC/data-construct-if-ast.cpp (+2-2)
- (modified) clang/test/SemaTemplate/instantiate-member-pointers.cpp (+2-1)
- (modified) clang/tools/libclang/CXType.cpp (+3-1)
- (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+4-4)
``````````diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp
index 9d1d92b989bf1..a8a9e6bdcdff8 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp
@@ -70,10 +70,7 @@ void ComparePointerToMemberVirtualFunctionCheck::check(
// compare with variable which type is pointer to member function.
llvm::SmallVector<SourceLocation, 12U> SameSignatureVirtualMethods{};
const auto *MPT = cast<MemberPointerType>(DRE->getType().getCanonicalType());
- const Type *T = MPT->getClass();
- if (T == nullptr)
- return;
- const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
+ const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
if (RD == nullptr)
return;
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index 108717e151b57..a6b00be75abf8 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -493,8 +493,7 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
NullMacrosStr(Options.get("NullMacros", "NULL")),
IgnoredTypes(utils::options::parseStringList(Options.get(
- "IgnoredTypes",
- "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
+ "IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
StringRef(NullMacrosStr).split(NullMacros, ",");
}
diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index 0fea7946a59f9..bc49fa856bafc 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -178,7 +178,9 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
// Note: converting Derived::* to Base::* is a different kind of conversion,
// called Pointer-to-member conversion.
- return FromMember->getClass() == ToMember->getClass() &&
+ return FromMember->getQualifier() == ToMember->getQualifier() &&
+ FromMember->getMostRecentCXXRecordDecl() ==
+ ToMember->getMostRecentCXXRecordDecl() &&
FromMember->getPointeeType() == ToMember->getPointeeType();
}
@@ -219,8 +221,8 @@ bool isQualificationConvertiblePointer(QualType From, QualType To,
if (P1->isMemberPointerType())
return P2->isMemberPointerType() &&
- P1->getAs<MemberPointerType>()->getClass() ==
- P2->getAs<MemberPointerType>()->getClass();
+ P1->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl() ==
+ P2->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
if (P1->isConstantArrayType())
return P2->isConstantArrayType() &&
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index fc54f89f4941e..602f61d9ecb41 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
"4: targets = {a}\n"
"5: targets = {a::b}, qualifier = 'a::'\n"
"6: targets = {a::b::S}\n"
- "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
+ "7: targets = {a::b::S::type}, qualifier = 'S::'\n"
"8: targets = {y}, decl\n"},
{R"cpp(
void foo() {
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7859871b0493a..c2130acbe51bf 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -161,8 +161,8 @@ related warnings within the method body.
``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.
This forces the global to be considered small or large in regards to the
x86-64 code model, regardless of the code model specified for the compilation.
-- Clang now emits a warning ``-Wreserved-init-priority`` instead of a hard error
- when ``__attribute__((init_priority(n)))`` is used with values of n in the
+- Clang now emits a warning ``-Wreserved-init-priority`` instead of a hard error
+ when ``__attribute__((init_priority(n)))`` is used with values of n in the
reserved range [0, 100]. The warning will be treated as an error by default.
- There is a new ``format_matches`` attribute to complement the existing
@@ -233,6 +233,7 @@ Improvements to Clang's diagnostics
under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
- Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
``-Wno-error=parentheses``.
+- Better preservation of member pointer type sugar.
- The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
- The :doc:`ThreadSafetyAnalysis` now supports ``-Wthread-safety-pointer``,
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index f9a12260a6590..af8c49e99a7ce 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1558,10 +1558,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getRValueReferenceType(QualType T) const;
/// Return the uniqued reference to the type for a member pointer to
- /// the specified type in the specified class.
- ///
- /// The class \p Cls is a \c Type because it could be a dependent name.
- QualType getMemberPointerType(QualType T, const Type *Cls) const;
+ /// the specified type in the specified nested name.
+ QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls) const;
/// Return a non-unique reference to the type for a variable array of
/// the specified element type.
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 3bc0bdff2bdd1..f557555e96e59 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -393,7 +393,9 @@ class ASTNodeTraverser
Visit(T->getPointeeType());
}
void VisitMemberPointerType(const MemberPointerType *T) {
- Visit(T->getClass());
+ // FIXME: Provide a NestedNameSpecifier visitor.
+ Visit(T->getQualifier()->getAsType());
+ Visit(T->getMostRecentCXXRecordDecl());
Visit(T->getPointeeType());
}
void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -485,7 +487,8 @@ class ASTNodeTraverser
}
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
- Visit(TL.getClassTInfo()->getTypeLoc());
+ // FIXME: Provide NestedNamespecifierLoc visitor.
+ Visit(TL.getQualifierLoc().getTypeLoc());
}
void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
Visit(TL.getSizeExpr());
diff --git a/clang/include/clang/AST/CanonicalType.h b/clang/include/clang/AST/CanonicalType.h
index 6699284d215bd..35db68971e029 100644
--- a/clang/include/clang/AST/CanonicalType.h
+++ b/clang/include/clang/AST/CanonicalType.h
@@ -453,7 +453,9 @@ template<>
struct CanProxyAdaptor<MemberPointerType>
: public CanProxyBase<MemberPointerType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
- LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
+ LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
+ getMostRecentCXXRecordDecl)
};
// CanProxyAdaptors for arrays are intentionally unimplemented because
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 5ca3e435f033b..67025eb7a5a38 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1004,7 +1004,8 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
{ TRY_TO(TraverseType(T->getPointeeType())); })
DEF_TRAVERSE_TYPE(MemberPointerType, {
- TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
TRY_TO(TraverseType(T->getPointeeType()));
})
@@ -1269,10 +1270,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
// We traverse this in the type case as well, but how is it not reached through
// the pointee type?
DEF_TRAVERSE_TYPELOC(MemberPointerType, {
- if (auto *TSI = TL.getClassTInfo())
- TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+ if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
+ TRY_TO(TraverseNestedNameSpecifierLoc(QL));
else
- TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
})
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index ef59bd1621fb8..84f40025b07fc 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -3524,14 +3524,16 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
QualType PointeeType;
/// The class of which the pointee is a member. Must ultimately be a
- /// RecordType, but could be a typedef or a template parameter too.
- const Type *Class;
+ /// CXXRecordType, but could be a typedef or a template parameter too.
+ NestedNameSpecifier *Qualifier;
- MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
+ MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
+ QualType CanonicalPtr)
: Type(MemberPointer, CanonicalPtr,
- (Cls->getDependence() & ~TypeDependence::VariablyModified) |
+ (toTypeDependence(Qualifier->getDependence()) &
+ ~TypeDependence::VariablyModified) |
Pointee->getDependence()),
- PointeeType(Pointee), Class(Cls) {}
+ PointeeType(Pointee), Qualifier(Qualifier) {}
public:
QualType getPointeeType() const { return PointeeType; }
@@ -3548,21 +3550,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
return !PointeeType->isFunctionProtoType();
}
- const Type *getClass() const { return Class; }
+ NestedNameSpecifier *getQualifier() const { return Qualifier; }
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
- bool isSugared() const { return false; }
- QualType desugar() const { return QualType(this, 0); }
+ bool isSugared() const;
+ QualType desugar() const {
+ return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
+ }
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getPointeeType(), getClass());
+ Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
- const Type *Class) {
- ID.AddPointer(Pointee.getAsOpaquePtr());
- ID.AddPointer(Class);
- }
+ const NestedNameSpecifier *Qualifier,
+ const CXXRecordDecl *Cls);
static bool classof(const Type *T) {
return T->getTypeClass() == MemberPointer;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index a55a38335ef6a..0fca6e522e03b 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -1355,7 +1355,7 @@ class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc,
};
struct MemberPointerLocInfo : public PointerLikeLocInfo {
- TypeSourceInfo *ClassTInfo;
+ void *QualifierData;
};
/// Wrapper for source info for member pointers.
@@ -1371,28 +1371,32 @@ class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc,
setSigilLoc(Loc);
}
- const Type *getClass() const {
- return getTypePtr()->getClass();
- }
-
- TypeSourceInfo *getClassTInfo() const {
- return getLocalData()->ClassTInfo;
+ NestedNameSpecifierLoc getQualifierLoc() const {
+ return NestedNameSpecifierLoc(getTypePtr()->getQualifier(),
+ getLocalData()->QualifierData);
}
- void setClassTInfo(TypeSourceInfo* TI) {
- getLocalData()->ClassTInfo = TI;
+ void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) {
+ assert(QualifierLoc.getNestedNameSpecifier() ==
+ getTypePtr()->getQualifier() &&
+ "Inconsistent nested-name-specifier pointer");
+ getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setSigilLoc(Loc);
- setClassTInfo(nullptr);
+ if (auto *Qualifier = getTypePtr()->getQualifier()) {
+ NestedNameSpecifierLocBuilder Builder;
+ Builder.MakeTrivial(Context, Qualifier, Loc);
+ setQualifierLoc(Builder.getWithLocInContext(Context));
+ } else
+ getLocalData()->QualifierData = nullptr;
}
SourceRange getLocalSourceRange() const {
- if (TypeSourceInfo *TI = getClassTInfo())
- return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc());
- else
- return SourceRange(getStarLoc());
+ if (NestedNameSpecifierLoc QL = getQualifierLoc())
+ return SourceRange(QL.getBeginLoc(), getStarLoc());
+ return SourceRange(getStarLoc());
}
};
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 6f1a76bd18fb5..27f71bf5cc62f 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -100,12 +100,15 @@ let Class = MemberPointerType in {
def : Property<"pointeeType", QualType> {
let Read = [{ node->getPointeeType() }];
}
- def : Property<"baseType", QualType> {
- let Read = [{ QualType(node->getClass(), 0) }];
+ def : Property<"Qualifier", NestedNameSpecifier> {
+ let Read = [{ node->getQualifier() }];
+ }
+ def : Property<"Cls", DeclRef> {
+ let Read = [{ node->getMostRecentCXXRecordDecl() }];
}
def : Creator<[{
- return ctx.getMemberPointerType(pointeeType, baseType.getTypePtr());
+ return ctx.getMemberPointerType(pointeeType, Qualifier, cast_or_null<CXXRecordDecl>(Cls));
}]>;
}
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 88d3fb35eea5c..80d3ca6b16bbb 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7038,10 +7038,8 @@ def err_illegal_decl_mempointer_to_reference : Error<
"'%0' declared as a member pointer to a reference of type %1">;
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">;
-def err_mempointer_in_nonclass_type : Error<
- "member pointer refers into non-class type %0">;
+def err_illegal_decl_mempointer_in_nonclass
+ : 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 fdef57e84ee3d..35a9eb48204de 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1348,6 +1348,12 @@ class Sema final : public SemaBase {
unsigned DiagID, bool ForceCheck = false,
bool ForceUnprivileged = false);
+ AccessResult CheckBaseClassAccess(
+ SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
+ const CXXBasePath &Path, unsigned DiagID,
+ llvm::function_ref<void(PartialDiagnostic &PD)> SetupPDiag,
+ bool ForceCheck = false, bool ForceUnprivileged = false);
+
/// Checks access to all the declarations in the given result set.
void CheckLookupAccess(const LookupResult &R);
@@ -5747,10 +5753,11 @@ class Sema final : public SemaBase {
/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
+ bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived,
+ CXXRecordDecl *Base, CXXBasePaths &Paths);
+ bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived,
+ CXXRecordDecl *Base);
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
-
- /// Determine whether the type \p Derived is a C++ class that is
- /// derived from the type \p Base.
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
CXXBasePaths &Paths);
@@ -10033,15 +10040,24 @@ class Sema final : public SemaBase {
bool InOverloadResolution,
QualType &ConvertedType);
+ enum class CheckMemberPointerConversionResult {
+ Success,
+ DifferentPointee,
+ NotDerived,
+ Ambiguous,
+ Virtual,
+ Inaccessible
+ };
+ enum class CheckMemberPointerConversionDirection : bool { Downcast, Upcast };
/// CheckMemberPointerConversion - Check the member pointer conversion from
/// the expression From to the type ToType. This routine checks for ambiguous
/// or virtual or inaccessible base-to-derived member pointer conversions for
- /// which IsMemberPointerConversion has already returned true. It returns true
- /// and produces a diagnostic if there was an error, or returns false
- /// otherwise.
- bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind,
- CXXCastPath &BasePath,
- bool IgnoreBaseAccess);
+ /// which IsMemberPointerConversion has already returned true. It produces a
+ // diagnostic if there was an error.
+ CheckMemberPointerConversionResult CheckMemberPointerConversion(
+ QualType FromType, const MemberPointerType *ToPtrType, CastKind &Kind,
+ CXXCastPath &BasePath, SourceLocation CheckLoc, SourceRange OpRange,
+ bool IgnoreBaseAccess, CheckMemberPointerConversionDirection Direction);
/// IsQualificationConversion - Determines whether the conversion from
/// an rvalue of type FromType to ToType is a qualification conversion
@@ -14869,8 +14885,9 @@ 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, QualType Class,
- SourceLocation Loc, DeclarationName Entity);
+ QualType BuildMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
+ CXXRecordDecl *Cls, SourceLocation Loc,
+ DeclarationName Entity);
/// Build a block pointer type.
///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index fce1c34897da7..a98e749e025fc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -3321,7 +3321,8 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx,
case Type::MemberPointer: {
OS << "M";
const auto *MPT = T->castAs<MemberPointerType>();
- encodeTypeForFunctionPointerAuth(Ctx, OS, QualType(MPT->getClass(), 0));
+ encodeTypeForFunctionPointerAuth(
+ Ctx, OS, QualType(MPT->getQualifier()->getAsType(), 0));
encodeTypeForFunctionPointerAuth(Ctx, OS, MPT->getPointeeType());
return;
}
@@ -3510,7 +3511,8 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) {
if (PointeeType->castAs<FunctionProtoType>()->getExceptionSpecType() !=
EST_None) {
QualType FT = getFunctionTypeWithExceptionSpec(PointeeType, EST_None);
- T = getMemberPointerType(FT, MPT->getClass());
+ T = getMemberPointerType(FT, MPT->getQualifier(),
+ MPT->getMostRecentCXXRecordDecl());
}
}
std::unique_ptr<MangleContext> MC(createMangleContext());
@@ -4024,32 +4026...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/130537
More information about the llvm-branch-commits
mailing list