Skip to content

Commit 6ad2cf2

Browse files
committed
[FOLD] fix crash when getting source range of undeserialized declarations
1 parent c0d0966 commit 6ad2cf2

File tree

3 files changed

+99
-51
lines changed

3 files changed

+99
-51
lines changed

clang/include/clang/AST/DeclTemplate.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,7 @@ class ClassTemplatePartialSpecializationDecl
21872187
/// template<> template<typename T>
21882188
/// struct X<int>::Inner<T*> { /* ... */ };
21892189
/// \endcode
2190-
bool isMemberSpecialization() {
2190+
bool isMemberSpecialization() const {
21912191
const auto *First =
21922192
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
21932193
return First->InstantiatedFromMember.getInt();
@@ -2210,6 +2210,8 @@ class ClassTemplatePartialSpecializationDecl
22102210
->getInjectedSpecializationType();
22112211
}
22122212

2213+
SourceRange getSourceRange() const override LLVM_READONLY;
2214+
22132215
void Profile(llvm::FoldingSetNodeID &ID) const {
22142216
Profile(ID, getTemplateArgs().asArray(), getTemplateParameters(),
22152217
getASTContext());
@@ -2947,7 +2949,7 @@ class VarTemplatePartialSpecializationDecl
29472949
/// template<> template<typename T>
29482950
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
29492951
/// \endcode
2950-
bool isMemberSpecialization() {
2952+
bool isMemberSpecialization() const {
29512953
const auto *First =
29522954
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
29532955
return First->InstantiatedFromMember.getInt();

clang/lib/AST/DeclTemplate.cpp

Lines changed: 89 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -985,36 +985,40 @@ ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
985985

986986
SourceRange
987987
ClassTemplateSpecializationDecl::getSourceRange() const {
988-
if (getSpecializationKind() == TSK_ExplicitInstantiationDeclaration) {
989-
return SourceRange(getExternKeywordLoc(),
990-
getTemplateArgsAsWritten()->getRAngleLoc());
991-
} else if (getSpecializationKind() == TSK_ExplicitInstantiationDefinition) {
992-
return SourceRange(getTemplateKeywordLoc(),
993-
getTemplateArgsAsWritten()->getRAngleLoc());
994-
} else if (!isExplicitSpecialization()) {
995-
// No explicit info available.
988+
switch (getSpecializationKind()) {
989+
case TSK_Undeclared:
990+
case TSK_ImplicitInstantiation: {
996991
llvm::PointerUnion<ClassTemplateDecl *,
997992
ClassTemplatePartialSpecializationDecl *>
998-
InstFrom = getInstantiatedFrom();
999-
if (InstFrom.isNull())
1000-
return getSpecializedTemplate()->getSourceRange();
1001-
if (const auto *CTD = InstFrom.dyn_cast<ClassTemplateDecl *>())
1002-
return CTD->getSourceRange();
1003-
return InstFrom.get<ClassTemplatePartialSpecializationDecl *>()
1004-
->getSourceRange();
993+
Pattern = getSpecializedTemplateOrPartial();
994+
assert(!Pattern.isNull() &&
995+
"Class template specialization without pattern?");
996+
if (const auto *CTPSD =
997+
Pattern.dyn_cast<ClassTemplatePartialSpecializationDecl *>())
998+
return CTPSD->getSourceRange();
999+
return Pattern.get<ClassTemplateDecl *>()->getSourceRange();
1000+
}
1001+
case TSK_ExplicitSpecialization: {
1002+
SourceRange Range = CXXRecordDecl::getSourceRange();
1003+
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1004+
!isThisDeclarationADefinition() && Args)
1005+
Range.setEnd(Args->getRAngleLoc());
1006+
return Range;
1007+
}
1008+
case TSK_ExplicitInstantiationDeclaration:
1009+
case TSK_ExplicitInstantiationDefinition: {
1010+
SourceRange Range = CXXRecordDecl::getSourceRange();
1011+
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1012+
Range.setBegin(ExternKW);
1013+
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1014+
TemplateKW.isValid())
1015+
Range.setBegin(TemplateKW);
1016+
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1017+
Range.setEnd(Args->getRAngleLoc());
1018+
return Range;
10051019
}
1006-
SourceLocation Begin = TagDecl::getOuterLocStart();
1007-
if (const auto *CTPSD =
1008-
dyn_cast<ClassTemplatePartialSpecializationDecl>(this)) {
1009-
if (const auto *InstFrom = CTPSD->getInstantiatedFromMember())
1010-
return InstFrom->getSourceRange();
1011-
else if (!getNumTemplateParameterLists())
1012-
Begin = CTPSD->getTemplateParameters()->getTemplateLoc();
10131020
}
1014-
SourceLocation End = getBraceRange().getEnd();
1015-
if (End.isInvalid())
1016-
End = getTemplateArgsAsWritten()->getRAngleLoc();
1017-
return SourceRange(Begin, End);
1021+
llvm_unreachable("unhandled template specialization kind");
10181022
}
10191023

10201024
void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
@@ -1147,6 +1151,18 @@ ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
11471151
return Result;
11481152
}
11491153

1154+
SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
1155+
if (const ClassTemplatePartialSpecializationDecl *MT =
1156+
getInstantiatedFromMember();
1157+
MT && !isMemberSpecialization())
1158+
return MT->getSourceRange();
1159+
SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
1160+
if (const TemplateParameterList *TPL = getTemplateParameters();
1161+
TPL && !getNumTemplateParameterLists())
1162+
Range.setBegin(TPL->getTemplateLoc());
1163+
return Range;
1164+
}
1165+
11501166
//===----------------------------------------------------------------------===//
11511167
// FriendTemplateDecl Implementation
11521168
//===----------------------------------------------------------------------===//
@@ -1380,19 +1396,45 @@ VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
13801396
}
13811397

13821398
SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
1383-
if (isExplicitSpecialization() && !hasInit()) {
1384-
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
1385-
return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
1386-
} else if (getTemplateSpecializationKind() ==
1387-
TSK_ExplicitInstantiationDeclaration) {
1388-
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
1389-
return SourceRange(getExternKeywordLoc(), Info->getRAngleLoc());
1390-
} else if (getTemplateSpecializationKind() ==
1391-
TSK_ExplicitInstantiationDefinition) {
1392-
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
1393-
return SourceRange(getTemplateKeywordLoc(), Info->getRAngleLoc());
1399+
switch (getSpecializationKind()) {
1400+
case TSK_Undeclared:
1401+
case TSK_ImplicitInstantiation: {
1402+
llvm::PointerUnion<VarTemplateDecl *,
1403+
VarTemplatePartialSpecializationDecl *>
1404+
Pattern = getSpecializedTemplateOrPartial();
1405+
assert(!Pattern.isNull() &&
1406+
"Variable template specialization without pattern?");
1407+
if (const auto *VTPSD =
1408+
Pattern.dyn_cast<VarTemplatePartialSpecializationDecl *>())
1409+
return VTPSD->getSourceRange();
1410+
VarTemplateDecl *VTD = Pattern.get<VarTemplateDecl *>();
1411+
if (hasInit()) {
1412+
if (VarTemplateDecl *Definition = VTD->getDefinition())
1413+
return Definition->getSourceRange();
1414+
}
1415+
return VTD->getCanonicalDecl()->getSourceRange();
1416+
}
1417+
case TSK_ExplicitSpecialization: {
1418+
SourceRange Range = VarDecl::getSourceRange();
1419+
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1420+
!hasInit() && Args)
1421+
Range.setEnd(Args->getRAngleLoc());
1422+
return Range;
1423+
}
1424+
case TSK_ExplicitInstantiationDeclaration:
1425+
case TSK_ExplicitInstantiationDefinition: {
1426+
SourceRange Range = VarDecl::getSourceRange();
1427+
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1428+
Range.setBegin(ExternKW);
1429+
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1430+
TemplateKW.isValid())
1431+
Range.setBegin(TemplateKW);
1432+
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1433+
Range.setEnd(Args->getRAngleLoc());
1434+
return Range;
13941435
}
1395-
return VarDecl::getSourceRange();
1436+
}
1437+
llvm_unreachable("unhandled template specialization kind");
13961438
}
13971439

13981440
void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
@@ -1460,11 +1502,15 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
14601502
}
14611503

14621504
SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
1463-
if (isExplicitSpecialization() && !hasInit()) {
1464-
if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
1465-
return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
1466-
}
1467-
return VarDecl::getSourceRange();
1505+
if (const VarTemplatePartialSpecializationDecl *MT =
1506+
getInstantiatedFromMember();
1507+
MT && !isMemberSpecialization())
1508+
return MT->getSourceRange();
1509+
SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
1510+
if (const TemplateParameterList *TPL = getTemplateParameters();
1511+
TPL && !getNumTemplateParameterLists())
1512+
Range.setBegin(TPL->getTemplateLoc());
1513+
return Range;
14681514
}
14691515

14701516
static TemplateParameterList *

clang/test/AST/ast-dump-decl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -613,15 +613,15 @@ namespace testCanonicalTemplate {
613613
// CHECK: VarTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-11]]:7, col:43> col:43 TestVarTemplate{{$}}
614614
// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <col:16, col:25> col:25 referenced typename depth 0 index 0 T{{$}}
615615
// CHECK-NEXT: |-VarDecl 0x{{.+}} <col:28, col:43> col:43 TestVarTemplate 'const T' static{{$}}
616-
// CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-11]]:3, col:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
616+
// CHECK-NEXT: |-VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <line:[[@LINE-12]]:3, line:[[@LINE-11]]:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
617617
// CHECK-NEXT: | |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}}
618618
// CHECK-NEXT: | |-TemplateArgument type 'int'{{$}}
619619
// CHECK-NEXT: | | `-BuiltinType 0x{{.+}} 'int'{{$}}
620620
// CHECK-NEXT: | `-InitListExpr 0x{{.+}} <col:32, col:34> 'int'{{$}}
621-
// CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}} <line:[[@LINE-19]]:28, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
621+
// CHECK-NEXT: `-VarTemplateSpecializationDecl 0x{{.+}} <line:[[@LINE-19]]:7, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
622622
// CHECK-NEXT: `-TemplateArgument type 'int'{{$}}
623623

624-
// CHECK: VarTemplateSpecializationDecl 0x{{.+}} <{{.+}}:[[@LINE-22]]:28, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
624+
// CHECK: VarTemplateSpecializationDecl 0x{{.+}} <{{.+}}:[[@LINE-22]]:7, col:43> col:43 referenced TestVarTemplate 'const int' implicit_instantiation static{{$}}
625625
// CHECK-NEXT:`-TemplateArgument type 'int'{{$}}
626626
// CHECK-NEXT: `-BuiltinType 0x{{.+}} 'int'{{$}}
627627

@@ -632,13 +632,13 @@ namespace testCanonicalTemplate {
632632
// CHECK-NEXT: | `-InitListExpr 0x{{.+}} <col:32, col:34> 'void'{{$}}
633633
// CHECK-NEXT: |-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}}
634634
// CHECK-NEXT: `-VarTemplateSpecialization 0x{{.+}} 'TestVarTemplate' 'const int'{{$}}
635-
636-
// CHECK: VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-31]]:3, col:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
635+
636+
// CHECK: VarTemplateSpecializationDecl 0x{{.+}} parent 0x{{.+}} prev 0x{{.+}} <{{.+}}:[[@LINE-32]]:3, line:[[@LINE-31]]:34> col:14 referenced TestVarTemplate 'const int' implicit_instantiation cinit{{$}}
637637
// CHECK-NEXT: |-NestedNameSpecifier TypeSpec 'testCanonicalTemplate::S'{{$}}
638638
// CHECK-NEXT: |-TemplateArgument type 'int'{{$}}
639639
// CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'int'{{$}}
640640
// CHECK-NEXT: `-InitListExpr 0x{{.+}} <col:32, col:34> 'int'{{$}}
641-
}
641+
}
642642

643643
template <class T>
644644
class TestClassScopeFunctionSpecialization {

0 commit comments

Comments
 (0)