Skip to content

Commit 74fd474

Browse files
committed
[clang] Evaluate non-type default template argument when it is required
Before this change a default template argument for a non-type template parameter was evaluated and checked immediately after it is met by parser. In some cases it is too early. Fixes #62224 Fixes #62596 Reviewed By: shafik, erichkeane, cor3ntin Differential Revision: https://reviews.llvm.org/D150108
1 parent cac4d7f commit 74fd474

File tree

10 files changed

+41
-24
lines changed

10 files changed

+41
-24
lines changed

clang/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,10 @@ Bug Fixes in This Version
376376
- Fix crash when attempting to pass a non-pointer type as first argument of
377377
``__builtin_assume_aligned``.
378378
(`#62305 <https://github.com/llvm/llvm-project/issues/62305>`_)
379+
- A default argument for a non-type template parameter is evaluated and checked
380+
at the point where it is required. This fixes:
381+
(`#62224 <https://github.com/llvm/llvm-project/issues/62224>`_) and
382+
(`#62596 <https://github.com/llvm/llvm-project/issues/62596>`_)
379383

380384
Bug Fixes to Compiler Builtins
381385
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplate.cpp

-10
Original file line numberDiff line numberDiff line change
@@ -1610,16 +1610,6 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
16101610
if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument))
16111611
return Param;
16121612

1613-
TemplateArgument SugaredConverted, CanonicalConverted;
1614-
ExprResult DefaultRes = CheckTemplateArgument(
1615-
Param, Param->getType(), Default, SugaredConverted, CanonicalConverted,
1616-
CTAK_Specified);
1617-
if (DefaultRes.isInvalid()) {
1618-
Param->setInvalidDecl();
1619-
return Param;
1620-
}
1621-
Default = DefaultRes.get();
1622-
16231613
Param->setDefaultArgument(Default);
16241614
}
16251615

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

+2-6
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,7 @@ namespace testClassTemplateDecl {
455455
// CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:[[@LINE-148]]:3, col:31> col:31 TestTemplateDefaultNonType
456456
// CHECK-NEXT: |-NonTypeTemplateParmDecl 0x{{.+}} <col:12, col:20> col:16 'int' depth 0 index 0 I
457457
// CHECK-NEXT: | `-TemplateArgument expr
458-
// CHECK-NEXT: | `-ConstantExpr 0x{{.+}} <col:20> 'int'
459-
// CHECK-NEXT: | |-value: Int 42
460-
// CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <col:20> 'int' 42
458+
// CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <col:20> 'int' 42
461459
// CHECK-NEXT: `-CXXRecordDecl 0x{{.+}} <col:24, col:31> col:31 struct TestTemplateDefaultNonType
462460

463461
// CHECK: ClassTemplateDecl 0x{{.+}} <{{.+}}:{{.*}}:3, col:68> col:68 TestTemplateTemplateDefaultType
@@ -661,9 +659,7 @@ namespace TestNonTypeTemplateParmDecl {
661659
// CHECK-NEXT: FunctionTemplateDecl
662660
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 0 I
663661
// CHECK-NEXT: TemplateArgument expr
664-
// CHECK-NEXT: ConstantExpr{{.*}} 'int'
665-
// CHECK-NEXT: value: Int 1
666-
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
662+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1
667663
// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' depth 0 index 1 ... J
668664

669665
namespace TestTemplateTemplateParmDecl {

clang/test/CXX/expr/expr.const/p3-0x.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ void NonConstF() {
1010
case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}}
1111
break;
1212
}
13+
NonConstT<> V; // expected-note {{while checking a default template argument used here}}
1314
return;
1415
}
1516

clang/test/Index/Core/index-source.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ template<typename T = Cls,
405405
// CHECK: [[@LINE-1]]:23 | class/C++ | Cls | c:@S@Cls | <no-cgname> | Ref,RelCont | rel: 1
406406
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
407407
int x = Record::C,
408-
// CHECK: [[@LINE-1]]:26 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,Read,RelCont | rel: 1
408+
// CHECK: [[@LINE-1]]:26 | static-property/C++ | C | c:@S@Record@C | __ZN6Record1CE | Ref,RelCont | rel: 1
409409
// CHECK-NEXT: RelCont | TemplateDefaultValues | c:@ST>3#T#NI#t>1#T@TemplateDefaultValues
410410
// CHECK: [[@LINE-3]]:18 | struct/C++ | Record | c:@S@Record | <no-cgname> | Ref,RelCont | rel: 1
411411
template <typename> class Collection = ns2::ACollectionDecl>

clang/test/SemaCXX/GH62596.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
3+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
4+
5+
struct foo {
6+
static constexpr bool bar() {
7+
return true;
8+
}
9+
10+
template<bool B = bar()>
11+
static constexpr bool baz() {
12+
return B;
13+
}
14+
};
15+
static_assert(foo::baz(), "");
16+
17+
// expected-no-diagnostics

clang/test/SemaCXX/cxx2a-consteval-default-params.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,16 @@ namespace ShouldNotCrash {
7979
};
8080
void f(A a = A()) { }
8181
}
82+
83+
namespace GH62224 {
84+
consteval int fwd();
85+
template <int i = fwd()>
86+
struct C {
87+
consteval C(int = fwd()) { }
88+
consteval int get() { return i; }
89+
};
90+
91+
consteval int fwd() { return 42; }
92+
C<> Val; // No error since fwd is defined already.
93+
static_assert(Val.get() == 42);
94+
}

clang/test/SemaTemplate/deduction-guide.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,7 @@ F s(0);
224224
// CHECK: |-NonTypeTemplateParmDecl {{.*}} 'char' depth 0 index 0
225225
// CHECK: `-TemplateArgument expr
226226
// CHECK: | |-inherited from NonTypeTemplateParm {{.*}} '' 'char'
227-
// CHECK: | `-ConstantExpr {{.*}} 'char'
228-
// CHECK: | |-value: Int 120
229-
// CHECK: | `-CharacterLiteral {{.*}} 'char' 120
227+
// CHECK: | `-CharacterLiteral {{.*}} 'char' 120
230228
// CHECK: |-TemplateTypeParmDecl {{.*}} typename depth 0 index 1 U
231229
// CHECK: |-ParenExpr {{.*}} 'bool'
232230
// CHECK: | `-CXXBoolLiteralExpr {{.*}} 'bool' false

clang/test/SemaTemplate/temp_arg_nontype.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ namespace EntityReferenced {
204204
}
205205

206206
namespace PR6964 {
207-
template <typename ,int, int = 9223372036854775807L > // expected-warning 2{{non-type template argument value '9223372036854775807' truncated to '-1' for template parameter of type 'int'}} \
208-
// expected-note 2{{template parameter is declared here}}
207+
template <typename ,int, int = 9223372036854775807L > // expected-warning {{non-type template argument value '9223372036854775807' truncated to '-1' for template parameter of type 'int'}} \
208+
// expected-note {{template parameter is declared here}}
209209
struct as_nview { };
210210

211211
template <typename Sequence, int I0>

clang/unittests/AST/ASTImporterTest.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -1156,8 +1156,6 @@ TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
11561156
NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
11571157
ASSERT_TRUE(To->hasDefaultArgument());
11581158
Stmt *ToArg = To->getDefaultArgument();
1159-
ASSERT_TRUE(isa<ConstantExpr>(ToArg));
1160-
ToArg = *ToArg->child_begin();
11611159
ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
11621160
ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
11631161
}

0 commit comments

Comments
 (0)