[clang] improve class type sugar preservation in pointers to members by mizvekov · Pull Request #130537 · llvm/llvm-project (original) (raw)

@llvm/pr-subscribers-clangd
@llvm/pr-subscribers-clang-static-analyzer-1
@llvm/pr-subscribers-clang-codegen
@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

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:

} 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(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);

@@ -10033,15 +10040,24 @@ class Sema final : public SemaBase { bool InOverloadResolution, QualType &ConvertedType);

@@ -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.

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();