Skip to content

Commit 29cc63d

Browse files
committed
[clang] resugar decltype of DeclRefExpr
This keeps around the resugared DeclType for DeclRefExpr, 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 002480b commit 29cc63d

File tree

18 files changed

+201
-130
lines changed

18 files changed

+201
-130
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,7 +1266,7 @@ class DeclRefExpr final
12661266
: public Expr,
12671267
private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc,
12681268
NamedDecl *, ASTTemplateKWAndArgsInfo,
1269-
TemplateArgumentLoc> {
1269+
TemplateArgumentLoc, QualType> {
12701270
friend class ASTStmtReader;
12711271
friend class ASTStmtWriter;
12721272
friend TrailingObjects;
@@ -1292,17 +1292,27 @@ class DeclRefExpr final
12921292
return hasTemplateKWAndArgsInfo();
12931293
}
12941294

1295+
size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
1296+
return getNumTemplateArgs();
1297+
}
1298+
1299+
size_t numTrailingObjects(OverloadToken<QualType>) const {
1300+
return HasResugaredDeclType();
1301+
}
1302+
12951303
/// Test whether there is a distinct FoundDecl attached to the end of
12961304
/// this DRE.
12971305
bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; }
12981306

1307+
static bool needsDeclTypeStorage(ValueDecl *VD, QualType DeclType);
1308+
12991309
DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
13001310
SourceLocation TemplateKWLoc, ValueDecl *D,
13011311
bool RefersToEnclosingVariableOrCapture,
13021312
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
13031313
const TemplateArgumentListInfo *TemplateArgs,
13041314
const TemplateArgumentList *ConvertedArgs, QualType T,
1305-
ExprValueKind VK, NonOdrUseReason NOUR);
1315+
ExprValueKind VK, QualType DeclType, NonOdrUseReason NOUR);
13061316

13071317
/// Construct an empty declaration reference expression.
13081318
explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {}
@@ -1318,7 +1328,8 @@ class DeclRefExpr final
13181328
Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
13191329
SourceLocation TemplateKWLoc, ValueDecl *D,
13201330
bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
1321-
QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
1331+
QualType T, ExprValueKind VK, QualType DeclType = QualType(),
1332+
NamedDecl *FoundD = nullptr,
13221333
const TemplateArgumentListInfo *TemplateArgs = nullptr,
13231334
const TemplateArgumentList *ConvertedArgs = nullptr,
13241335
NonOdrUseReason NOUR = NOUR_None);
@@ -1328,7 +1339,7 @@ class DeclRefExpr final
13281339
SourceLocation TemplateKWLoc, ValueDecl *D,
13291340
bool RefersToEnclosingVariableOrCapture,
13301341
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
1331-
NamedDecl *FoundD = nullptr,
1342+
QualType DeclType = QualType(), NamedDecl *FoundD = nullptr,
13321343
const TemplateArgumentListInfo *TemplateArgs = nullptr,
13331344
const TemplateArgumentList *ConvertedArgs = nullptr,
13341345
NonOdrUseReason NOUR = NOUR_None);
@@ -1337,11 +1348,22 @@ class DeclRefExpr final
13371348
static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier,
13381349
bool HasFoundDecl,
13391350
bool HasTemplateKWAndArgsInfo,
1340-
unsigned NumTemplateArgs);
1351+
unsigned NumTemplateArgs,
1352+
bool HasResugaredDeclType);
13411353

13421354
ValueDecl *getDecl() { return D; }
13431355
const ValueDecl *getDecl() const { return D; }
13441356
void setDecl(ValueDecl *NewD);
1357+
void recomputeDependency();
1358+
1359+
bool HasResugaredDeclType() const {
1360+
return DeclRefExprBits.HasResugaredDeclType;
1361+
}
1362+
QualType getDeclType() const {
1363+
return HasResugaredDeclType() ? *getTrailingObjects<QualType>()
1364+
: D->getType();
1365+
}
1366+
void setDeclType(QualType T);
13451367

13461368
DeclarationNameInfo getNameInfo() const {
13471369
return DeclarationNameInfo(getDecl()->getDeclName(), getLocation(), DNLoc);

clang/include/clang/AST/Stmt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ class alignas(void *) Stmt {
448448
unsigned NonOdrUseReason : 2;
449449
LLVM_PREFERRED_TYPE(bool)
450450
unsigned IsImmediateEscalating : 1;
451+
LLVM_PREFERRED_TYPE(bool)
452+
unsigned HasResugaredDeclType : 1;
451453

452454
/// The location of the declaration name itself.
453455
SourceLocation Loc;

clang/include/clang/Sema/Sema.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6848,22 +6848,23 @@ class Sema final : public SemaBase {
68486848

68496849
DeclRefExpr *BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
68506850
SourceLocation Loc,
6851+
QualType DeclType = QualType(),
68516852
const CXXScopeSpec *SS = nullptr);
6852-
DeclRefExpr *
6853-
BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
6854-
const DeclarationNameInfo &NameInfo,
6855-
const CXXScopeSpec *SS = nullptr,
6856-
NamedDecl *FoundD = nullptr,
6857-
SourceLocation TemplateKWLoc = SourceLocation(),
6858-
const TemplateArgumentListInfo *TemplateArgs = nullptr,
6859-
const TemplateArgumentList *ConvertArgs = nullptr);
6853+
DeclRefExpr *BuildDeclRefExpr(
6854+
ValueDecl *D, QualType Ty, ExprValueKind VK,
6855+
const DeclarationNameInfo &NameInfo, QualType DeclType = QualType(),
6856+
const CXXScopeSpec *SS = nullptr, NamedDecl *FoundD = nullptr,
6857+
SourceLocation TemplateKWLoc = SourceLocation(),
6858+
const TemplateArgumentListInfo *TemplateArgs = nullptr,
6859+
const TemplateArgumentList *ConvertArgs = nullptr);
68606860

68616861
/// BuildDeclRefExpr - Build an expression that references a
68626862
/// declaration that does not require a closure capture.
68636863
DeclRefExpr *
68646864
BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
68656865
const DeclarationNameInfo &NameInfo,
6866-
NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr,
6866+
NestedNameSpecifierLoc NNS, QualType DeclType = QualType(),
6867+
NamedDecl *FoundD = nullptr,
68676868
SourceLocation TemplateKWLoc = SourceLocation(),
68686869
const TemplateArgumentListInfo *TemplateArgs = nullptr,
68696870
const TemplateArgumentList *ConvertArgs = nullptr);
@@ -14006,6 +14007,7 @@ class Sema final : public SemaBase {
1400614007
QualType resugar(const Type *Base, QualType T);
1400714008
QualType resugar(const Type *Base, NamedDecl *ND,
1400814009
ArrayRef<TemplateArgument> Args, QualType T);
14010+
QualType resugar(DeclRefExpr *DRE, ValueDecl *VD);
1400914011

1401014012
/// Performs template instantiation for all implicit template
1401114013
/// 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
@@ -7503,6 +7503,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
75037503
auto ToConvertedArgs = importChecked(Err, E->getConvertedArgs());
75047504
auto ToLocation = importChecked(Err, E->getLocation());
75057505
auto ToType = importChecked(Err, E->getType());
7506+
auto ToDeclType = importChecked(Err, E->getDeclType());
75067507
if (Err)
75077508
return std::move(Err);
75087509

@@ -7527,7 +7528,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
75277528
auto *ToE = DeclRefExpr::Create(
75287529
Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
75297530
E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
7530-
E->getValueKind(), ToFoundD, ToResInfo, ToConvertedArgs,
7531+
E->getValueKind(), ToDeclType, ToFoundD, ToResInfo, ToConvertedArgs,
75317532
E->isNonOdrUse());
75327533
if (E->hadMultipleCandidates())
75337534
ToE->setHadMultipleCandidates(true);

clang/lib/AST/Expr.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,11 @@ APValue ConstantExpr::getAPValueResult() const {
426426
llvm_unreachable("invalid ResultKind");
427427
}
428428

429+
bool DeclRefExpr::needsDeclTypeStorage(ValueDecl *VD, QualType DeclType) {
430+
return !DeclType.isNull() &&
431+
(DeclType != VD->getType() || VD->getType()->isUndeducedType());
432+
}
433+
429434
DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
430435
bool RefersToEnclosingVariableOrCapture, QualType T,
431436
ExprValueKind VK, SourceLocation L,
@@ -442,6 +447,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, ValueDecl *D,
442447
DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false;
443448
DeclRefExprBits.NonOdrUseReason = NOUR;
444449
DeclRefExprBits.IsImmediateEscalating = false;
450+
DeclRefExprBits.HasResugaredDeclType = false;
445451
DeclRefExprBits.Loc = L;
446452
setDependence(computeDependence(this, Ctx));
447453
}
@@ -453,7 +459,8 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
453459
const DeclarationNameInfo &NameInfo, NamedDecl *FoundD,
454460
const TemplateArgumentListInfo *TemplateArgs,
455461
const TemplateArgumentList *ConvertedArgs, QualType T,
456-
ExprValueKind VK, NonOdrUseReason NOUR)
462+
ExprValueKind VK, QualType DeclType,
463+
NonOdrUseReason NOUR)
457464
: Expr(DeclRefExprClass, T, VK, OK_Ordinary), D(D),
458465
ConvertedArgs(ConvertedArgs), DNLoc(NameInfo.getInfo()) {
459466
assert(!TemplateArgs || ConvertedArgs);
@@ -472,6 +479,7 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
472479
RefersToEnclosingVariableOrCapture;
473480
DeclRefExprBits.CapturedByCopyInLambdaWithExplicitObjectParameter = false;
474481
DeclRefExprBits.NonOdrUseReason = NOUR;
482+
DeclRefExprBits.HasResugaredDeclType = needsDeclTypeStorage(D, DeclType);
475483
if (TemplateArgs) {
476484
auto Deps = TemplateArgumentDependence::None;
477485
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
@@ -483,72 +491,92 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
483491
getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
484492
TemplateKWLoc);
485493
}
494+
if (HasResugaredDeclType()) {
495+
assert(Ctx.hasSameType(DeclType, D->getType()));
496+
*getTrailingObjects<QualType>() =
497+
DeclType.isNull() ? D->getType() : DeclType;
498+
}
486499
DeclRefExprBits.IsImmediateEscalating = false;
487500
DeclRefExprBits.HadMultipleCandidates = 0;
488501
setDependence(computeDependence(this, Ctx));
489502
}
490503

504+
DeclRefExpr *DeclRefExpr::Create(
505+
const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
506+
SourceLocation TemplateKWLoc, ValueDecl *D,
507+
bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T,
508+
ExprValueKind VK, QualType DeclType, NamedDecl *FoundD,
509+
const TemplateArgumentListInfo *TemplateArgs,
510+
const TemplateArgumentList *ConvertedArgs, NonOdrUseReason NOUR) {
511+
return Create(Context, QualifierLoc, TemplateKWLoc, D,
512+
RefersToEnclosingVariableOrCapture,
513+
DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, DeclType,
514+
FoundD, TemplateArgs, ConvertedArgs, NOUR);
515+
}
516+
491517
DeclRefExpr *DeclRefExpr::Create(const ASTContext &Context,
492518
NestedNameSpecifierLoc QualifierLoc,
493519
SourceLocation TemplateKWLoc, ValueDecl *D,
494520
bool RefersToEnclosingVariableOrCapture,
495-
SourceLocation NameLoc, QualType T,
496-
ExprValueKind VK, NamedDecl *FoundD,
521+
const DeclarationNameInfo &NameInfo,
522+
QualType T, ExprValueKind VK,
523+
QualType DeclType, NamedDecl *FoundD,
497524
const TemplateArgumentListInfo *TemplateArgs,
498525
const TemplateArgumentList *ConvertedArgs,
499526
NonOdrUseReason NOUR) {
500-
return Create(Context, QualifierLoc, TemplateKWLoc, D,
501-
RefersToEnclosingVariableOrCapture,
502-
DeclarationNameInfo(D->getDeclName(), NameLoc), T, VK, FoundD,
503-
TemplateArgs, ConvertedArgs, NOUR);
504-
}
505-
506-
DeclRefExpr *DeclRefExpr::Create(
507-
const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
508-
SourceLocation TemplateKWLoc, ValueDecl *D,
509-
bool RefersToEnclosingVariableOrCapture,
510-
const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
511-
NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs,
512-
const TemplateArgumentList *ConvertedArgs, NonOdrUseReason NOUR) {
513527
// Filter out cases where the found Decl is the same as the value refenenced.
514528
if (D == FoundD)
515529
FoundD = nullptr;
516530

517531
bool HasTemplateKWAndArgsInfo = TemplateArgs || TemplateKWLoc.isValid();
518532
std::size_t Size =
519533
totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *,
520-
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
534+
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>(
521535
QualifierLoc ? 1 : 0, FoundD ? 1 : 0,
522536
HasTemplateKWAndArgsInfo ? 1 : 0,
523-
TemplateArgs ? TemplateArgs->size() : 0);
537+
TemplateArgs ? TemplateArgs->size() : 0,
538+
needsDeclTypeStorage(D, DeclType) ? 1 : 0);
524539

525540
void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
526541
return new (Mem)
527542
DeclRefExpr(Context, QualifierLoc, TemplateKWLoc, D,
528543
RefersToEnclosingVariableOrCapture, NameInfo, FoundD,
529-
TemplateArgs, ConvertedArgs, T, VK, NOUR);
544+
TemplateArgs, ConvertedArgs, T, VK, DeclType, NOUR);
530545
}
531546

532547
DeclRefExpr *DeclRefExpr::CreateEmpty(const ASTContext &Context,
533-
bool HasQualifier,
534-
bool HasFoundDecl,
548+
bool HasQualifier, bool HasFoundDecl,
535549
bool HasTemplateKWAndArgsInfo,
536-
unsigned NumTemplateArgs) {
550+
unsigned NumTemplateArgs,
551+
bool HasResugaredDeclType) {
537552
assert(NumTemplateArgs == 0 || HasTemplateKWAndArgsInfo);
538553
std::size_t Size =
539554
totalSizeToAlloc<NestedNameSpecifierLoc, NamedDecl *,
540-
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(
555+
ASTTemplateKWAndArgsInfo, TemplateArgumentLoc, QualType>(
541556
HasQualifier ? 1 : 0, HasFoundDecl ? 1 : 0, HasTemplateKWAndArgsInfo,
542-
NumTemplateArgs);
557+
NumTemplateArgs, HasResugaredDeclType ? 1 : 0);
543558
void *Mem = Context.Allocate(Size, alignof(DeclRefExpr));
544559
return new (Mem) DeclRefExpr(EmptyShell());
545560
}
546561

547562
void DeclRefExpr::setDecl(ValueDecl *NewD) {
563+
assert(D != NewD);
564+
assert(declaresSameEntity(D, NewD));
565+
assert(!HasResugaredDeclType() ||
566+
D->getASTContext().hasSameType(NewD->getType(),
567+
*getTrailingObjects<QualType>()));
548568
D = NewD;
549-
if (getType()->isUndeducedType())
550-
setType(NewD->getType());
551-
setDependence(computeDependence(this, NewD->getASTContext()));
569+
recomputeDependency();
570+
}
571+
572+
void DeclRefExpr::recomputeDependency() {
573+
setDependence(computeDependence(this, D->getASTContext()));
574+
}
575+
576+
void DeclRefExpr::setDeclType(QualType T) {
577+
assert(!T.isNull());
578+
if (HasResugaredDeclType())
579+
*getTrailingObjects<QualType>() = T;
552580
}
553581

554582
SourceLocation DeclRefExpr::getBeginLoc() const {

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,8 +1850,8 @@ static DeclRefExpr *tryToConvertMemberExprToDeclRefExpr(CodeGenFunction &CGF,
18501850
return DeclRefExpr::Create(
18511851
CGF.getContext(), NestedNameSpecifierLoc(), SourceLocation(), VD,
18521852
/*RefersToEnclosingVariableOrCapture=*/false, ME->getExprLoc(),
1853-
ME->getType(), ME->getValueKind(), nullptr, nullptr, nullptr,
1854-
ME->isNonOdrUse());
1853+
ME->getType(), ME->getValueKind(), QualType(), nullptr, nullptr,
1854+
nullptr, ME->isNonOdrUse());
18551855
}
18561856
return nullptr;
18571857
}

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4632,7 +4632,8 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) {
46324632
DeclRefExpr *NewDRE = DeclRefExpr::Create(
46334633
Context, DRE->getQualifierLoc(), SourceLocation(), NewBuiltinDecl,
46344634
/*enclosing*/ false, DRE->getLocation(), Context.BuiltinFnTy,
4635-
DRE->getValueKind(), nullptr, nullptr, nullptr, DRE->isNonOdrUse());
4635+
DRE->getValueKind(), QualType(), nullptr, nullptr, nullptr,
4636+
DRE->isNonOdrUse());
46364637

46374638
// Set the callee in the CallExpr.
46384639
// FIXME: This loses syntactic information.

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4951,11 +4951,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
49514951
ParmVarDecl *Param = Constructor->getParamDecl(0);
49524952
QualType ParamType = Param->getType().getNonReferenceType();
49534953

4954-
Expr *CopyCtorArg =
4955-
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
4956-
SourceLocation(), Param, false,
4957-
Constructor->getLocation(), ParamType,
4958-
VK_LValue, nullptr);
4954+
Expr *CopyCtorArg = DeclRefExpr::Create(
4955+
SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param,
4956+
false, Constructor->getLocation(), ParamType, VK_LValue);
49594957

49604958
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
49614959

@@ -5025,10 +5023,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
50255023
if (Field->isZeroLengthBitField())
50265024
return false;
50275025

5028-
Expr *MemberExprBase =
5029-
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
5030-
SourceLocation(), Param, false,
5031-
Loc, ParamType, VK_LValue, nullptr);
5026+
Expr *MemberExprBase = DeclRefExpr::Create(
5027+
SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param,
5028+
false, Loc, ParamType, VK_LValue);
50325029

50335030
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
50345031

@@ -14693,8 +14690,8 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
1469314690
// about it.
1469414691
return StmtError();
1469514692

14696-
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
14697-
VK_PRValue, Loc, nullptr);
14693+
ExprResult MemCpyRef =
14694+
S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, VK_PRValue, Loc);
1469814695
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
1469914696

1470014697
Expr *CallArgs[] = {

0 commit comments

Comments
 (0)