[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
Mordante added a comment. Friendly ping. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65694/new/ https://reviews.llvm.org/D65694 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
comex added a comment. Ping. I'm not qualified to review this myself but I'd like to see the bug fixed. :) CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65694/new/ https://reviews.llvm.org/D65694 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
Mordante updated this revision to Diff 218256. Mordante added a comment. Changed the approach to use `addInstantiatedParametersToScope` as suggested by @rsmith. Since the function was `static` in another file I made it a member of `LocalInstantiationScope` and adjusted all callers. Minor changes: - Unit test remove link to Bugzilla - MutiLevelArgList -> Mu__l__tiLevelArgList CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65694/new/ https://reviews.llvm.org/D65694 Files: clang/include/clang/Sema/Template.h clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaTemplate/default-arguments-cxx0x.cpp Index: clang/test/SemaTemplate/default-arguments-cxx0x.cpp === --- clang/test/SemaTemplate/default-arguments-cxx0x.cpp +++ clang/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -114,3 +114,33 @@ S _a{}; }; } + +// Failure to resolve the decltype part during instantiation caused an +// assertion failure +namespace PR28500 { +namespace original { +template +void bar(T t = [](decltype(t) i) { return 0; }(0)) {} +void foo() { + bar(); +} +} // namespace original + +namespace cast { +template +void bar(T t = decltype(t)(0)) {} +void foo() { + bar(); + bar(); +} +} // namespace cast + +namespace value { +template +void bar(T t = decltype(t)()) {} +void foo() { + bar(); + bar(); +} +} // namespace value +} // namespace PR28500 Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp === --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3823,70 +3823,6 @@ return NewTInfo; } -/// Introduce the instantiated function parameters into the local -/// instantiation scope, and set the parameter names to those used -/// in the template. -static bool addInstantiatedParametersToScope(Sema , FunctionDecl *Function, - const FunctionDecl *PatternDecl, - LocalInstantiationScope , - const MultiLevelTemplateArgumentList ) { - unsigned FParamIdx = 0; - for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { -const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); -if (!PatternParam->isParameterPack()) { - // Simple case: not a parameter pack. - assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); - FunctionParam->setDeclName(PatternParam->getDeclName()); - // If the parameter's type is not dependent, update it to match the type - // in the pattern. They can differ in top-level cv-qualifiers, and we want - // the pattern's type here. If the type is dependent, they can't differ, - // per core issue 1668. Substitute into the type from the pattern, in case - // it's instantiation-dependent. - // FIXME: Updating the type to work around this is at best fragile. - if (!PatternDecl->getType()->isDependentType()) { -QualType T = S.SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); -if (T.isNull()) - return true; -FunctionParam->setType(T); - } - - Scope.InstantiatedLocal(PatternParam, FunctionParam); - ++FParamIdx; - continue; -} - -// Expand the parameter pack. -Scope.MakeInstantiatedLocalArgPack(PatternParam); -Optional NumArgumentsInExpansion - = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); -if (NumArgumentsInExpansion) { - QualType PatternType = - PatternParam->getType()->castAs()->getPattern(); - for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { -ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); -FunctionParam->setDeclName(PatternParam->getDeclName()); -if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg); - QualType T = S.SubstType(PatternType, TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); - if (T.isNull()) -return true; - FunctionParam->setType(T); -} - -Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); -++FParamIdx; - } -} - } - - return false; -} - void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Decl) { const FunctionProtoType *Proto = Decl->getType()->castAs(); @@ -3918,8 +3854,7 @@ getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
rsmith added a comment. This isn't the right approach: instead of re-instantiating the parameter when we encounter a use of it, we should inject the parameters into the local instantiation scope before trying to instantiate a default argument (`Sema::CheckCXXDefaultArgExpr` should call `addInstantiatedParametersToScope` to populate the `LocalInstantiationScope` before calling `SubstInitializer`). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65694/new/ https://reviews.llvm.org/D65694 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
comex added a comment. Ping. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D65694/new/ https://reviews.llvm.org/D65694 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D65694: Properly instantiate a decltype in argument's default initializer
Mordante created this revision. Mordante added reviewers: sepavloff, rsmith. Mordante added a project: clang. This fixes https://bugs.llvm.org/show_bug.cgi?id=28500 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D65694 Files: clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaTemplate/default-arguments-cxx0x.cpp Index: clang/test/SemaTemplate/default-arguments-cxx0x.cpp === --- clang/test/SemaTemplate/default-arguments-cxx0x.cpp +++ clang/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -114,3 +114,34 @@ S _a{}; }; } + +// https://bugs.llvm.org/show_bug.cgi?id=28500 +// Failure to resolve the decltype part during instantiation caused an +// assertion failure +namespace PR28500 { +namespace original { +template +void bar(T t = [](decltype(t) i) { return 0; }(0)) {} +void foo() { + bar(); +} +} // namespace original + +namespace cast { +template +void bar(T t = decltype(t)(0)) {} +void foo() { + bar(); + bar(); +} +} // namespace cast + +namespace value { +template +void bar(T t = decltype(t)()) {} +void foo() { + bar(); + bar(); +} +} // namespace value +} // namespace PR28500 Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp === --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5287,29 +5287,33 @@ // } // // In this case instantiation of the type of 'g1' requires definition of -// 'x1', which is defined later. Error recovery may produce an enum used -// before definition. In these cases we need to instantiate relevant -// declarations here. +// 'x1', which is defined later. +// +// Error recovery may produce an enum used before definition. +// +// Default arguments with a decltype referencing arguments: +// +// template void bar(T t = decltype(t)()) {} +// +// Else we must have a label decl that hasn't been found yet. +// +// In these cases we need to instantiate relevant declarations here. bool NeedInstantiate = false; if (CXXRecordDecl *RD = dyn_cast(D)) NeedInstantiate = RD->isLocalClass(); else - NeedInstantiate = isa(D); + NeedInstantiate = + isa(D) || isa(D) || isa(D); if (NeedInstantiate) { Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + assert(Inst && "Failed to instantiate"); CurrentInstantiationScope->InstantiatedLocal(D, Inst); - return cast(Inst); + return cast(Inst); } -// If we didn't find the decl, then we must have a label decl that hasn't -// been found yet. Lazily instantiate it and return it now. -assert(isa(D)); - -Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); -assert(Inst && "Failed to instantiate label??"); +assert(0 && "Failed to instantiate"); -CurrentInstantiationScope->InstantiatedLocal(D, Inst); -return cast(Inst); +return nullptr; } if (CXXRecordDecl *Record = dyn_cast(D)) { Index: clang/lib/Sema/SemaTemplateInstantiate.cpp === --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2974,6 +2974,11 @@ if (isa(D)) return nullptr; + // Default arguments with a decltype referencing arguments prior to definition + // may require instantiation. + if (isa(D)) +return nullptr; + // If we didn't find the decl, then we either have a sema bug, or we have a // forward reference to a label declaration. Return null to indicate that // we have an uninstantiated label. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits