Skip to content

Commit ad1ef07

Browse files
committed
[clang] resugar decltype of MemberExpr
This keeps around the resugared DeclType for MemberExpr, which is otherwise partially lost as the expression type removes top level references. This helps 'decltype' resugaring work without any loss of information.
1 parent 0a36331 commit ad1ef07

File tree

15 files changed

+129
-53
lines changed

15 files changed

+129
-53
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3263,7 +3263,7 @@ class MemberExpr final
32633263
: public Expr,
32643264
private llvm::TrailingObjects<MemberExpr, NestedNameSpecifierLoc,
32653265
DeclAccessPair, ASTTemplateKWAndArgsInfo,
3266-
TemplateArgumentLoc> {
3266+
TemplateArgumentLoc, QualType> {
32673267
friend class ASTReader;
32683268
friend class ASTStmtReader;
32693269
friend class ASTStmtWriter;
@@ -3304,13 +3304,23 @@ class MemberExpr final
33043304
return MemberExprBits.HasTemplateKWAndArgsInfo;
33053305
}
33063306

3307+
size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
3308+
return getNumTemplateArgs();
3309+
}
3310+
3311+
size_t numTrailingObjects(OverloadToken<QualType>) const {
3312+
return HasResugaredDeclType();
3313+
}
3314+
3315+
static bool needsDeclTypeStorage(ValueDecl *VD, QualType DeclType);
3316+
33073317
MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
33083318
NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc,
33093319
ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
33103320
const DeclarationNameInfo &NameInfo,
33113321
const TemplateArgumentListInfo *TemplateArgs,
33123322
const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
3313-
ExprObjectKind OK, NonOdrUseReason NOUR);
3323+
QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR);
33143324
MemberExpr(EmptyShell Empty)
33153325
: Expr(MemberExprClass, Empty), Base(), MemberDecl() {}
33163326

@@ -3322,7 +3332,7 @@ class MemberExpr final
33223332
DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo,
33233333
const TemplateArgumentListInfo *TemplateArgs,
33243334
const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
3325-
ExprObjectKind OK, NonOdrUseReason NOUR);
3335+
QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR);
33263336

33273337
/// Create an implicit MemberExpr, with no location, qualifier, template
33283338
/// arguments, and so on. Suitable only for non-static member access.
@@ -3333,14 +3343,15 @@ class MemberExpr final
33333343
return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(),
33343344
SourceLocation(), MemberDecl,
33353345
DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()),
3336-
DeclarationNameInfo(), nullptr, /*Deduced=*/{}, T, VK, OK,
3337-
NOUR_None);
3346+
DeclarationNameInfo(), nullptr, /*Deduced=*/{}, T, VK,
3347+
QualType(), OK, NOUR_None);
33383348
}
33393349

33403350
static MemberExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
33413351
bool HasFoundDecl,
33423352
bool HasTemplateKWAndArgsInfo,
3343-
unsigned NumTemplateArgs);
3353+
unsigned NumTemplateArgs,
3354+
bool HasResugaredDeclType);
33443355

33453356
void setBase(Expr *E) { Base = E; }
33463357
Expr *getBase() const { return cast<Expr>(Base); }
@@ -3351,6 +3362,16 @@ class MemberExpr final
33513362
/// static data members), a CXXMethodDecl, or an EnumConstantDecl.
33523363
ValueDecl *getMemberDecl() const { return MemberDecl; }
33533364
void setMemberDecl(ValueDecl *D);
3365+
void recomputeDependency();
3366+
3367+
bool HasResugaredDeclType() const {
3368+
return MemberExprBits.HasResugaredDeclType;
3369+
}
3370+
QualType getDeclType() const {
3371+
return HasResugaredDeclType() ? *getTrailingObjects<QualType>()
3372+
: MemberDecl->getType();
3373+
}
3374+
void setDeclType(QualType T);
33543375

33553376
/// Retrieves the declaration found by lookup.
33563377
DeclAccessPair getFoundDecl() const {

clang/include/clang/AST/Stmt.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,10 @@ class alignas(void *) Stmt {
616616
LLVM_PREFERRED_TYPE(NonOdrUseReason)
617617
unsigned NonOdrUseReason : 2;
618618

619+
/// Consider a different type for the MemberDecl this MemberExpr refers to.
620+
LLVM_PREFERRED_TYPE(bool)
621+
unsigned HasResugaredDeclType : 1;
622+
619623
/// This is the location of the -> or . in the expression.
620624
SourceLocation OperatorLoc;
621625
};

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8709,7 +8709,8 @@ class Sema final : public SemaBase {
87098709
NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
87108710
ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates,
87118711
const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK,
8712-
ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr,
8712+
ExprObjectKind OK, QualType DeclType = QualType(),
8713+
const TemplateArgumentListInfo *TemplateArgs = nullptr,
87138714
const TemplateArgumentList *Deduced = nullptr);
87148715

87158716
// Check whether the declarations we found through a nested-name
@@ -8758,7 +8759,7 @@ class Sema final : public SemaBase {
87588759
ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
87598760
SourceLocation OpLoc,
87608761
const NestedNameSpecifierLoc &NNS,
8761-
FieldDecl *Field, QualType FieldType,
8762+
FieldDecl *Field, QualType FieldDeclType,
87628763
DeclAccessPair FoundDecl,
87638764
const DeclarationNameInfo &MemberNameInfo);
87648765

@@ -14013,6 +14014,7 @@ class Sema final : public SemaBase {
1401314014
QualType resugar(const Type *Base, NamedDecl *ND,
1401414015
ArrayRef<TemplateArgument> Args, QualType T);
1401514016
QualType resugar(DeclRefExpr *DRE, ValueDecl *VD);
14017+
QualType resugar(MemberExpr *ME, ValueDecl *VD);
1401614018

1401714019
/// Performs template instantiation for all implicit template
1401814020
/// instantiations we have seen until this point.

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8452,6 +8452,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
84528452
auto ToDecl = importChecked(Err, E->getFoundDecl().getDecl());
84538453
auto ToName = importChecked(Err, E->getMemberNameInfo().getName());
84548454
auto ToLoc = importChecked(Err, E->getMemberNameInfo().getLoc());
8455+
auto ToDeclType = importChecked(Err, E->getDeclType());
84558456
if (Err)
84568457
return std::move(Err);
84578458

@@ -8473,7 +8474,7 @@ ExpectedStmt ASTNodeImporter::VisitMemberExpr(MemberExpr *E) {
84738474
ToOperatorLoc, ToQualifierLoc, ToTemplateKeywordLoc,
84748475
ToMemberDecl, ToFoundDecl, ToMemberNameInfo,
84758476
ResInfo, ToDeduced, ToType, E->getValueKind(),
8476-
E->getObjectKind(), E->isNonOdrUse());
8477+
ToDeclType, E->getObjectKind(), E->isNonOdrUse());
84778478
}
84788479

84798480
ExpectedStmt

clang/lib/AST/Expr.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,14 +1761,19 @@ UnaryExprOrTypeTraitExpr::UnaryExprOrTypeTraitExpr(
17611761
setDependence(computeDependence(this));
17621762
}
17631763

1764+
bool MemberExpr::needsDeclTypeStorage(ValueDecl *VD, QualType DeclType) {
1765+
return !DeclType.isNull() &&
1766+
(DeclType != VD->getType() || VD->getType()->isUndeducedType());
1767+
}
1768+
17641769
MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
17651770
NestedNameSpecifierLoc QualifierLoc,
17661771
SourceLocation TemplateKWLoc, ValueDecl *MemberDecl,
17671772
DeclAccessPair FoundDecl,
17681773
const DeclarationNameInfo &NameInfo,
17691774
const TemplateArgumentListInfo *TemplateArgs,
17701775
const TemplateArgumentList *Deduced, QualType T,
1771-
ExprValueKind VK, ExprObjectKind OK,
1776+
ExprValueKind VK, QualType DeclType, ExprObjectKind OK,
17721777
NonOdrUseReason NOUR)
17731778
: Expr(MemberExprClass, T, VK, OK), Base(Base), MemberDecl(MemberDecl),
17741779
Deduced(Deduced), MemberDNLoc(NameInfo.getInfo()),
@@ -1784,6 +1789,8 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
17841789
TemplateArgs || TemplateKWLoc.isValid();
17851790
MemberExprBits.HadMultipleCandidates = false;
17861791
MemberExprBits.NonOdrUseReason = NOUR;
1792+
MemberExprBits.HasResugaredDeclType =
1793+
needsDeclTypeStorage(MemberDecl, DeclType);
17871794
MemberExprBits.OperatorLoc = OperatorLoc;
17881795

17891796
if (hasQualifier())
@@ -1800,6 +1807,12 @@ MemberExpr::MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc,
18001807
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
18011808
TemplateKWLoc);
18021809
}
1810+
if (HasResugaredDeclType()) {
1811+
assert(DeclType.getCanonicalType() ==
1812+
MemberDecl->getType().getCanonicalType());
1813+
*getTrailingObjects<QualType>() =
1814+
DeclType.isNull() ? MemberDecl->getType() : DeclType;
1815+
}
18031816
setDependence(computeDependence(this));
18041817
}
18051818

@@ -1809,45 +1822,60 @@ MemberExpr *MemberExpr::Create(
18091822
ValueDecl *MemberDecl, DeclAccessPair FoundDecl,
18101823
DeclarationNameInfo NameInfo, const TemplateArgumentListInfo *TemplateArgs,
18111824
const TemplateArgumentList *Deduced, QualType T, ExprValueKind VK,
1812-
ExprObjectKind OK, NonOdrUseReason NOUR) {
1825+
QualType DeclType, ExprObjectKind OK, NonOdrUseReason NOUR) {
18131826
bool HasQualifier = QualifierLoc.hasQualifier();
18141827
bool HasFoundDecl = FoundDecl.getDecl() != MemberDecl ||
18151828
FoundDecl.getAccess() != MemberDecl->getAccess();
18161829
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
18171830
std::size_t Size =
18181831
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
1819-
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
1832+
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>(
18201833
HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo,
1821-
TemplateArgs ? TemplateArgs->size() : 0);
1834+
TemplateArgs ? TemplateArgs->size() : 0,
1835+
needsDeclTypeStorage(MemberDecl, DeclType) ? 1 : 0);
18221836

18231837
void *Mem = C.Allocate(Size, alignof(MemberExpr));
18241838
return new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, QualifierLoc,
18251839
TemplateKWLoc, MemberDecl, FoundDecl, NameInfo,
1826-
TemplateArgs, Deduced, T, VK, OK, NOUR);
1840+
TemplateArgs, Deduced, T, VK, DeclType, OK, NOUR);
18271841
}
18281842

18291843
MemberExpr *MemberExpr::CreateEmpty(const ASTContext &Context,
18301844
bool HasQualifier, bool HasFoundDecl,
18311845
bool HasTemplateKWAndArgsInfo,
1832-
unsigned NumTemplateArgs) {
1846+
unsigned NumTemplateArgs,
1847+
bool HasResugaredDeclType) {
18331848
assert((!NumTemplateArgs || HasTemplateKWAndArgsInfo) &&
18341849
"template args but no template arg info?");
18351850
std::size_t Size =
18361851
totalSizeToAlloc<NestedNameSpecifierLoc, DeclAccessPair,
1837-
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
1838-
HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo,
1839-
NumTemplateArgs);
1852+
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>(
1853+
HasQualifier, HasFoundDecl, HasTemplateKWAndArgsInfo, NumTemplateArgs,
1854+
HasResugaredDeclType);
18401855
void *Mem = Context.Allocate(Size, alignof(MemberExpr));
18411856
return new (Mem) MemberExpr(EmptyShell());
18421857
}
18431858

18441859
void MemberExpr::setMemberDecl(ValueDecl *NewD) {
1860+
assert(MemberDecl != NewD);
1861+
assert(declaresSameEntity(MemberDecl, NewD));
1862+
assert(!HasResugaredDeclType() ||
1863+
MemberDecl->getASTContext().hasSameType(
1864+
NewD->getType(), *getTrailingObjects<QualType>()));
18451865
MemberDecl = NewD;
1846-
if (getType()->isUndeducedType())
1847-
setType(NewD->getType());
1866+
recomputeDependency();
1867+
}
1868+
1869+
void MemberExpr::recomputeDependency() {
18481870
setDependence(computeDependence(this));
18491871
}
18501872

