aboutsummaryrefslogtreecommitdiff
path: root/clang/test
diff options
context:
space:
mode:
authorCorentin Jabot <corentinjabot@gmail.com>2023-03-23 14:26:45 +0100
committerCorentin Jabot <corentinjabot@gmail.com>2023-03-30 16:30:23 +0200
commitabf4a8cb15d4faf04ee0da14e37d7349d3bde9a1 (patch)
tree0e153899e0b010eeac281facbca646a8c54a4d6f /clang/test
parent5114843983b6d3ec866877308073d3821759a747 (diff)
downloadllvm-abf4a8cb15d4faf04ee0da14e37d7349d3bde9a1.zip
llvm-abf4a8cb15d4faf04ee0da14e37d7349d3bde9a1.tar.gz
llvm-abf4a8cb15d4faf04ee0da14e37d7349d3bde9a1.tar.bz2
[Clang] Improve diagnostics when using a concept as template argument
When using the name of a template variable or concept in places where an expression was expected, Clang would drop the cxxscope token preceeding it, if any. This leads to subpar diagnostics - complaining about the identifier being undeclared as clang would not know to look into a non-global scope. We make sure the scope is preserved. When encountering `ns::Concept foo x;`, Clang would also fail to provide the same quality as it does at global scope. Reviewed By: aaron.ballman, erichkeane Differential Revision: https://reviews.llvm.org/D146719
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Parser/cxx-template-template-recovery.cpp44
1 files changed, 44 insertions, 0 deletions
diff --git a/clang/test/Parser/cxx-template-template-recovery.cpp b/clang/test/Parser/cxx-template-template-recovery.cpp
new file mode 100644
index 0000000..1230c86
--- /dev/null
+++ b/clang/test/Parser/cxx-template-template-recovery.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only %s
+
+namespace a {
+ template <typename T>
+ concept C1 = true; // #C1
+
+ template <typename T>
+ auto V1 = true; // #V1
+
+ namespace b {
+ template <typename T>
+ concept C2 = true; // #C2
+ template <typename T>
+ auto V2 = true; // #V2
+ }
+}
+
+template <typename T>
+concept C3 = true; // #C3
+template <typename T>
+auto V3 = true; // #V3
+template <template <typename T> typename C>
+constexpr bool test = true;
+
+static_assert(test<a::C1>); // expected-error {{too few template arguments for concept 'C1'}} \
+ // expected-note@#C1 {{here}}
+static_assert(test<a::b::C2>); // expected-error {{too few template arguments for concept 'C2'}} \
+ // expected-note@#C2 {{here}}
+static_assert(test<C3>); // expected-error {{too few template arguments for concept 'C3'}} \
+ // expected-note@#C3 {{here}}
+
+static_assert(test<a::V1>); // expected-error {{use of variable template 'V1' requires template arguments}} \
+ // expected-note@#V1 {{here}}
+static_assert(test<a::b::V2>); // expected-error {{use of variable template 'V2' requires template arguments}} \
+ // expected-note@#V2 {{here}}
+static_assert(test<V3>); // expected-error {{use of variable template 'V3' requires template arguments}} \
+ // expected-note@#V3 {{here}}
+
+
+void f() {
+ C3 t1 = 0; // expected-error {{expected 'auto' or 'decltype(auto)' after concept name}}
+ a::C1 t2 = 0; // expected-error {{expected 'auto' or 'decltype(auto)' after concept name}}
+ a::b::C2 t3 = 0; // expected-error {{expected 'auto' or 'decltype(auto)' after concept name}}
+}