Skip to content

Commit 0a36331

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 df203b5 commit 0a36331

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
@@ -6849,22 +6849,23 @@ class Sema final : public SemaBase {
68496849

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

68626862
/// BuildDeclRefExpr - Build an expression that references a
68636863
/// declaration that does not require a closure capture.
68646864
DeclRefExpr *
68656865
BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
68666866
const DeclarationNameInfo &NameInfo,
6867-
NestedNameSpecifierLoc NNS, NamedDecl *FoundD = nullptr,
6867+
NestedNameSpecifierLoc NNS, QualType DeclType = QualType(),
6868+
NamedDecl *FoundD = nullptr,
68686869
SourceLocation TemplateKWLoc = SourceLocation(),
68696870
const TemplateArgumentListInfo *TemplateArgs = nullptr,
68706871
const TemplateArgumentList *ConvertArgs = nullptr);
@@ -14011,6 +14012,7 @@ class Sema final : public SemaBase {
1401114012
QualType resugar(const Type *Base, QualType T);
1401214013
QualType resugar(const Type *Base, NamedDecl *ND,
1401314014
ArrayRef<TemplateArgument> Args, QualType T);
14015+
QualType resugar(DeclRefExpr *DRE, ValueDecl *VD);
1401414016

1401514017
/// Performs template instantiation for all implicit template
1401614018
/// 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
@@ -7496,6 +7496,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
74967496
auto ToConvertedArgs = importChecked(Err, E->getConvertedArgs());
74977497
auto ToLocation = importChecked(Err, E->getLocation());
74987498
auto ToType = importChecked(Err, E->getType());
7499+
auto ToDeclType = importChecked(Err, E->getDeclType());
74997500
if (Err)
75007501
return std::move(Err);
75017502

@@ -7520,7 +7521,7 @@ ExpectedStmt ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) {
75207521
auto *ToE = DeclRefExpr::Create(
75217522
Importer.getToContext(), ToQualifierLoc, ToTemplateKeywordLoc, ToDecl,
75227523
E->refersToEnclosingVariableOrCapture(), ToLocation, ToType,
7523-
E->getValueKind(), ToFoundD, ToResInfo, ToConvertedArgs,
7524+
E->getValueKind(), ToDeclType, ToFoundD, ToResInfo, ToConvertedArgs,
75247525
E->isNonOdrUse());
75257526
if (E->hadMultipleCandidates())
75267527
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
@@ -1867,8 +1867,8 @@ 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(), nullptr, nullptr, nullptr,
1871-
ME->isNonOdrUse());
1870+
ME->getType(), ME->getValueKind(), QualType(), nullptr, nullptr,
1871+
nullptr, ME->isNonOdrUse());
18721872
}
18731873
return nullptr;
18741874
}

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
@@ -4920,11 +4920,9 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
49204920
ParmVarDecl *Param = Constructor->getParamDecl(0);
49214921
QualType ParamType = Param->getType().getNonReferenceType();
49224922

4923-
Expr *CopyCtorArg =
4924-
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
4925-
SourceLocation(), Param, false,
4926-
Constructor->getLocation(), ParamType,
4927-
VK_LValue, nullptr);
4923+
Expr *CopyCtorArg = DeclRefExpr::Create(
4924+
SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param,
4925+
false, Constructor->getLocation(), ParamType, VK_LValue);
49284926

49294927
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
49304928

@@ -4994,10 +4992,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
49944992
if (Field->isZeroLengthBitField())
49954993
return false;
49964994

4997-
Expr *MemberExprBase =
4998-
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
4999-
SourceLocation(), Param, false,
5000-
Loc, ParamType, VK_LValue, nullptr);
4995+
Expr *MemberExprBase = DeclRefExpr::Create(
4996+
SemaRef.Context, NestedNameSpecifierLoc(), SourceLocation(), Param,
4997+
false, Loc, ParamType, VK_LValue);
50014998

50024999
SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
50035000

@@ -14676,8 +14673,8 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
1467614673
// about it.
1467714674
return StmtError();
1467814675

14679-
ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
14680-
VK_PRValue, Loc, nullptr);
14676+
ExprResult MemCpyRef =
14677+
S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, VK_PRValue, Loc);
1468114678
assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");
1468214679

1468314680
Expr *CallArgs[] = {

0 commit comments

Comments
 (0)