to limit non-defined/non-member functions as well. Additionally, we now diagnose
requires on lambdas when not allowed, which we previously missed.
(`#61748 <https://github.com/llvm/llvm-project/issues/61748>`_)
+- Fix confusing diagnostic for incorrect use of qualified concepts names.
+
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
undefined symbols in the created module to be a linker error. To prevent this,
pass ``-Wl,--undefined`` if compiling directly, or ``-Xoffload-linker
--undefined`` if using an offloading language.
-- The deprecated ``-mcode-object-v3`` and ``-mno-code-object-v3`` command-line
+- The deprecated ``-mcode-object-v3`` and ``-mno-code-object-v3`` command-line
options have been removed.
X86 Support
continue;
}
- if (TemplateId && TemplateId->Kind == TNK_Concept_template &&
- GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype)) {
+ if (TemplateId && TemplateId->Kind == TNK_Concept_template) {
DS.getTypeSpecScope() = SS;
- // This is a qualified placeholder-specifier, e.g., ::C<int> auto ...
- // Consume the scope annotation and continue to consume the template-id
- // as a placeholder-specifier.
+ // This is probably a qualified placeholder-specifier, e.g., ::C<int>
+ // auto ... Consume the scope annotation and continue to consume the
+ // template-id as a placeholder-specifier. Let the next iteration
+ // diagnose a missing auto.
ConsumeAnnotationToken();
continue;
}
return ANK_TemplateName;
}
[[fallthrough]];
+ case Sema::NC_Concept:
case Sema::NC_VarTemplate:
case Sema::NC_FunctionTemplate:
case Sema::NC_UndeclaredTemplate: {
- // We have a type, variable or function template followed by '<'.
- ConsumeToken();
- UnqualifiedId Id;
- Id.setIdentifier(Name, NameLoc);
- if (AnnotateTemplateIdToken(
- TemplateTy::make(Classification.getTemplateName()),
- Classification.getTemplateNameKind(), SS, SourceLocation(), Id))
- return ANK_Error;
- return ANK_Success;
- }
- case Sema::NC_Concept: {
- UnqualifiedId Id;
- Id.setIdentifier(Name, NameLoc);
+ bool IsConceptName = Classification.getKind() == Sema::NC_Concept;
+ // We have a template name followed by '<'. Consume the identifier token so
+ // we reach the '<' and annotate it.
if (Next.is(tok::less))
- // We have a concept name followed by '<'. Consume the identifier token so
- // we reach the '<' and annotate it.
ConsumeToken();
+ UnqualifiedId Id;
+ Id.setIdentifier(Name, NameLoc);
if (AnnotateTemplateIdToken(
TemplateTy::make(Classification.getTemplateName()),
Classification.getTemplateNameKind(), SS, SourceLocation(), Id,
- /*AllowTypeAnnotation=*/false, /*TypeConstraint=*/true))
+ /*AllowTypeAnnotation=*/!IsConceptName,
+ /*TypeConstraint=*/IsConceptName))
return ANK_Error;
+ if (SS.isNotEmpty())
+ AnnotateScopeToken(SS, !WasScopeAnnotation);
return ANK_Success;
}
}
--- /dev/null
+// 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}}
+}