Skip to content

Commit 505956e

Browse files
authored
[Clang] Use the templated declaration for DiagnoseUseOfDecl (#161900)
We missed the check of diagnose_if attributes for the constructor templates, because we used the template declaration, rather than its templated one. Also, we can avoid the duplicate constraint checking because it's already performed in overload resolution. There are some diagnostic regressions, all of which are warnings for uses of lambdas in C++03 mode, which I believe we should still diagnose. Fixes #160776
1 parent a741479 commit 505956e

File tree

5 files changed

+55
-11
lines changed

5 files changed

+55
-11
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,7 @@ Bug Fixes to AST Handling
452452

453453
Miscellaneous Bug Fixes
454454
^^^^^^^^^^^^^^^^^^^^^^^
455+
- Fixed missing diagnostics of ``diagnose_if`` on templates involved in initialization. (#GH160776)
455456

456457
Miscellaneous Clang Crashes Fixed
457458
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaInit.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7539,7 +7539,7 @@ PerformConstructorInitialization(Sema &S,
75397539

75407540
// Only check access if all of that succeeded.
75417541
S.CheckConstructorAccess(Loc, Constructor, Step.Function.FoundDecl, Entity);
7542-
if (S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc))
7542+
if (S.DiagnoseUseOfOverloadedDecl(Constructor, Loc))
75437543
return ExprError();
75447544

75457545
if (const ArrayType *AT = S.Context.getAsArrayType(Entity.getType()))
@@ -8092,7 +8092,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
80928092

80938093
S.CheckConstructorAccess(Kind.getLocation(), Constructor, FoundFn,
80948094
Entity);
8095-
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
8095+
if (S.DiagnoseUseOfOverloadedDecl(Constructor, Kind.getLocation()))
80968096
return ExprError();
80978097

80988098
CastKind = CK_ConstructorConversion;
@@ -8102,7 +8102,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
81028102
CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
81038103
S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), nullptr,
81048104
FoundFn);
8105-
if (S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()))
8105+
if (S.DiagnoseUseOfOverloadedDecl(Conversion, Kind.getLocation()))
81068106
return ExprError();
81078107

81088108
CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion,

clang/test/Parser/cxx0x-lambda-expressions.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++03 -Wno-c99-designator %s -Wno-c++11-extensions
1+
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++03 -Wno-c99-designator %s -Wno-c++11-extensions -Wno-local-type-template-args
22
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx14ext,cxx17ext,cxx20ext,cxx23ext -std=c++11 -Wno-c99-designator %s
33
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx17ext,cxx20ext,cxx23ext -std=c++14 -Wno-c99-designator %s
44
// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify=expected,cxx20ext,cxx23ext -std=c++17 -Wno-c99-designator %s

clang/test/SemaCXX/diagnose_if.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14
2+
// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++20 -verify=expected,cxx20
23
// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++14 -fexperimental-new-constant-interpreter
4+
// RUN: %clang_cc1 %s -verify -fno-builtin -std=c++20 -verify=expected,cxx20 -fexperimental-new-constant-interpreter
35

46
#define _diagnose_if(...) __attribute__((diagnose_if(__VA_ARGS__)))
57

@@ -665,3 +667,28 @@ void run() {
665667
switch (constexpr Foo i = 2) { default: break; } // expected-error{{oh no}}
666668
}
667669
}
670+
671+
namespace GH160776 {
672+
673+
struct ConstructorTemplate {
674+
template <class T>
675+
explicit ConstructorTemplate(T x)
676+
_diagnose_if(sizeof(T) == sizeof(char), "oh no", "error") {} // expected-note {{diagnose_if}}
677+
678+
template <class T>
679+
#if __cplusplus >= 202002L
680+
requires (sizeof(T) == 1) // cxx20-note {{evaluated to false}}
681+
#endif
682+
operator T() _diagnose_if(sizeof(T) == sizeof(char), "oh no", "error") { // expected-note {{diagnose_if}} \
683+
// cxx20-note {{constraints not satisfied}}
684+
return T{};
685+
}
686+
};
687+
688+
void run() {
689+
ConstructorTemplate x('1'); // expected-error {{oh no}}
690+
char y = x; // expected-error {{oh no}}
691+
int z = x; // cxx20-error {{no viable conversion}}
692+
}
693+
694+
}

clang/test/SemaCXX/lambda-expressions.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ namespace PR12031 {
149149
void f(int i, X x);
150150
void g() {
151151
const int v = 10;
152-
f(v, [](){});
152+
f(v, [](){}); // cxx03-warning {{template argument uses local type}} \
153+
// cxx03-note {{while substituting}}
153154
}
154155
}
155156

@@ -572,26 +573,37 @@ namespace PR27994 {
572573
struct A { template <class T> A(T); };
573574

574575
template <class T>
575-
struct B {
576+
struct B { // #PR27994_B
576577
int x;
577-
A a = [&] { int y = x; };
578-
A b = [&] { [&] { [&] { int y = x; }; }; };
579-
A d = [&](auto param) { int y = x; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}}
580-
A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx03-cxx11-error 2 {{'auto' not allowed in lambda parameter}}
578+
A a = [&] { int y = x; }; // cxx03-warning {{template argument uses unnamed type}} \
579+
// cxx03-note {{while substituting}} cxx03-note {{unnamed type used}}
580+
A b = [&] { [&] { [&] { int y = x; }; }; }; // cxx03-warning {{template argument uses unnamed type}} \
581+
// cxx03-note {{while substituting}} cxx03-note {{unnamed type used}}
582+
A d = [&](auto param) { int y = x; }; // cxx03-cxx11-error {{'auto' not allowed in lambda parameter}} \
583+
// cxx03-warning {{template argument uses unnamed type}} \
584+
// cxx03-note {{while substituting}} cxx03-note {{unnamed type used}}
585+
A e = [&](auto param) { [&] { [&](auto param2) { int y = x; }; }; }; // cxx03-cxx11-error 2 {{'auto' not allowed in lambda parameter}} \
586+
// cxx03-warning {{template argument uses unnamed type}} \
587+
// cxx03-note {{while substituting}} cxx03-note {{unnamed type used}}
581588
};
582589

583590
B<int> b;
591+
// cxx03-note@#PR27994_B 4{{in instantiation of default member initializer}}
592+
// cxx03-note@-2 4{{in evaluation of exception}}
584593

585594
template <class T> struct C {
586595
struct D {
596+
// cxx03-note@-1 {{in instantiation of default member initializer}}
587597
int x;
588-
A f = [&] { int y = x; };
598+
A f = [&] { int y = x; }; // cxx03-warning {{template argument uses unnamed type}} \
599+
// cxx03-note {{while substituting}} cxx03-note {{unnamed type used}}
589600
};
590601
};
591602

592603
int func() {
593604
C<int> a;
594605
decltype(a)::D b;
606+
// cxx03-note@-1 {{in evaluation of exception}}
595607
}
596608
}
597609

@@ -606,8 +618,12 @@ struct S1 {
606618

607619
void foo1() {
608620
auto s0 = S1([name=]() {}); // expected-error {{expected expression}}
621+
// cxx03-warning@-1 {{template argument uses local type}} \
622+
// cxx03-note@-1 {{while substituting deduced template arguments}}
609623
auto s1 = S1([name=name]() {}); // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}}
610624
// cxx03-cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}}
625+
// cxx03-warning@-2 {{template argument uses local type}} \
626+
// cxx03-note@-2 {{while substituting deduced template arguments}}
611627
}
612628
}
613629

0 commit comments

Comments
 (0)