Author: Richard Smith Date: 2019-12-10T17:55:30-08:00 New Revision: 2e48be09b02e6d01b85d31704d768b6d0c751751
URL: https://github.com/llvm/llvm-project/commit/2e48be09b02e6d01b85d31704d768b6d0c751751 DIFF: https://github.com/llvm/llvm-project/commit/2e48be09b02e6d01b85d31704d768b6d0c751751.diff LOG: Fix mishandling of invalid-but-non-empty nested name specifiers in name classification. We were accidentally treating invalid scope specs as being empty, resulting in our trying to form an ADL-only call with a qualified callee, which tripped up an assert later on. Added: Modified: clang/lib/Sema/SemaDecl.cpp clang/test/Parser/cxx-template-decl.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 76bf7b034518..1cf87e45a299 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -867,6 +867,9 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); LookupParsedName(Result, S, &SS, !CurMethod); + if (SS.isInvalid()) + return NameClassification::Error(); + // For unqualified lookup in a class template in MSVC mode, look into // dependent base classes where the primary class template is known. if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) { @@ -879,7 +882,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, // synthesized instance variables), if we're in an Objective-C method. // FIXME: This lookup really, really needs to be folded in to the normal // unqualified lookup mechanism. - if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + if (SS.isEmpty() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { DeclResult Ivar = LookupIvarInObjCMethod(Result, S, Name); if (Ivar.isInvalid()) return NameClassification::Error(); @@ -899,7 +902,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, case LookupResult::NotFound: // If an unqualified-id is followed by a '(', then we have a function // call. - if (!SS.isSet() && NextToken.is(tok::l_paren)) { + if (SS.isEmpty() && NextToken.is(tok::l_paren)) { // In C++, this is an ADL-only call. // FIXME: Reference? if (getLangOpts().CPlusPlus) @@ -921,7 +924,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, return NameClassification::NonType(D); } - if (getLangOpts().CPlusPlus2a && !SS.isSet() && NextToken.is(tok::less)) { + if (getLangOpts().CPlusPlus2a && SS.isEmpty() && NextToken.is(tok::less)) { // In C++20 onwards, this could be an ADL-only call to a function // template, and we're required to assume that this is a template name. // @@ -1063,7 +1066,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, hasAnyAcceptableTemplateNames( Result, /*AllowFunctionTemplates=*/true, /*AllowDependent=*/false, - /*AllowNonTemplateFunctions*/ !SS.isSet() && + /*AllowNonTemplateFunctions*/ SS.isEmpty() && getLangOpts().CPlusPlus2a))) { // C++ [temp.names]p3: // After name lookup (3.4) finds that a name is a template-name or that @@ -1092,7 +1095,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); IsVarTemplate = isa<VarTemplateDecl>(TD); - if (SS.isSet() && !SS.isInvalid()) + if (SS.isNotEmpty()) Template = Context.getQualifiedTemplateName(SS.getScopeRep(), /*TemplateKeyword=*/false, TD); diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 07316782a830..cb8a93fdecb1 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -261,3 +261,11 @@ namespace PR42071 { template<int Q::N> struct C; // expected-error {{parameter declarator cannot be qualified}} template<int f(int a = 0)> struct D; // expected-error {{default arguments can only be specified for parameters in a function declaration}} } + +namespace AnnotateAfterInvalidTemplateId { + template<int I, int J> struct A { }; + template<int J> struct A<0, J> { }; // expected-note {{J = 0}} + template<int I> struct A<I, 0> { }; // expected-note {{I = 0}} + + void f() { A<0, 0>::f(); } // expected-error {{ambiguous partial specializations}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits