hokein updated this revision to Diff 272963. hokein added a comment. per offline discussion: add error-bit to TemplateArgument which provide a more general fix for missing error-bit in the code path: "error type/expr" -> "teample argument" -> "template specialization typ".
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D82102/new/ https://reviews.llvm.org/D82102 Files: clang/include/clang/AST/DependenceFlags.h clang/lib/AST/Type.cpp clang/test/SemaCXX/invalid-template-base-specifier.cpp Index: clang/test/SemaCXX/invalid-template-base-specifier.cpp =================================================================== --- clang/test/SemaCXX/invalid-template-base-specifier.cpp +++ 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 <typename T> struct Crash : decltype(Foo(T())) { // expected-error {{no matching function for call to 'Foo'}} @@ -18,3 +17,12 @@ }; void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}} + +template <typename T> +class Base {}; +template <typename T> +struct Crash3 : Base<decltype(Foo(T()))> { // expected-error {{no matching function for call to 'Foo'}} + Crash3(){}; +}; + +void test3() { Crash3<int>(); } // expected-note {{in instantiation of template class}} Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -3591,7 +3591,7 @@ auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(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: Index: clang/include/clang/AST/DependenceFlags.h =================================================================== --- clang/include/clang/AST/DependenceFlags.h +++ 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 {
Index: clang/test/SemaCXX/invalid-template-base-specifier.cpp =================================================================== --- clang/test/SemaCXX/invalid-template-base-specifier.cpp +++ 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 <typename T> struct Crash : decltype(Foo(T())) { // expected-error {{no matching function for call to 'Foo'}} @@ -18,3 +17,12 @@ }; void test2() { Crash2<int>(); } // expected-note {{in instantiation of template class 'Crash2<int>' requested here}} + +template <typename T> +class Base {}; +template <typename T> +struct Crash3 : Base<decltype(Foo(T()))> { // expected-error {{no matching function for call to 'Foo'}} + Crash3(){}; +}; + +void test3() { Crash3<int>(); } // expected-note {{in instantiation of template class}} Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -3591,7 +3591,7 @@ auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(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: Index: clang/include/clang/AST/DependenceFlags.h =================================================================== --- clang/include/clang/AST/DependenceFlags.h +++ 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 {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits