Author: tcottin Date: 2026-01-10T19:56:02+01:00 New Revision: 696946f897db90d07dbfb981ad8e75fd872a1d35
URL: https://github.com/llvm/llvm-project/commit/696946f897db90d07dbfb981ad8e75fd872a1d35 DIFF: https://github.com/llvm/llvm-project/commit/696946f897db90d07dbfb981ad8e75fd872a1d35.diff LOG: [clang] Add a valid begin source location for abbreviated function templates (#174723) The begin source location for function templates is determined by the source location of the template keyword. Pure abbreviated function templates do not have the template keyword. This results in an invalid begin source location for abbreviated function templates. Without a valid begin source location, comments cannot be attached to the function template which leads to the bug described in clangd/clangd#2565. This patch introduces new begin locations for abbreviated function templates (begin of the templated function) and generic lambdas (begin of the introducer `[...]`) when creating the template parameter lists in Sema. Added: Modified: clang-tools-extra/clangd/unittests/HoverTests.cpp clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaLambda.cpp clang/test/AST/ast-dump-record-definition-data-json.cpp clang/test/AST/ast-dump-templates.cpp clang/test/CXX/temp/temp.pre/p6.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index eb858ff616e90..7bff20e6f5635 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -57,6 +57,137 @@ TEST(Hover, Structured) { HI.Type = "void ()"; HI.Parameters.emplace(); }}, + {R"cpp( + // Best foo ever. + void [[fo^o]](auto x) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "void foo(auto x)"; + HI.ReturnType = "void"; + HI.Type = "void (auto)"; + HI.TemplateParameters = { + {{"class"}, std::string("x:auto"), std::nullopt}, + }; + HI.Parameters = { + {{"auto"}, std::string("x"), std::nullopt}, + }; + }}, + {R"cpp( + // Best foo ever. + template <class T> + void [[fo^o]](T x) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "template <class T> void foo(T x)"; + HI.ReturnType = "void"; + HI.Type = "void (T)"; + HI.TemplateParameters = { + {{"class"}, std::string("T"), std::nullopt}, + }; + HI.Parameters = { + {{"T"}, std::string("x"), std::nullopt}, + }; + }}, + {R"cpp( + // Best foo ever. + template <class T> + void [[fo^o]](T x, auto y) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "template <class T> void foo(T x, auto y)"; + HI.ReturnType = "void"; + HI.Type = "void (T, auto)"; + HI.TemplateParameters = { + {{"class"}, std::string("T"), std::nullopt}, + {{"class"}, std::string("y:auto"), std::nullopt}, + }; + HI.Parameters = { + {{"T"}, std::string("x"), std::nullopt}, + {{"auto"}, std::string("y"), std::nullopt}, + }; + }}, + {R"cpp( + template<typename T1, typename T2> + concept C = requires () { true; }; + + // Best foo ever. + template<C<int> T> + void [[fo^o]](T x) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "template <C<int> T> void foo(T x)"; + HI.ReturnType = "void"; + HI.Type = "void (T)"; + HI.TemplateParameters = { + {{"class"}, std::string("T"), std::nullopt}, + }; + HI.Parameters = { + {{"T"}, std::string("x"), std::nullopt}, + }; + }}, + {R"cpp( + template<typename T1, typename T2> + concept C = requires () { true; }; + + // Best foo ever. + void [[fo^o]](C<int> auto x) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "void foo(C<int> auto x)"; + HI.ReturnType = "void"; + HI.Type = "void (C<int> auto)"; + HI.TemplateParameters = { + {{"class"}, std::string("x:auto"), std::nullopt}, + }; + HI.Parameters = { + {{"C<int> auto"}, std::string("x"), std::nullopt}, + }; + }}, + {R"cpp( + template<typename T1, typename T2> + concept C = requires () { true; }; + + // Best foo ever. + template<C<int> T> + void [[fo^o]](T x, C<int> auto y) {} + )cpp", + [](HoverInfo &HI) { + HI.NamespaceScope = ""; + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Documentation = "Best foo ever."; + HI.Definition = "template <C<int> T> void foo(T x, C<int> auto y)"; + HI.ReturnType = "void"; + HI.Type = "void (T, C<int> auto)"; + HI.TemplateParameters = { + {{"class"}, std::string("T"), std::nullopt}, + {{"class"}, std::string("y:auto"), std::nullopt}, + }; + HI.Parameters = { + {{"T"}, std::string("x"), std::nullopt}, + {{"C<int> auto"}, std::string("y"), std::nullopt}, + }; + }}, // Inside namespace {R"cpp( namespace ns1 { namespace ns2 { diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c4384fcea5504..f62298938af93 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -140,6 +140,12 @@ ABI Changes in This Version --------------------------- - Fix AArch64 argument passing for C++ empty classes with large explicitly specified alignment. +AST Potentially Breaking Changes +-------------------------------- +- Abbreviated function templates and generic lambdas now have a valid begin source location. + The begin source location of abbreviated function templates is the begin source location of the templated function. + The begin source location of generic lambdas is the begin source location of the lambda introducer ``[...]``. + AST Dumping Potentially Breaking Changes ---------------------------------------- - How nested name specifiers are dumped and printed changes, keeping track of clang AST changes. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6b5a80f7ea3f9..51b3f80590d1c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -19635,10 +19635,10 @@ void Sema::ActOnFinishFunctionDeclarationDeclarator(Declarator &Declarator) { ExplicitParams->getRAngleLoc(), ExplicitParams->getRequiresClause())); } else { - Declarator.setInventedTemplateParameterList( - TemplateParameterList::Create( - Context, SourceLocation(), SourceLocation(), FSI.TemplateParams, - SourceLocation(), /*RequiresClause=*/nullptr)); + Declarator.setInventedTemplateParameterList(TemplateParameterList::Create( + Context, Declarator.getBeginLoc(), SourceLocation(), + FSI.TemplateParams, Declarator.getEndLoc(), + /*RequiresClause=*/nullptr)); } } InventedParameterInfos.pop_back(); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 53f2612a46bf4..c864a47e022bd 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -235,10 +235,10 @@ getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { if (!LSI->GLTemplateParameterList && !LSI->TemplateParams.empty()) { LSI->GLTemplateParameterList = TemplateParameterList::Create( SemaRef.Context, - /*Template kw loc*/ SourceLocation(), + /*Begin loc of the lambda expression*/ LSI->IntroducerRange.getBegin(), /*L angle loc*/ LSI->ExplicitTemplateParamsRange.getBegin(), LSI->TemplateParams, - /*R angle loc*/LSI->ExplicitTemplateParamsRange.getEnd(), + /*R angle loc*/ LSI->ExplicitTemplateParamsRange.getEnd(), LSI->RequiresClause.get()); } return LSI->GLTemplateParameterList; diff --git a/clang/test/AST/ast-dump-record-definition-data-json.cpp b/clang/test/AST/ast-dump-record-definition-data-json.cpp index e35bec78c6847..d8ff6e980fb94 100644 --- a/clang/test/AST/ast-dump-record-definition-data-json.cpp +++ b/clang/test/AST/ast-dump-record-definition-data-json.cpp @@ -408,7 +408,11 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { -// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 190, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, // CHECK-NEXT: "end": { // CHECK-NEXT: "offset": 199, // CHECK-NEXT: "col": 35, @@ -523,7 +527,11 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { -// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 190, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, // CHECK-NEXT: "end": { // CHECK-NEXT: "offset": 199, // CHECK-NEXT: "col": 35, @@ -598,7 +606,11 @@ struct DoesNotAllowConstDefaultInit { // CHECK-NEXT: "tokLen": 1 // CHECK-NEXT: }, // CHECK-NEXT: "range": { -// CHECK-NEXT: "begin": {}, +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "offset": 190, +// CHECK-NEXT: "col": 26, +// CHECK-NEXT: "tokLen": 1 +// CHECK-NEXT: }, // CHECK-NEXT: "end": { // CHECK-NEXT: "offset": 199, // CHECK-NEXT: "col": 35, diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp index f0357c5a8aa32..8cf9b6a29e332 100644 --- a/clang/test/AST/ast-dump-templates.cpp +++ b/clang/test/AST/ast-dump-templates.cpp @@ -266,6 +266,17 @@ namespace AliasDependentTemplateSpecializationType { // DUMP-NEXT: `-BuiltinType {{.*}} 'int' } // namespace +namespace TestAbbreviatedTemplateDecls { + // DUMP-LABEL: NamespaceDecl {{.*}} TestAbbreviatedTemplateDecls{{$}} + void abbreviated(auto); + template<class T> + void mixed(T, auto); + +// DUMP: FunctionTemplateDecl {{.*}} <line:[[@LINE-4]]:3, col:24> col:8 abbreviated +// DUMP: FunctionTemplateDecl {{.*}} <line:[[@LINE-4]]:3, line:[[@LINE-3]]:21> col:8 mixed + +} // namespace TestAbbreviatedTemplateDecls + // NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py @@ -9256,6 +9267,290 @@ namespace AliasDependentTemplateSpecializationType { // JSON-NEXT: ] // JSON-NEXT: } // JSON-NEXT: ] +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "NamespaceDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11557, +// JSON-NEXT: "line": 269, +// JSON-NEXT: "col": 11, +// JSON-NEXT: "tokLen": 28 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11547, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 9 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11906, +// JSON-NEXT: "line": 278, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "TestAbbreviatedTemplateDecls", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "FunctionTemplateDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11667, +// JSON-NEXT: "line": 271, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 11 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11662, +// JSON-NEXT: "col": 3, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11683, +// JSON-NEXT: "col": 24, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "abbreviated", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "TemplateTypeParmDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11683, +// JSON-NEXT: "col": 24, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11679, +// JSON-NEXT: "col": 20, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11683, +// JSON-NEXT: "col": 24, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "isImplicit": true, +// JSON-NEXT: "name": "auto:1", +// JSON-NEXT: "tagUsed": "class", +// JSON-NEXT: "depth": 0, +// JSON-NEXT: "index": 0 +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "FunctionDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11667, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 11 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11662, +// JSON-NEXT: "col": 3, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11683, +// JSON-NEXT: "col": 24, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "abbreviated", +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "void (auto)" +// JSON-NEXT: }, +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ParmVarDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11683, +// JSON-NEXT: "col": 24, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11679, +// JSON-NEXT: "col": 20, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11679, +// JSON-NEXT: "col": 20, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "auto" +// JSON-NEXT: } +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "FunctionTemplateDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11713, +// JSON-NEXT: "line": 273, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 5 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11688, +// JSON-NEXT: "line": 272, +// JSON-NEXT: "col": 3, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11726, +// JSON-NEXT: "line": 273, +// JSON-NEXT: "col": 21, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "mixed", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "TemplateTypeParmDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11703, +// JSON-NEXT: "line": 272, +// JSON-NEXT: "col": 18, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11697, +// JSON-NEXT: "col": 12, +// JSON-NEXT: "tokLen": 5 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11703, +// JSON-NEXT: "col": 18, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "isReferenced": true, +// JSON-NEXT: "name": "T", +// JSON-NEXT: "tagUsed": "class", +// JSON-NEXT: "depth": 0, +// JSON-NEXT: "index": 0 +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "TemplateTypeParmDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11726, +// JSON-NEXT: "line": 273, +// JSON-NEXT: "col": 21, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11722, +// JSON-NEXT: "col": 17, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11726, +// JSON-NEXT: "col": 21, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "isImplicit": true, +// JSON-NEXT: "name": "auto:2", +// JSON-NEXT: "tagUsed": "class", +// JSON-NEXT: "depth": 0, +// JSON-NEXT: "index": 1 +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "FunctionDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11713, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 5 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11708, +// JSON-NEXT: "col": 3, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11726, +// JSON-NEXT: "col": 21, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "mixed", +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "void (T, auto)" +// JSON-NEXT: }, +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ParmVarDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11720, +// JSON-NEXT: "col": 15, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11719, +// JSON-NEXT: "col": 14, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11719, +// JSON-NEXT: "col": 14, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "T" +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ParmVarDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 11726, +// JSON-NEXT: "col": 21, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 11722, +// JSON-NEXT: "col": 17, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 11722, +// JSON-NEXT: "col": 17, +// JSON-NEXT: "tokLen": 4 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "auto" +// JSON-NEXT: } +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: } +// JSON-NEXT: ] // JSON-NEXT: } // JSON-NEXT: ] // JSON-NEXT: } diff --git a/clang/test/CXX/temp/temp.pre/p6.cpp b/clang/test/CXX/temp/temp.pre/p6.cpp index 264972eb44eb3..13531483ae1e7 100644 --- a/clang/test/CXX/temp/temp.pre/p6.cpp +++ b/clang/test/CXX/temp/temp.pre/p6.cpp @@ -6,7 +6,7 @@ namespace GH46386 { // CHECK: error: templates must have C++ linkage // CHECK-NEXT: {{^}} void f(auto) {} - // CHECK-NEXT: {{^}} ^~~~~{{$}} + // CHECK-NEXT: {{^}} ^~~~~~~~~~~~{{$}} void f(auto) {} // expected-error {{templates must have C++ linkage}} void f(void) { // expected-note {{candidate function not viable: requires 0 arguments, but 1 was provided}} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
