llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Yanzuo Liu (zwuis) <details> <summary>Changes</summary> #<!-- -->134522 triggers compilation error with libstdc++. See #<!-- -->139067 or <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120190>. This reverts commit 91f1830cb69cab96201adba6378d64095e251f95. --- Full diff: https://github.com/llvm/llvm-project/pull/139539.diff 10 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (-2) - (modified) clang/include/clang/AST/ASTContext.h (-5) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3-11) - (modified) clang/lib/AST/ASTContext.cpp (-49) - (modified) clang/lib/Sema/SemaExpr.cpp (+1-2) - (modified) clang/lib/Sema/SemaTemplate.cpp (+1-50) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+80-3) - (modified) clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp (-20) - (modified) clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp (-17) - (modified) clang/test/SemaTemplate/instantiate-var-template.cpp (-11) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e362ec595a3bb..d0645f3cbc6a5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -684,8 +684,6 @@ Bug Fixes to C++ Support - Fixed an assertion when trying to constant-fold various builtins when the argument referred to a reference to an incomplete type. (#GH129397) - Fixed a crash when a cast involved a parenthesized aggregate initialization in dependent context. (#GH72880) -- No longer crashes when instantiating invalid variable template specialization - whose type depends on itself. (#GH51347), (#GH55872) - Improved parser recovery of invalid requirement expressions. In turn, this fixes crashes from follow-on processing of the invalid requirement. (#GH138820) - Fixed the handling of pack indexing types in the constraints of a member function redeclaration. (#GH138255) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 1fdc488a76507..555afc315b704 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2971,11 +2971,6 @@ class ASTContext : public RefCountedBase<ASTContext> { TemplateTemplateParmDecl *insertCanonicalTemplateTemplateParmDeclInternal( TemplateTemplateParmDecl *CanonTTP) const; - /// Determine whether the given template arguments \p Arg1 and \p Arg2 are - /// equivalent. - bool isSameTemplateArgument(const TemplateArgument &Arg1, - const TemplateArgument &Arg2) const; - /// Type Query functions. If the type is an instance of the specified class, /// return the Type pointer for the underlying maximally pretty type. This /// is a member of ASTContext because this may need to do some amount of diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ca47cf62324f3..4751acfbb0456 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2531,14 +2531,9 @@ def note_implicit_deduction_guide : Note<"implicit deduction guide declared as ' def warn_cxx98_compat_auto_type_specifier : Warning< "'auto' type specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def err_auto_variable_cannot_appear_in_own_initializer - : Error< - "%enum_select<ParsingInitFor>{%Var{variable}|" - "%VarTemplate{variable template}|" - "%VarTemplatePartialSpec{variable template partial specialization}|" - "%VarTemplateExplicitSpec{variable template explicit " - "specialization}}0 %1 " - "declared with deduced type %2 cannot appear in its own initializer">; +def err_auto_variable_cannot_appear_in_own_initializer : Error< + "variable %0 declared with deduced type %1 " + "cannot appear in its own initializer">; def err_binding_cannot_appear_in_own_initializer : Error< "binding %0 cannot appear in the initializer of its own " "decomposition declaration">; @@ -5312,9 +5307,6 @@ def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; -def err_var_template_spec_type_depends_on_self : Error< - "the type of variable template specialization %0 declared with deduced type " - "%1 depends on itself">; def warn_unqualified_call_to_std_cast_function : Warning< "unqualified call to '%0'">, InGroup<DiagGroup<"unqualified-std-cast-call">>; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c58cd2c93fb60..6b8685ae99256 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7666,55 +7666,6 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { llvm_unreachable("Unhandled template argument kind"); } -bool ASTContext::isSameTemplateArgument(const TemplateArgument &Arg1, - const TemplateArgument &Arg2) const { - if (Arg1.getKind() != Arg2.getKind()) - return false; - - switch (Arg1.getKind()) { - case TemplateArgument::Null: - llvm_unreachable("Comparing NULL template argument"); - - case TemplateArgument::Type: - return hasSameType(Arg1.getAsType(), Arg2.getAsType()); - - case TemplateArgument::Declaration: - return Arg1.getAsDecl()->getUnderlyingDecl()->getCanonicalDecl() == - Arg2.getAsDecl()->getUnderlyingDecl()->getCanonicalDecl(); - - case TemplateArgument::NullPtr: - return hasSameType(Arg1.getNullPtrType(), Arg2.getNullPtrType()); - - case TemplateArgument::Template: - case TemplateArgument::TemplateExpansion: - return getCanonicalTemplateName(Arg1.getAsTemplateOrTemplatePattern()) == - getCanonicalTemplateName(Arg2.getAsTemplateOrTemplatePattern()); - - case TemplateArgument::Integral: - return llvm::APSInt::isSameValue(Arg1.getAsIntegral(), - Arg2.getAsIntegral()); - - case TemplateArgument::StructuralValue: - return Arg1.structurallyEquals(Arg2); - - case TemplateArgument::Expression: { - llvm::FoldingSetNodeID ID1, ID2; - Arg1.getAsExpr()->Profile(ID1, *this, /*Canonical=*/true); - Arg2.getAsExpr()->Profile(ID2, *this, /*Canonical=*/true); - return ID1 == ID2; - } - - case TemplateArgument::Pack: - return llvm::equal( - Arg1.getPackAsArray(), Arg2.getPackAsArray(), - [&](const TemplateArgument &Arg1, const TemplateArgument &Arg2) { - return isSameTemplateArgument(Arg1, Arg2); - }); - } - - llvm_unreachable("Unhandled template argument kind"); -} - NestedNameSpecifier * ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { if (!NNS) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2c81f7c583eb6..4af9b6f0a1f56 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -251,8 +251,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, << D->getDeclName(); } else { Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) - << diag::ParsingInitFor::Var << D->getDeclName() - << cast<VarDecl>(D)->getType(); + << D->getDeclName() << cast<VarDecl>(D)->getType(); } return true; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7940340064eda..8ccfdb80e1ce5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4373,43 +4373,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // Produce a placeholder value if the specialization is dependent. if (Template->getDeclContext()->isDependentContext() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, CTAI.CanonicalConverted)) { - if (ParsingInitForAutoVars.empty()) - return DeclResult(); - - auto IsSameTemplateArg = [&](const TemplateArgument &Arg1, - const TemplateArgument &Arg2) { - return Context.isSameTemplateArgument(Arg1, Arg2); - }; - - if (VarDecl *Var = Template->getTemplatedDecl(); - ParsingInitForAutoVars.count(Var) && - llvm::equal( - CTAI.CanonicalConverted, - Template->getTemplateParameters()->getInjectedTemplateArgs(Context), - IsSameTemplateArg)) { - Diag(TemplateNameLoc, - diag::err_auto_variable_cannot_appear_in_own_initializer) - << diag::ParsingInitFor::VarTemplate << Var << Var->getType(); - return true; - } - - SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs; - Template->getPartialSpecializations(PartialSpecs); - for (VarTemplatePartialSpecializationDecl *Partial : PartialSpecs) - if (ParsingInitForAutoVars.count(Partial) && - llvm::equal(CTAI.CanonicalConverted, - Partial->getTemplateArgs().asArray(), - IsSameTemplateArg)) { - Diag(TemplateNameLoc, - diag::err_auto_variable_cannot_appear_in_own_initializer) - << diag::ParsingInitFor::VarTemplatePartialSpec << Partial - << Partial->getType(); - return true; - } - + TemplateArgs, CTAI.CanonicalConverted)) return DeclResult(); - } // Find the variable template specialization declaration that // corresponds to these arguments. @@ -4417,20 +4382,6 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(CTAI.CanonicalConverted, InsertPos)) { checkSpecializationReachability(TemplateNameLoc, Spec); - if (Spec->getType()->isUndeducedType()) { - if (ParsingInitForAutoVars.count(Spec)) - Diag(TemplateNameLoc, - diag::err_auto_variable_cannot_appear_in_own_initializer) - << diag::ParsingInitFor::VarTemplateExplicitSpec << Spec - << Spec->getType(); - else - // We are substituting the initializer of this variable template - // specialization. - Diag(TemplateNameLoc, diag::err_var_template_spec_type_depends_on_self) - << Spec << Spec->getType(); - - return true; - } // If we already have a variable template specialization, return it. return Spec; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 5dc06ebc2a235..b3505bad281f2 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -114,6 +114,27 @@ namespace clang { using namespace clang; using namespace sema; +/// Compare two APSInts, extending and switching the sign as +/// necessary to compare their values regardless of underlying type. +static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) { + if (Y.getBitWidth() > X.getBitWidth()) + X = X.extend(Y.getBitWidth()); + else if (Y.getBitWidth() < X.getBitWidth()) + Y = Y.extend(X.getBitWidth()); + + // If there is a signedness mismatch, correct it. + if (X.isSigned() != Y.isSigned()) { + // If the signed value is negative, then the values cannot be the same. + if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative())) + return false; + + Y.setIsSigned(true); + X.setIsSigned(true); + } + + return X == Y; +} + /// The kind of PartialOrdering we're performing template argument deduction /// for (C++11 [temp.deduct.partial]). enum class PartialOrderingKind { None, NonCall, Call }; @@ -252,7 +273,7 @@ checkDeducedTemplateArguments(ASTContext &Context, if (Y.getKind() == TemplateArgument::Expression || Y.getKind() == TemplateArgument::Declaration || (Y.getKind() == TemplateArgument::Integral && - llvm::APSInt::isSameValue(X.getAsIntegral(), Y.getAsIntegral()))) + hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral()))) return X.wasDeducedFromArrayBound() ? Y : X; // All other combinations are incompatible. @@ -2553,7 +2574,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, case TemplateArgument::Integral: if (A.getKind() == TemplateArgument::Integral) { - if (llvm::APSInt::isSameValue(P.getAsIntegral(), A.getAsIntegral())) + if (hasSameExtendedValue(P.getAsIntegral(), A.getAsIntegral())) return TemplateDeductionResult::Success; } Info.FirstArg = P; @@ -2807,6 +2828,62 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( /*HasDeducedAnyParam=*/nullptr); } +/// Determine whether two template arguments are the same. +static bool isSameTemplateArg(ASTContext &Context, const TemplateArgument &X, + const TemplateArgument &Y) { + if (X.getKind() != Y.getKind()) + return false; + + switch (X.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Comparing NULL template argument"); + + case TemplateArgument::Type: + return Context.getCanonicalType(X.getAsType()) == + Context.getCanonicalType(Y.getAsType()); + + case TemplateArgument::Declaration: + return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()); + + case TemplateArgument::NullPtr: + return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()); + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + return Context.getCanonicalTemplateName( + X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() == + Context.getCanonicalTemplateName( + Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer(); + + case TemplateArgument::Integral: + return hasSameExtendedValue(X.getAsIntegral(), Y.getAsIntegral()); + + case TemplateArgument::StructuralValue: + return X.structurallyEquals(Y); + + case TemplateArgument::Expression: { + llvm::FoldingSetNodeID XID, YID; + X.getAsExpr()->Profile(XID, Context, true); + Y.getAsExpr()->Profile(YID, Context, true); + return XID == YID; + } + + case TemplateArgument::Pack: { + unsigned PackIterationSize = X.pack_size(); + if (X.pack_size() != Y.pack_size()) + return false; + ArrayRef<TemplateArgument> XP = X.pack_elements(); + ArrayRef<TemplateArgument> YP = Y.pack_elements(); + for (unsigned i = 0; i < PackIterationSize; ++i) + if (!isSameTemplateArg(Context, XP[i], YP[i])) + return false; + return true; + } + } + + llvm_unreachable("Invalid TemplateArgument Kind!"); +} + TemplateArgumentLoc Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, @@ -3272,7 +3349,7 @@ static TemplateDeductionResult FinishTemplateArgumentDeduction( break; TemplateArgument PP = P.isPackExpansion() ? P.getPackExpansionPattern() : P, PA = A.isPackExpansion() ? A.getPackExpansionPattern() : A; - if (!S.Context.isSameTemplateArgument(PP, PA)) { + if (!isSameTemplateArg(S.Context, PP, PA)) { if (!P.isPackExpansion() && !A.isPackExpansion()) { Info.Param = makeTemplateParameter(TPL->getParam( (AsStack.empty() ? As.end() : AsStack.back().begin()) - diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index 57a48fac56cd6..eafadb07b29e1 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -412,26 +412,6 @@ namespace dependent_static_var_template { } int cf() { return F<int>(); } - -#ifdef CPP1Y - namespace GH55872 { - struct s { - template<typename T> - static CONST auto f = [] { return T::template g<s>; }; - // expected-note@-1 {{in instantiation of static data member 'dependent_static_var_template::GH55872::t::g' requested here}} - // expected-note@-2 {{while substituting into a lambda expression here}} - }; - - struct t { - template<typename T> - static CONST auto g = [] { return T::template f<t>; }; - // expected-error@-1 {{the type of variable template specialization 'f<dependent_static_var_template::GH55872::t>' declared with deduced type 'const auto' depends on itself}} - // expected-note@-2 {{while substituting into a lambda expression here}} - }; - - void test() { s::f<t>()(); } // expected-note {{in instantiation of static data member 'dependent_static_var_template::GH55872::s::f' requested here}} - } -#endif } #ifndef PRECXX11 diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index 1fe0ce9aabf29..6fc2032ee7fb4 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -492,21 +492,4 @@ static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[3] == 3, ""); static_assert(C<int, 0,1,2,3,4>::VALUEARRAY[0] == 0, ""); } - -namespace appear_in_its_own_init { -template <class T> -auto GH51347 = GH51347<T>; // expected-error {{variable template 'GH51347' declared with deduced type 'auto' cannot appear in its own initializer}} - -template <class T, class... Ts> -auto a = [] { - using U = T; - a<U, Ts...>; // expected-error {{variable template 'a' declared with deduced type 'auto' cannot appear in its own initializer}} -}; - -template <int...> int b; -template <int I> -auto b<I, I * 2, 5> = b<I, I * 2, 5l>; // expected-error {{variable template partial specialization 'b<I, I * 2, 5>' declared with deduced type 'auto' cannot appear in its own initializer}} -template <> auto b<0, 0, 0> = b<0, 0, 0>; // expected-error {{variable template explicit specialization 'b<0, 0, 0>' declared with deduced type 'auto' cannot appear in its own initializer}} -} - #endif diff --git a/clang/test/SemaTemplate/instantiate-var-template.cpp b/clang/test/SemaTemplate/instantiate-var-template.cpp index 50b7219af4bea..60d3bd3b59f53 100644 --- a/clang/test/SemaTemplate/instantiate-var-template.cpp +++ b/clang/test/SemaTemplate/instantiate-var-template.cpp @@ -47,14 +47,3 @@ namespace InvalidInsertPos { template<> int v<int, 0>; int k = v<int, 500>; } - -namespace GH97881_comment { - template <bool B> - auto g = sizeof(g<!B>); - // expected-error@-1 {{the type of variable template specialization 'g<false>'}} - // expected-note@-2 {{in instantiation of variable template specialization 'GH97881_comment::g'}} - - void test() { - (void)sizeof(g<false>); // expected-note {{in instantiation of variable template specialization 'GH97881_comment::g'}} - } -} `````````` </details> https://github.com/llvm/llvm-project/pull/139539 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits