Skip to content

Commit e9948a1

Browse files
committed
[Clang] prevent recovery call expression from proceeding with explicit attributes and undeclared templates
1 parent 2162723 commit e9948a1

File tree

5 files changed

+48
-4
lines changed

5 files changed

+48
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,8 @@ Bug Fixes to C++ Support
424424
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
425425
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
426426
- Fixed an assertion failure by adjusting integral to boolean vector conversions (#GH108326)
427+
- Fixed an assertion failure when invoking recovery call expressions with explicit attributes
428+
and undeclared templates. (#GH107047, #GH49093)
427429

428430
Bug Fixes to AST Handling
429431
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6753,7 +6753,9 @@ class Sema final : public SemaBase {
67536753
///
67546754
/// Return \c true if the error is unrecoverable, or \c false if the caller
67556755
/// should attempt to recover using these lookup results.
6756-
bool DiagnoseDependentMemberLookup(const LookupResult &R);
6756+
bool DiagnoseDependentMemberLookup(
6757+
const LookupResult &R,
6758+
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
67576759

67586760
/// Diagnose an empty lookup.
67596761
///

clang/lib/Sema/SemaExpr.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,15 @@ static void emitEmptyLookupTypoDiagnostic(
23852385
SemaRef.PDiag(NoteID));
23862386
}
23872387

2388-
bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) {
2388+
bool Sema::DiagnoseDependentMemberLookup(
2389+
const LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs) {
2390+
auto IsTemplated = [](NamedDecl *D) { return D->isTemplated(); };
2391+
if (ExplicitTemplateArgs && !llvm::all_of(R, IsTemplated)) {
2392+
Diag(R.getNameLoc(), diag::err_non_template_in_template_id)
2393+
<< R.getLookupName();
2394+
return true;
2395+
}
2396+
23892397
// During a default argument instantiation the CurContext points
23902398
// to a CXXMethodDecl; but we can't apply a this-> fixit inside a
23912399
// function parameter list, hence add an explicit check.
@@ -2487,7 +2495,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
24872495
R.resolveKind();
24882496
}
24892497

2490-
return DiagnoseDependentMemberLookup(R);
2498+
return DiagnoseDependentMemberLookup(R, ExplicitTemplateArgs);
24912499
}
24922500

24932501
R.clear();

clang/lib/Sema/SemaOverload.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13860,7 +13860,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
1386013860
// enclosing class.
1386113861
// FIXME: We should also explain why the candidates found by name lookup
1386213862
// were not viable.
13863-
if (SemaRef.DiagnoseDependentMemberLookup(R))
13863+
if (SemaRef.DiagnoseDependentMemberLookup(R, ExplicitTemplateArgs))
1386413864
return ExprError();
1386513865
} else {
1386613866
// We had viable candidates and couldn't recover; let the caller diagnose
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
2+
3+
namespace GH49093 {
4+
class B {
5+
public:
6+
static int a() { return 0; }
7+
decltype(a< 0 >(0)) test; // expected-error {{'a' does not name a template but is followed by template arguments}}
8+
};
9+
10+
struct C {
11+
static int a() { return 0; }
12+
decltype(a < 0 > (0)) test; // expected-error {{'a' does not name a template but is followed by template arguments}}
13+
};
14+
15+
void test_is_bool(bool t) {}
16+
void test_is_bool(int t) {}
17+
18+
int main() {
19+
B b;
20+
test_is_bool(b.test);
21+
22+
C c;
23+
test_is_bool(c.test);
24+
}
25+
}
26+
27+
namespace GH107047 {
28+
struct A {
29+
static constexpr auto test() { return 1; }
30+
static constexpr int s = test< 1 >(); // expected-error {{'test' does not name a template but is followed by template arguments}}
31+
};
32+
}

0 commit comments

Comments
 (0)