1873+
void MemberExpr::setDeclType(QualType T) {
1874+
assert(!T.isNull());
1875+
if (HasResugaredDeclType())
1876+
*getTrailingObjects<QualType>() = T;
1877+
}
1878+
18511879
SourceLocation MemberExpr::getBeginLoc() const {
18521880
if (isImplicitAccess()) {
18531881
if (hasQualifier())

clang/lib/Analysis/BodyFarm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl,
232232
SourceLocation(), MemberDecl, FoundDecl,
233233
DeclarationNameInfo(MemberDecl->getDeclName(), SourceLocation()),
234234
/* TemplateArgumentListInfo=*/nullptr, /*Deduced=*/nullptr,
235-
MemberDecl->getType(), ValueKind, OK_Ordinary, NOUR_None);
235+
MemberDecl->getType(), ValueKind, QualType(), OK_Ordinary, NOUR_None);
236236
}
237237

238238
ValueDecl *ASTMaker::findMemberField(const RecordDecl *RD, StringRef Name) {

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1867,7 +1867,7 @@ static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF,
18671867
return DeclRefExpr::Create(
18681868
CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
18691869
/*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
1870-
ME->getType(), ME->getValueKind(), QualType(), nullptr, nullptr,
1870+
ME->getType(), ME->getValueKind(), ME->getDeclType(), nullptr, nullptr,
18711871
nullptr, ME->isNonOdrUse());
18721872
}
18731873
return nullptr;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19537,7 +19537,8 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
1953719537
ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
1953819538
ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
1953919539
CopiedTemplateArgs(ME), ME->getDeduced(), ME->getType(),
19540-
ME->getValueKind(), ME->getObjectKind(), ME->isNonOdrUse());
19540+
ME->getValueKind(), ME->getDeclType(), ME->getObjectKind(),
19541+
ME->isNonOdrUse());
1954119542
}
1954219543

1954319544
if (ME->getMemberDecl()->isCXXInstanceMember())
@@ -19554,7 +19555,7 @@ static ExprResult rebuildPotentialResultsAsNonOdrUsed(Sema &S, Expr *E,
1955419555
S.Context, ME->getBase(), ME->isArrow(), ME->getOperatorLoc(),
1955519556
ME->getQualifierLoc(), ME->getTemplateKeywordLoc(), ME->getMemberDecl(),
1955619557
ME->getFoundDecl(), ME->getMemberNameInfo(), CopiedTemplateArgs(ME),
19557-
ME->getDeduced(), ME->getType(), ME->getValueKind(),
19558+
ME->getDeduced(), ME->getType(), ME->getValueKind(), ME->getDeclType(),
1955819559
ME->getObjectKind(), NOUR);
1955919560
}
1956019561

@@ -19905,17 +19906,9 @@ static void DoMarkVarDeclReferenced(
1990519906
DRE->setType(SemaRef.resugar(DRE, DRE->getDecl()));
1990619907
DRE->recomputeDependency();
1990719908
} else if (auto *ME = dyn_cast_or_null<MemberExpr>(E)) {
19908-
ME->setMemberDecl(ME->getMemberDecl());
19909-
CXXScopeSpec SS;
19910-
SS.Adopt(ME->getQualifierLoc());
19911-
assert(ME->template_arguments().size() == 0 ||
19912-
ME->getDeduced() != nullptr);
19913-
QualType T =
19914-
ME->getDeduced()
19915-
? SemaRef.resugar(SS.getScopeRep(), ME->getMemberDecl(),
19916-
ME->getDeduced()->asArray(), ME->getType())
19917-
: SemaRef.resugar(SS.getScopeRep(), ME->getType());
19918-
ME->setType(T);
19909+
if (ME->getType()->isUndeducedType())
19910+
ME->setType(SemaRef.resugar(ME, ME->getMemberDecl()));
19911+
ME->recomputeDependency();
1991919912
}
1992019913
} else if (FirstInstantiation) {
1992119914
SemaRef.PendingInstantiations

0 commit comments

Comments
 (0)