Skip to content

Commit fb38f66

Browse files
committed
[clang] preserve class type sugar when taking pointer to member
This changes the MemberPointerType representation to use a NestedNameSpecifier instead of a Type to represent the base 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 syntatically, and they represent 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.
1 parent cce9f36 commit fb38f66

File tree

81 files changed

+1358
-662
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

81 files changed

+1358
-662
lines changed

clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ void ComparePointerToMemberVirtualFunctionCheck::check(
7070
// compare with variable which type is pointer to member function.
7171
llvm::SmallVector<SourceLocation, 12U> SameSignatureVirtualMethods{};
7272
const auto *MPT = cast<MemberPointerType>(DRE->getType().getCanonicalType());
73-
const Type *T = MPT->getClass();
74-
if (T == nullptr)
75-
return;
76-
const CXXRecordDecl *RD = T->getAsCXXRecordDecl();
73+
const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
7774
if (RD == nullptr)
7875
return;
7976

clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -493,8 +493,7 @@ UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
493493
: ClangTidyCheck(Name, Context),
494494
NullMacrosStr(Options.get("NullMacros", "NULL")),
495495
IgnoredTypes(utils::options::parseStringList(Options.get(
496-
"IgnoredTypes",
497-
"std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
496+
"IgnoredTypes", "_CmpUnspecifiedParam;^std::__cmp_cat::__unspec"))) {
498497
StringRef(NullMacrosStr).split(NullMacros, ",");
499498
}
500499

clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ bool isFunctionPointerConvertible(QualType From, QualType To) {
178178

179179
// Note: converting Derived::* to Base::* is a different kind of conversion,
180180
// called Pointer-to-member conversion.
181-
return FromMember->getClass() == ToMember->getClass() &&
181+
return FromMember->getQualifier() == ToMember->getQualifier() &&
182+
FromMember->getMostRecentCXXRecordDecl() ==
183+
ToMember->getMostRecentCXXRecordDecl() &&
182184
FromMember->getPointeeType() == ToMember->getPointeeType();
183185
}
184186

@@ -219,8 +221,8 @@ bool isQualificationConvertiblePointer(QualType From, QualType To,
219221

220222
if (P1->isMemberPointerType())
221223
return P2->isMemberPointerType() &&
222-
P1->getAs<MemberPointerType>()->getClass() ==
223-
P2->getAs<MemberPointerType>()->getClass();
224+
P1->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl() ==
225+
P2->getAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
224226

225227
if (P1->isConstantArrayType())
226228
return P2->isConstantArrayType() &&

clang-tools-extra/clangd/unittests/FindTargetTests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
14891489
"4: targets = {a}\n"
14901490
"5: targets = {a::b}, qualifier = 'a::'\n"
14911491
"6: targets = {a::b::S}\n"
1492-
"7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
1492+
"7: targets = {a::b::S::type}, qualifier = 'S::'\n"
14931493
"8: targets = {y}, decl\n"},
14941494
{R"cpp(
14951495
void foo() {

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ related warnings within the method body.
161161
``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.
162162
This forces the global to be considered small or large in regards to the
163163
x86-64 code model, regardless of the code model specified for the compilation.
164-
- Clang now emits a warning ``-Wreserved-init-priority`` instead of a hard error
165-
when ``__attribute__((init_priority(n)))`` is used with values of n in the
164+
- Clang now emits a warning ``-Wreserved-init-priority`` instead of a hard error
165+
when ``__attribute__((init_priority(n)))`` is used with values of n in the
166166
reserved range [0, 100]. The warning will be treated as an error by default.
167167

168168
- There is a new ``format_matches`` attribute to complement the existing
@@ -233,6 +233,7 @@ Improvements to Clang's diagnostics
233233
under the subgroup ``-Wunsafe-buffer-usage-in-libc-call``.
234234
- Diagnostics on chained comparisons (``a < b < c``) are now an error by default. This can be disabled with
235235
``-Wno-error=parentheses``.
236+
- Better preservation of member pointer type sugar.
236237
- The ``-Wshift-bool`` warning has been added to warn about shifting a boolean. (#GH28334)
237238

238239
- The :doc:`ThreadSafetyAnalysis` now supports ``-Wthread-safety-pointer``,

clang/include/clang/AST/ASTContext.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,10 +1558,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
15581558
QualType getRValueReferenceType(QualType T) const;
15591559

15601560
/// Return the uniqued reference to the type for a member pointer to
1561-
/// the specified type in the specified class.
1562-
///
1563-
/// The class \p Cls is a \c Type because it could be a dependent name.
1564-
QualType getMemberPointerType(QualType T, const Type *Cls) const;
1561+
/// the specified type in the specified nested name.
1562+
QualType getMemberPointerType(QualType T, NestedNameSpecifier *Qualifier,
1563+
const CXXRecordDecl *Cls) const;
15651564

15661565
/// Return a non-unique reference to the type for a variable array of
15671566
/// the specified element type.

clang/include/clang/AST/ASTNodeTraverser.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,9 @@ class ASTNodeTraverser
393393
Visit(T->getPointeeType());
394394
}
395395
void VisitMemberPointerType(const MemberPointerType *T) {
396-
Visit(T->getClass());
396+
// FIXME: Provide a NestedNameSpecifier visitor.
397+
Visit(T->getQualifier()->getAsType());
398+
Visit(T->getMostRecentCXXRecordDecl());
397399
Visit(T->getPointeeType());
398400
}
399401
void VisitArrayType(const ArrayType *T) { Visit(T->getElementType()); }
@@ -485,7 +487,8 @@ class ASTNodeTraverser
485487
}
486488
}
487489
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
488-
Visit(TL.getClassTInfo()->getTypeLoc());
490+
// FIXME: Provide NestedNamespecifierLoc visitor.
491+
Visit(TL.getQualifierLoc().getTypeLoc());
489492
}
490493
void VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
491494
Visit(TL.getSizeExpr());

clang/include/clang/AST/CanonicalType.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,9 @@ template<>
453453
struct CanProxyAdaptor<MemberPointerType>
454454
: public CanProxyBase<MemberPointerType> {
455455
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getPointeeType)
456-
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const Type *, getClass)
456+
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(NestedNameSpecifier *, getQualifier)
457+
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const CXXRecordDecl *,
458+
getMostRecentCXXRecordDecl)
457459
};
458460

459461
// CanProxyAdaptors for arrays are intentionally unimplemented because

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,7 +1004,8 @@ DEF_TRAVERSE_TYPE(RValueReferenceType,
10041004
{ TRY_TO(TraverseType(T->getPointeeType())); })
10051005

10061006
DEF_TRAVERSE_TYPE(MemberPointerType, {
1007-
TRY_TO(TraverseType(QualType(T->getClass(), 0)));
1007+
TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
1008+
TRY_TO(TraverseDecl(T->getMostRecentCXXRecordDecl()));
10081009
TRY_TO(TraverseType(T->getPointeeType()));
10091010
})
10101011

@@ -1269,10 +1270,10 @@ DEF_TRAVERSE_TYPELOC(RValueReferenceType,
12691270
// We traverse this in the type case as well, but how is it not reached through
12701271
// the pointee type?
12711272
DEF_TRAVERSE_TYPELOC(MemberPointerType, {
1272-
if (auto *TSI = TL.getClassTInfo())
1273-
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
1273+
if (NestedNameSpecifierLoc QL = TL.getQualifierLoc())
1274+
TRY_TO(TraverseNestedNameSpecifierLoc(QL));
12741275
else
1275-
TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
1276+
TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier()));
12761277
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
12771278
})
12781279

clang/include/clang/AST/Type.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,14 +3524,16 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
35243524
QualType PointeeType;
35253525

35263526
/// The class of which the pointee is a member. Must ultimately be a
3527-
/// RecordType, but could be a typedef or a template parameter too.
3528-
const Type *Class;
3527+
/// CXXRecordType, but could be a typedef or a template parameter too.
3528+
NestedNameSpecifier *Qualifier;
35293529

3530-
MemberPointerType(QualType Pointee, const Type *Cls, QualType CanonicalPtr)
3530+
MemberPointerType(QualType Pointee, NestedNameSpecifier *Qualifier,
3531+
QualType CanonicalPtr)
35313532
: Type(MemberPointer, CanonicalPtr,
3532-
(Cls->getDependence() & ~TypeDependence::VariablyModified) |
3533+
(toTypeDependence(Qualifier->getDependence()) &
3534+
~TypeDependence::VariablyModified) |
35333535
Pointee->getDependence()),
3534-
PointeeType(Pointee), Class(Cls) {}
3536+
PointeeType(Pointee), Qualifier(Qualifier) {}
35353537

35363538
public:
35373539
QualType getPointeeType() const { return PointeeType; }
@@ -3548,21 +3550,21 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
35483550
return !PointeeType->isFunctionProtoType();
35493551
}
35503552

3551-
const Type *getClass() const { return Class; }
3553+
NestedNameSpecifier *getQualifier() const { return Qualifier; }
35523554
CXXRecordDecl *getMostRecentCXXRecordDecl() const;
35533555

3554-
bool isSugared() const { return false; }
3555-
QualType desugar() const { return QualType(this, 0); }
3556+
bool isSugared() const;
3557+
QualType desugar() const {
3558+
return isSugared() ? getCanonicalTypeInternal() : QualType(this, 0);
3559+
}
35563560

35573561
void Profile(llvm::FoldingSetNodeID &ID) {
3558-
Profile(ID, getPointeeType(), getClass());
3562+
Profile(ID, getPointeeType(), getQualifier(), getMostRecentCXXRecordDecl());
35593563
}
35603564

35613565
static void Profile(llvm::FoldingSetNodeID &ID, QualType Pointee,
3562-
const Type *Class) {
3563-
ID.AddPointer(Pointee.getAsOpaquePtr());
3564-
ID.AddPointer(Class);
3565-
}
3566+
const NestedNameSpecifier *Qualifier,
3567+
const CXXRecordDecl *Cls);
35663568

35673569
static bool classof(const Type *T) {
35683570
return T->getTypeClass() == MemberPointer;

0 commit comments

Comments
 (0)