aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorMatheus Izvekov <mizvekov@gmail.com>2025-03-20 11:09:25 -0300
committerGitHub <noreply@github.com>2025-03-20 11:09:25 -0300
commit6cd62ad08c974b7d4f7171c66f6567de82bd236f (patch)
tree259dbf4169ef28a26ddb2663b12beffb51ff789b /clang/lib/Sema
parente6a87da8fe314a009eed769f9737b4b281a06fba (diff)
downloadllvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.zip
llvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.tar.gz
llvm-6cd62ad08c974b7d4f7171c66f6567de82bd236f.tar.bz2
Revert "[clang] improve class type sugar preservation in pointers to members" (#132215)
Reverts llvm/llvm-project#130537 This missed updating lldb, which we didn't notice due to lack of pre-commit CI.
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaAccess.cpp26
-rw-r--r--clang/lib/Sema/SemaCast.cpp4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp10
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp4
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp5
-rw-r--r--clang/lib/Sema/SemaOverload.cpp87
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp8
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp21
-rw-r--r--clang/lib/Sema/SemaType.cpp122
-rw-r--r--clang/lib/Sema/TreeTransform.h59
10 files changed, 184 insertions, 162 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index b77cbdb..4ba46a9 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1873,20 +1873,21 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr,
return CheckAccess(*this, Ovl->getNameLoc(), Entity);
}
-Sema::AccessResult Sema::CheckBaseClassAccess(
- SourceLocation AccessLoc, CXXRecordDecl *Base, CXXRecordDecl *Derived,
- const CXXBasePath &Path, unsigned DiagID,
- llvm::function_ref<void(PartialDiagnostic &)> SetupPDiag, bool ForceCheck,
- bool ForceUnprivileged) {
+Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
+ QualType Base, QualType Derived,
+ const CXXBasePath &Path,
+ unsigned DiagID, bool ForceCheck,
+ bool ForceUnprivileged) {
if (!ForceCheck && !getLangOpts().AccessControl)
return AR_accessible;
if (Path.Access == AS_public)
return AR_accessible;
- AccessTarget Entity(Context, AccessTarget::Base, Base, Derived, Path.Access);
+ AccessTarget Entity(Context, AccessTarget::Base, Base->getAsCXXRecordDecl(),
+ Derived->getAsCXXRecordDecl(), Path.Access);
if (DiagID)
- SetupPDiag(Entity.setDiag(DiagID));
+ Entity.setDiag(DiagID) << Derived << Base;
if (ForceUnprivileged) {
switch (
@@ -1903,17 +1904,6 @@ Sema::AccessResult Sema::CheckBaseClassAccess(
return CheckAccess(*this, AccessLoc, Entity);
}
-Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc,
- QualType Base, QualType Derived,
- const CXXBasePath &Path,
- unsigned DiagID, bool ForceCheck,
- bool ForceUnprivileged) {
- return CheckBaseClassAccess(
- AccessLoc, Base->getAsCXXRecordDecl(), Derived->getAsCXXRecordDecl(),
- Path, DiagID, [&](PartialDiagnostic &PD) { PD << Derived << Base; },
- ForceCheck, ForceUnprivileged);
-}
-
void Sema::CheckLookupAccess(const LookupResult &R) {
assert(getLangOpts().AccessControl
&& "performing access check without access control");
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index a5dbc16..718f6be 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -1788,8 +1788,8 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
= Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
FoundOverload)) {
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
- SrcType = Self.Context.getMemberPointerType(
- Fn->getType(), /*Qualifier=*/nullptr, M->getParent());
+ SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+ Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
WasOverloadedFunction = true;
}
}
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 16f0b6d..42f0acb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -14314,8 +14314,9 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
CheckUseOfCXXMethodAsAddressOfOperand(OpLoc, OrigOp.get(), MD);
+
QualType MPTy = Context.getMemberPointerType(
- op->getType(), DRE->getQualifier(), MD->getParent());
+ op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr());
if (getLangOpts().PointerAuthCalls && MD->isVirtual() &&
!isUnevaluatedContext() && !MPTy->isDependentType()) {
@@ -14403,8 +14404,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// of some class C [...] and if E is a qualified-id, E is
// not the un-parenthesized operand of the unary & operator [...]
// the id-expression is transformed into a class member access expression.
- if (auto *DRE = dyn_cast<DeclRefExpr>(op);
- DRE && DRE->getQualifier() && !isa<ParenExpr>(OrigOp.get())) {
+ if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() &&
+ !isa<ParenExpr>(OrigOp.get())) {
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (dcl->getType()->isReferenceType()) {
@@ -14418,7 +14419,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
Ctx = Ctx->getParent();
QualType MPTy = Context.getMemberPointerType(
- op->getType(), DRE->getQualifier(), cast<CXXRecordDecl>(Ctx));
+ op->getType(),
+ Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(OpLoc, MPTy);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 90a4a5a..f085fac 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -7368,7 +7368,6 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
Qualifiers Quals;
/// The class for a pointer-to-member; a constant array type with a bound
/// (if any) for an array.
- /// FIXME: Store Qualifier for pointer-to-member.
const Type *ClassOrBound;
Step(Kind K, const Type *ClassOrBound = nullptr)
@@ -7379,8 +7378,7 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
case Pointer:
return Ctx.getPointerType(T);
case MemberPointer:
- return Ctx.getMemberPointerType(T, /*Qualifier=*/nullptr,
- ClassOrBound->getAsCXXRecordDecl());
+ return Ctx.getMemberPointerType(T, ClassOrBound);
case ObjCPointer:
return Ctx.getObjCObjectPointerType(T);
case Array:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 1c771b0..890de83 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -7366,8 +7366,9 @@ SemaOpenMP::checkOpenMPDeclareVariantFunction(SemaOpenMP::DeclGroupPtrTy DG,
QualType FnPtrType;
auto *Method = dyn_cast<CXXMethodDecl>(FD);
if (Method && !Method->isStatic()) {
- FnPtrType = Context.getMemberPointerType(
- AdjustedFnType, /*Qualifier=*/nullptr, Method->getParent());
+ const Type *ClassType =
+ Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
ExprResult ER;
{
// Build addr_of unary op to correctly handle type checks for member
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 670c27f..161c0da 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -2243,8 +2243,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode()
== UO_AddrOf &&
"Non-address-of operator on non-static member address");
- FromType = S.Context.getMemberPointerType(
- FromType, /*Qualifier=*/nullptr, Method->getParent());
+ const Type *ClassType
+ = S.Context.getTypeDeclType(Method->getParent()).getTypePtr();
+ FromType = S.Context.getMemberPointerType(FromType, ClassType);
} else if (isa<UnaryOperator>(From->IgnoreParens())) {
assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() ==
UO_AddrOf &&
@@ -3292,17 +3293,8 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
*ToMember = ToType->castAs<MemberPointerType>();
if (!declaresSameEntity(FromMember->getMostRecentCXXRecordDecl(),
ToMember->getMostRecentCXXRecordDecl())) {
- PDiag << ft_different_class;
- if (ToMember->isSugared())
- PDiag << Context.getTypeDeclType(
- ToMember->getMostRecentCXXRecordDecl());
- else
- PDiag << ToMember->getQualifier();
- if (FromMember->isSugared())
- PDiag << Context.getTypeDeclType(
- FromMember->getMostRecentCXXRecordDecl());
- else
- PDiag << FromMember->getQualifier();
+ PDiag << ft_different_class << QualType(ToMember->getClass(), 0)
+ << QualType(FromMember->getClass(), 0);
return;
}
FromType = FromMember->getPointeeType();
@@ -3543,13 +3535,13 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType,
// A pointer to member of B can be converted to a pointer to member of D,
// where D is derived from B (C++ 4.11p2).
- CXXRecordDecl *FromClass = FromTypePtr->getMostRecentCXXRecordDecl();
- CXXRecordDecl *ToClass = ToTypePtr->getMostRecentCXXRecordDecl();
+ QualType FromClass(FromTypePtr->getClass(), 0);
+ QualType ToClass(ToTypePtr->getClass(), 0);
- if (!declaresSameEntity(FromClass, ToClass) &&
+ if (!Context.hasSameUnqualifiedType(FromClass, ToClass) &&
IsDerivedFrom(From->getBeginLoc(), ToClass, FromClass)) {
- ConvertedType = Context.getMemberPointerType(
- FromTypePtr->getPointeeType(), FromTypePtr->getQualifier(), ToClass);
+ ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(),
+ ToClass.getTypePtr());
return true;
}
@@ -3580,23 +3572,10 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
ToPtrType->getPointeeType()))
return MemberPointerConversionResult::DifferentPointee;
- CXXRecordDecl *FromClass = FromPtrType->getMostRecentCXXRecordDecl(),
- *ToClass = ToPtrType->getMostRecentCXXRecordDecl();
-
- auto DiagCls = [](PartialDiagnostic &PD, NestedNameSpecifier *Qual,
- const CXXRecordDecl *Cls) {
- if (declaresSameEntity(Qual->getAsRecordDecl(), Cls))
- PD << Qual;
- else
- PD << QualType(Cls->getTypeForDecl(), 0);
- };
- auto DiagFromTo = [&](PartialDiagnostic &PD) -> PartialDiagnostic & {
- DiagCls(PD, FromPtrType->getQualifier(), FromClass);
- DiagCls(PD, ToPtrType->getQualifier(), ToClass);
- return PD;
- };
+ QualType FromClass = QualType(FromPtrType->getClass(), 0),
+ ToClass = QualType(ToPtrType->getClass(), 0);
- CXXRecordDecl *Base = FromClass, *Derived = ToClass;
+ QualType Base = FromClass, Derived = ToClass;
if (Direction == MemberPointerConversionDirection::Upcast)
std::swap(Base, Derived);
@@ -3605,19 +3584,16 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
if (!IsDerivedFrom(OpRange.getBegin(), Derived, Base, Paths))
return MemberPointerConversionResult::NotDerived;
- if (Paths.isAmbiguous(
- Base->getTypeForDecl()->getCanonicalTypeUnqualified())) {
- PartialDiagnostic PD = PDiag(diag::err_ambiguous_memptr_conv);
- PD << int(Direction);
- DiagFromTo(PD) << getAmbiguousPathsDisplayString(Paths) << OpRange;
- Diag(CheckLoc, PD);
+ if (Paths.isAmbiguous(Base->getCanonicalTypeUnqualified())) {
+ Diag(CheckLoc, diag::err_ambiguous_memptr_conv)
+ << int(Direction) << FromClass << ToClass
+ << getAmbiguousPathsDisplayString(Paths) << OpRange;
return MemberPointerConversionResult::Ambiguous;
}
if (const RecordType *VBase = Paths.getDetectedVirtual()) {
- PartialDiagnostic PD = PDiag(diag::err_memptr_conv_via_virtual);
- DiagFromTo(PD) << QualType(VBase, 0) << OpRange;
- Diag(CheckLoc, PD);
+ Diag(CheckLoc, diag::err_memptr_conv_via_virtual)
+ << FromClass << ToClass << QualType(VBase, 0) << OpRange;
return MemberPointerConversionResult::Virtual;
}
@@ -3632,15 +3608,7 @@ Sema::MemberPointerConversionResult Sema::CheckMemberPointerConversion(
CheckLoc, Base, Derived, Paths.front(),
Direction == MemberPointerConversionDirection::Upcast
? diag::err_upcast_to_inaccessible_base
- : diag::err_downcast_from_inaccessible_base,
- [&](PartialDiagnostic &PD) {
- NestedNameSpecifier *BaseQual = FromPtrType->getQualifier(),
- *DerivedQual = ToPtrType->getQualifier();
- if (Direction == MemberPointerConversionDirection::Upcast)
- std::swap(BaseQual, DerivedQual);
- DiagCls(PD, DerivedQual, Derived);
- DiagCls(PD, BaseQual, Base);
- })) {
+ : diag::err_downcast_from_inaccessible_base)) {
case Sema::AR_accessible:
case Sema::AR_delayed:
case Sema::AR_dependent:
@@ -8759,7 +8727,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
// and those shouldn't have qualifier variants anyway.
if (PointeeTy->isArrayType())
return true;
- CXXRecordDecl *Cls = PointerTy->getMostRecentCXXRecordDecl();
+ const Type *ClassTy = PointerTy->getClass();
// Iterate through all strict supersets of the pointee type's CVR
// qualifiers.
@@ -8769,7 +8737,7 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(
QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);
MemberPointerTypes.insert(
- Context.getMemberPointerType(QPointeeTy, /*Qualifier=*/nullptr, Cls));
+ Context.getMemberPointerType(QPointeeTy, ClassTy));
}
return true;
@@ -16463,17 +16431,16 @@ ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
assert(isa<DeclRefExpr>(SubExpr.get()) &&
"fixed to something other than a decl ref");
- NestedNameSpecifier *Qualifier =
- cast<DeclRefExpr>(SubExpr.get())->getQualifier();
- assert(Qualifier &&
+ assert(cast<DeclRefExpr>(SubExpr.get())->getQualifier() &&
"fixed to a member ref with no nested name qualifier");
// We have taken the address of a pointer to member
// function. Perform the computation here so that we get the
// appropriate pointer to member type.
- QualType MemPtrType = Context.getMemberPointerType(
- Fn->getType(), Qualifier,
- cast<CXXRecordDecl>(Method->getDeclContext()));
+ QualType ClassType
+ = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+ QualType MemPtrType
+ = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr());
// Under the MS ABI, lock down the inheritance model now.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
(void)isCompleteType(UnOp->getOperatorLoc(), MemPtrType);
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 45fb9d0..c3c993d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -5923,12 +5923,8 @@ bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType(
}
bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType(
- const MemberPointerType *T) {
- if (Visit(T->getPointeeType()))
- return true;
- if (auto *RD = T->getMostRecentCXXRecordDecl())
- return VisitTagDecl(RD);
- return VisitNestedNameSpecifier(T->getQualifier());
+ const MemberPointerType* T) {
+ return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0));
}
bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType(
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index c3bec6b..e6ec4a7 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2127,19 +2127,9 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
/*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
Result != TemplateDeductionResult::Success)
return Result;
- const Type *QP = MPP->getQualifier()->getAsType(),
- *QA = MPA->getQualifier()->getAsType();
- CXXRecordDecl *ClsP = MPP->getMostRecentCXXRecordDecl(),
- *ClsA = MPA->getMostRecentCXXRecordDecl();
- // FIXME: Don't drop the rest of the prefixes here.
- QualType P = !ClsP || declaresSameEntity(QP->getAsCXXRecordDecl(), ClsP)
- ? QualType(QP, 0)
- : S.Context.getTypeDeclType(ClsP);
- QualType A = !ClsA || declaresSameEntity(QA->getAsCXXRecordDecl(), ClsA)
- ? QualType(QA, 0)
- : S.Context.getTypeDeclType(ClsA);
return DeduceTemplateArgumentsByTypeMatch(
- S, TemplateParams, P, A, Info, Deduced, SubTDF,
+ S, TemplateParams, QualType(MPP->getClass(), 0),
+ QualType(MPA->getClass(), 0), Info, Deduced, SubTDF,
degradeCallPartialOrderingKind(POK),
/*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
}
@@ -4221,8 +4211,8 @@ static QualType GetTypeOfFunction(Sema &S, const OverloadExpr::FindResult &R,
if (!R.HasFormOfMemberPointer)
return {};
- return S.Context.getMemberPointerType(
- Fn->getType(), /*Qualifier=*/nullptr, Method->getParent());
+ return S.Context.getMemberPointerType(Fn->getType(),
+ S.Context.getTypeDeclType(Method->getParent()).getTypePtr());
}
if (!R.IsAddressOfOperand) return Fn->getType();
@@ -6843,8 +6833,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr());
MarkUsedTemplateParameters(Ctx, MemPtr->getPointeeType(), OnlyDeduced,
Depth, Used);
- MarkUsedTemplateParameters(Ctx,
- QualType(MemPtr->getQualifier()->getAsType(), 0),
+ MarkUsedTemplateParameters(Ctx, QualType(MemPtr->getClass(), 0),
OnlyDeduced, Depth, Used);
break;
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3971738..11943c0 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2086,7 +2086,7 @@ QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM,
// an inheritance model, even if it's inside an unused typedef.
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>())
- if (!MPTy->getQualifier()->isDependent())
+ if (!MPTy->getClass()->isDependentType())
(void)isCompleteType(Loc, T);
} else {
@@ -2685,9 +2685,8 @@ QualType Sema::BuildFunctionType(QualType T,
return Context.getFunctionType(T, ParamTypes, EPI);
}
-QualType Sema::BuildMemberPointerType(QualType T,
- NestedNameSpecifier *Qualifier,
- CXXRecordDecl *Cls, SourceLocation Loc,
+QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
+ SourceLocation Loc,
DeclarationName Entity) {
// Verify that we're not building a pointer to pointer to function with
// exception specification.
@@ -2710,6 +2709,11 @@ QualType Sema::BuildMemberPointerType(QualType T,
return QualType();
}
+ if (!Class->isDependentType() && !Class->isRecordType()) {
+ Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
+ return QualType();
+ }
+
if (T->isFunctionType() && getLangOpts().OpenCL &&
!getOpenCLOptions().isAvailableOption("__cl_clang_function_pointers",
getLangOpts())) {
@@ -2730,7 +2734,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, Class.getTypePtr());
}
QualType Sema::BuildBlockPointerType(QualType T,
@@ -5334,6 +5338,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorChunk::MemberPointer: {
// The scope spec must refer to a class, or be dependent.
CXXScopeSpec &SS = DeclType.Mem.Scope();
+ QualType ClsType;
// Handle pointer nullability.
inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc,
@@ -5343,23 +5348,57 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (SS.isInvalid()) {
// 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 if (S.isDependentScopeSpecifier(SS) ||
+ isa_and_nonnull<CXXRecordDecl>(S.computeDeclContext(SS))) {
+ NestedNameSpecifier *NNS = SS.getScopeRep();
+ NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ ClsType = Context.getDependentNameType(
+ ElaboratedTypeKeyword::None, NNSPrefix, NNS->getAsIdentifier());
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ llvm_unreachable("Nested-name-specifier must name a type");
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ const Type *NNSType = NNS->getAsType();
+ ClsType = QualType(NNSType, 0);
+ // Note: if the NNS has a prefix and ClsType is a nondependent
+ // TemplateSpecializationType or a RecordType, then the NNS prefix is
+ // NOT included in ClsType; hence we wrap ClsType into an
+ // ElaboratedType. NOTE: in particular, no wrap occurs if ClsType
+ // already is an Elaborated, DependentName, or
+ // DependentTemplateSpecialization.
+ if (isa<DependentTemplateSpecializationType>(NNSType)) {
+ // FIXME: Rebuild DependentTemplateSpecializationType, adding the
+ // Prefix.
+ } else if (isa<TemplateSpecializationType, RecordType>(NNSType)) {
+ // Either the dependent case (TemplateSpecializationType), or the
+ // non-dependent one (RecordType).
+ ClsType = Context.getElaboratedType(ElaboratedTypeKeyword::None,
+ NNSPrefix, ClsType);
+ }
+ break;
+ }
} 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.
}
+ if (!ClsType.isNull())
+ T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc,
+ D.getIdentifier());
+ else
+ AreDeclaratorChunksValid = false;
+
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
@@ -6145,8 +6184,48 @@ namespace {
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
+ const CXXScopeSpec& SS = Chunk.Mem.Scope();
+ NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
+
+ const Type* ClsTy = TL.getClass();
+ QualType ClsQT = QualType(ClsTy, 0);
+ TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
+ // Now copy source location info into the type loc component.
+ TypeLoc ClsTL = ClsTInfo->getTypeLoc();
+ switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
+ {
+ DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>();
+ DNTLoc.setElaboratedKeywordLoc(SourceLocation());
+ DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
+ DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
+ }
+ break;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ if (isa<ElaboratedType>(ClsTy)) {
+ ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>();
+ ETLoc.setElaboratedKeywordLoc(SourceLocation());
+ ETLoc.setQualifierLoc(NNSLoc.getPrefix());
+ TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
+ NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
+ } else {
+ ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
+ }
+ break;
+
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Super:
+ llvm_unreachable("Nested-name-specifier must name a type");
+ }
+
+ // Finally fill in MemberPointerLocInfo fields.
TL.setStarLoc(Chunk.Mem.StarLoc);
- TL.setQualifierLoc(Chunk.Mem.Scope().getWithLocInContext(Context));
+ TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
@@ -6975,8 +7054,7 @@ namespace {
case MemberPointer: {
const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
QualType New = wrap(C, OldMPT->getPointeeType(), I);
- return C.getMemberPointerType(New, OldMPT->getQualifier(),
- OldMPT->getMostRecentCXXRecordDecl());
+ return C.getMemberPointerType(New, OldMPT->getClass());
}
case Reference: {
@@ -9255,17 +9333,17 @@ 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 (!MPTy->getClass()->isDependentType()) {
if (getLangOpts().CompleteMemberPointers &&
- !MPTy->getMostRecentCXXRecordDecl()->isBeingDefined() &&
- RequireCompleteType(Loc, T, Kind, diag::err_memptr_incomplete))
+ !MPTy->getClass()->getAsCXXRecordDecl()->isBeingDefined() &&
+ RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), Kind,
+ diag::err_memptr_incomplete))
return true;
// We lock in the inheritance model once somebody has asked us to ensure
// that a pointer-to-member type is complete.
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
- (void)isCompleteType(Loc, T);
+ (void)isCompleteType(Loc, QualType(MPTy->getClass(), 0));
assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 5686b9d..b5de98e 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -859,13 +859,12 @@ public:
SourceLocation Sigil);
/// Build a new member pointer type given the pointee type and the
- /// qualifier it refers into.
+ /// class type it refers into.
///
/// 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);
+ QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType,
+ SourceLocation Sigil);
QualType RebuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
SourceLocation ProtocolLAngleLoc,
@@ -5608,30 +5607,31 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
if (PointeeType.isNull())
return QualType();
- const MemberPointerType *T = TL.getTypePtr();
-
- NestedNameSpecifierLoc OldQualifierLoc = TL.getQualifierLoc();
- NestedNameSpecifierLoc NewQualifierLoc =
- getDerived().TransformNestedNameSpecifierLoc(OldQualifierLoc);
- if (!NewQualifierLoc)
- return QualType();
+ TypeSourceInfo* OldClsTInfo = TL.getClassTInfo();
+ TypeSourceInfo *NewClsTInfo = nullptr;
+ if (OldClsTInfo) {
+ NewClsTInfo = getDerived().TransformType(OldClsTInfo);
+ if (!NewClsTInfo)
+ return QualType();
+ }
- CXXRecordDecl *OldCls = T->getMostRecentCXXRecordDecl(), *NewCls = nullptr;
- if (OldCls) {
- NewCls = cast_or_null<CXXRecordDecl>(
- getDerived().TransformDecl(TL.getStarLoc(), OldCls));
- if (!NewCls)
+ const MemberPointerType *T = TL.getTypePtr();
+ QualType OldClsType = QualType(T->getClass(), 0);
+ QualType NewClsType;
+ if (NewClsTInfo)
+ NewClsType = NewClsTInfo->getType();
+ else {
+ NewClsType = getDerived().TransformType(OldClsType);
+ if (NewClsType.isNull())
return QualType();
}
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() ||
- NewQualifierLoc.getNestedNameSpecifier() !=
- OldQualifierLoc.getNestedNameSpecifier() ||
- NewCls != OldCls) {
- Result = getDerived().RebuildMemberPointerType(
- PointeeType, NewQualifierLoc.getNestedNameSpecifier(), NewCls,
- TL.getStarLoc());
+ if (getDerived().AlwaysRebuild() ||
+ PointeeType != T->getPointeeType() ||
+ NewClsType != OldClsType) {
+ Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType,
+ TL.getStarLoc());
if (Result.isNull())
return QualType();
}
@@ -5646,7 +5646,7 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB,
MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result);
NewTL.setSigilLoc(TL.getSigilLoc());
- NewTL.setQualifierLoc(NewQualifierLoc);
+ NewTL.setClassTInfo(NewClsTInfo);
return Result;
}
@@ -17040,11 +17040,12 @@ TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType,
Sigil, getDerived().getBaseEntity());
}
-template <typename Derived>
-QualType TreeTransform<Derived>::RebuildMemberPointerType(
- QualType PointeeType, NestedNameSpecifier *Qualifier, CXXRecordDecl *Cls,
- SourceLocation Sigil) {
- return SemaRef.BuildMemberPointerType(PointeeType, Qualifier, Cls, Sigil,
+template<typename Derived>
+QualType
+TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,
+ QualType ClassType,
+ SourceLocation Sigil) {
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil,
getDerived().getBaseEntity());
}