diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h --- a/clang/include/clang/AST/DependenceFlags.h +++ b/clang/include/clang/AST/DependenceFlags.h @@ -64,6 +64,23 @@ }; using TypeDependence = TypeDependenceScope::TypeDependence; +struct TemplateArgumentDependenceScope { + enum TemplateArgumentDependence : uint8_t { + UnexpandedPack = 1, + Instantiation = 2, + Dependent = 4, + + Error = 8, + + DependentInstantiation = Dependent | Instantiation, + None = 0, + All = 15, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Error) + }; +}; +using TemplateArgumentDependence = + TemplateArgumentDependenceScope ::TemplateArgumentDependence; + #define LLVM_COMMON_DEPENDENCE(NAME) \ struct NAME##Scope { \ enum NAME : uint8_t { \ @@ -82,7 +99,6 @@ LLVM_COMMON_DEPENDENCE(NestedNameSpecifierDependence) LLVM_COMMON_DEPENDENCE(TemplateNameDependence) -LLVM_COMMON_DEPENDENCE(TemplateArgumentDependence) #undef LLVM_COMMON_DEPENDENCE // A combined space of all dependence concepts for all node types. @@ -137,8 +153,9 @@ Dependence(TemplateArgumentDependence D) : V(translate(D, TADependence::UnexpandedPack, UnexpandedPack) | - translate(D, TADependence::Instantiation, Instantiation) | - translate(D, TADependence::Dependent, Dependent)) {} + translate(D, TADependence::Instantiation, Instantiation) | + translate(D, TADependence::Dependent, Dependent) | + translate(D, TADependence::Error, Error)) {} Dependence(TemplateNameDependence D) : V(translate(D, TNDependence::UnexpandedPack, UnexpandedPack) | @@ -170,7 +187,8 @@ TemplateArgumentDependence templateArgument() const { return translate(V, UnexpandedPack, TADependence::UnexpandedPack) | translate(V, Instantiation, TADependence::Instantiation) | - translate(V, Dependent, TADependence::Dependent); + translate(V, Dependent, TADependence::Dependent) | + translate(V, Error, TADependence::Error); } TemplateNameDependence templateName() const { diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3591,7 +3591,7 @@ auto *TemplateArgs = reinterpret_cast(this + 1); for (const TemplateArgument &Arg : Args) { - // Update instantiation-dependent and variably-modified bits. + // Update instantiation-dependent, variably-modified, and error bits. // If the canonical type exists and is non-dependent, the template // specialization type can be non-dependent even if one of the type // arguments is. Given: diff --git a/clang/test/SemaCXX/invalid-template-base-specifier.cpp b/clang/test/SemaCXX/invalid-template-base-specifier.cpp --- a/clang/test/SemaCXX/invalid-template-base-specifier.cpp +++ b/clang/test/SemaCXX/invalid-template-base-specifier.cpp @@ -1,7 +1,6 @@ // RUN: %clang_cc1 -frecovery-ast -verify %s -bool Foo(int *); // expected-note {{candidate function not viable}} \ - // expected-note {{candidate function not viable}} +bool Foo(int *); // expected-note 3{{candidate function not viable}} template struct Crash : decltype(Foo(T())) { // expected-error {{no matching function for call to 'Foo'}} @@ -18,3 +17,12 @@ }; void test2() { Crash2(); } // expected-note {{in instantiation of template class 'Crash2' requested here}} + +template +class Base {}; +template +struct Crash3 : Base { // expected-error {{no matching function for call to 'Foo'}} + Crash3(){}; +}; + +void test3() { Crash3(); } // expected-note {{in instantiation of template class}}