[PATCH] D27486: Correct class-template deprecation behavior
This revision was automatically updated to reflect the committed changes. Closed by commit rL298410: Correct class-template deprecation behavior (authored by erichkeane). Changed prior to commit: https://reviews.llvm.org/D27486?vs=84330=92514#toc Repository: rL LLVM https://reviews.llvm.org/D27486 Files: cfe/trunk/include/clang/Basic/Attr.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDeclAttr.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp cfe/trunk/test/Sema/attr-deprecated.c cfe/trunk/test/SemaCXX/attr-deprecated.cpp cfe/trunk/test/SemaObjC/attr-deprecated.m cfe/trunk/test/SemaObjC/special-dep-unavail-warning.m cfe/trunk/test/SemaObjC/warn-deprecated-implementations.m cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Index: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp === --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp @@ -2451,26 +2451,19 @@ OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { - emitSourceFileHeader("Template instantiation code for attributes", OS); - - std::vectorAttrs = Records.getAllDerivedDefinitions("Attr"); - - OS << "namespace clang {\n" - << "namespace sema {\n\n" - << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " - << "Sema ,\n" - << "const MultiLevelTemplateArgumentList ) {\n" - << " switch (At->getKind()) {\n"; +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , +bool AppliesToDecl) { + OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record = *Attr; if (!R.getValueAsBit("ASTNode")) continue; - OS << "case attr::" << R.getName() << ": {\n"; -bool ShouldClone = R.getValueAsBit("Clone"); +bool ShouldClone = R.getValueAsBit("Clone") && + (!AppliesToDecl || +R.getValueAsBit("MeaningfulToClassTemplateDefinition")); if (!ShouldClone) { OS << " return nullptr;\n"; @@ -2507,8 +2500,27 @@ } OS << " } // end switch\n" << " llvm_unreachable(\"Unknown attribute!\");\n" - << " return nullptr;\n" - << "}\n\n" + << " return nullptr;\n"; +} + +// Emits code to instantiate dependent attributes on templates. +void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { + emitSourceFileHeader("Template instantiation code for attributes", OS); + + std::vector Attrs = Records.getAllDerivedDefinitions("Attr"); + + OS << "namespace clang {\n" + << "namespace sema {\n\n" + << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " + << "Sema ,\n" + << "const MultiLevelTemplateArgumentList ) {\n"; + EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false); + OS << "}\n\n" + << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n" + << " ASTContext , Sema ,\n" + << "const MultiLevelTemplateArgumentList ) {\n"; + EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true); + OS << "}\n\n" << "} // end namespace sema\n" << "} // end namespace clang\n"; } Index: cfe/trunk/include/clang/Sema/Sema.h === --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -7505,6 +7505,12 @@ LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + void + InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList , + const Decl *Pattern, Decl *Inst, + LateInstantiatedAttrVec *LateAttrs = nullptr, + LocalInstantiationScope *OuterMostScope = nullptr); + bool InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, Index: cfe/trunk/include/clang/Basic/Attr.td === --- cfe/trunk/include/clang/Basic/Attr.td +++ cfe/trunk/include/clang/Basic/Attr.td @@ -302,6 +302,9 @@ // Set to true if this attribute can be duplicated on a subject when merging // attributes. By default, attributes are not merged. bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute is meaningful when applied to or inherited + // in a class template definition. + bit
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. @rsmith did you ever get a chance to re-review this? Is this what you were wanting for this? https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
rsmith added inline comments. Comment at: include/clang/Basic/Attr.td:301 bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute should apply to template declarations, + // remains false if this should only be applied to the definition. erichkeane wrote: > rsmith wrote: > > I find this confusing -- it seems to suggest the attribute would be applied > > to the template declaration, not the templated declaration. I also think > > that the property we're modelling here is something more general than > > something about templates -- rather, I think the property is "is this > > attribute only meaningful when applied to / inherited into a defintiion?" > > It would also be useful to make clear that this only applies to class > > templates; for function templates, we always instantiate all the attributes > > with the declaration. > > > > Looking through our current attribute set, it looks like at least `AbiTag` > > should also get this set, and maybe also `Visibility`. (Though I wonder if > > there would be any problem with always instantiating the full attribute set > > for a class declaration.) > > (Though I wonder if there would be any problem with always instantiating > > the full attribute set for a class declaration.) > > This is definitely a good point. It seems that just about every other usage > of instantiating attributes happens right after creation, class template > specialization is the lone exception it seems. > > If I were to simply revert most of this change, then alter my > SemaTemplate.cpp changes to just call InstantiateAttrs and presumably remove > the other call to InstantiateAttrs (since it results in 2 sets of > attributes), would you consider that to be more acceptable? > > > Yes, I think we should at least try that and see if there's a reason why we would need the extra complexity here. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. I've actually figured out how to fix the diagnosis location. I switched the diagnosis to use the location of the actual [[deprecated]] attribute instead of the Declaration location. IMO, this is a BETTER note anyway (since the arrow points to the actual [[deprecated]] label!). I'll be uploading a new diff once I clean up a few things. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. Thanks for the feedback Richard! I'll look into whether instantiating the full attribute set upon creation is a possibility. Comment at: include/clang/Basic/Attr.td:301 bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute should apply to template declarations, + // remains false if this should only be applied to the definition. rsmith wrote: > I find this confusing -- it seems to suggest the attribute would be applied > to the template declaration, not the templated declaration. I also think that > the property we're modelling here is something more general than something > about templates -- rather, I think the property is "is this attribute only > meaningful when applied to / inherited into a defintiion?" It would also be > useful to make clear that this only applies to class templates; for function > templates, we always instantiate all the attributes with the declaration. > > Looking through our current attribute set, it looks like at least `AbiTag` > should also get this set, and maybe also `Visibility`. (Though I wonder if > there would be any problem with always instantiating the full attribute set > for a class declaration.) > (Though I wonder if there would be any problem with always instantiating the > full attribute set for a class declaration.) This is definitely a good point. It seems that just about every other usage of instantiating attributes happens right after creation, class template specialization is the lone exception it seems. If I were to simply revert most of this change, then alter my SemaTemplate.cpp changes to just call InstantiateAttrs and presumably remove the other call to InstantiateAttrs (since it results in 2 sets of attributes), would you consider that to be more acceptable? https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
rsmith added inline comments. Comment at: include/clang/Basic/Attr.td:301 bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute should apply to template declarations, + // remains false if this should only be applied to the definition. I find this confusing -- it seems to suggest the attribute would be applied to the template declaration, not the templated declaration. I also think that the property we're modelling here is something more general than something about templates -- rather, I think the property is "is this attribute only meaningful when applied to / inherited into a defintiion?" It would also be useful to make clear that this only applies to class templates; for function templates, we always instantiate all the attributes with the declaration. Looking through our current attribute set, it looks like at least `AbiTag` should also get this set, and maybe also `Visibility`. (Though I wonder if there would be any problem with always instantiating the full attribute set for a class declaration.) Comment at: lib/Sema/SemaTemplate.cpp:2406-2407 + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->AddSpecialization(Decl, InsertPos); You should also presumably do this when instantiating a member `CXXRecordDecl` nested within a class template, and when instantiating a local class in a function template. What should happen if more attributes are added between uses of the template? Example: ``` template struct A; A *p; template struct [[deprecated]] A; A *q; // warn here? ``` https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. Thanks for your help here Aaron. I agree about waiting for @rsmith, thanks! https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. This LGTM, but you should wait for @rsmith to sign off as well. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. Marking Aaron's comments done. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane updated this revision to Diff 83081. erichkeane marked 3 inline comments as done. erichkeane added a comment. Aaron's new comments https://reviews.llvm.org/D27486 Files: include/clang/Basic/Attr.td include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp utils/TableGen/ClangAttrEmitter.cpp Index: lib/Sema/SemaTemplateInstantiate.cpp === --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1882,6 +1882,8 @@ namespace sema { Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , Sema , const MultiLevelTemplateArgumentList ); +Attr *instantiateTemplateAttributeForDecl(const Attr *At, ASTContext , Sema , +const MultiLevelTemplateArgumentList ); } } Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2401,6 +2401,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -308,6 +308,26 @@ Attr.getRange()); } +void Sema::InstantiateAttrsForDecl( +const MultiLevelTemplateArgumentList , const Decl *Tmpl, +Decl *New, LateInstantiatedAttrVec *LateAttrs, +LocalInstantiationScope *OuterMostScope) { + if (NamedDecl *ND = dyn_cast(New)) { +for (const auto *TmplAttr : Tmpl->attrs()) { + // FIXME: If any of the special case versions from InstantiateAttrs become + // applicable to template declaration, we'll need to add them here. + CXXThisScopeRAII ThisScope( + *this, dyn_cast_or_null(ND->getDeclContext()), + /*TypeQuals*/ 0, ND->isCXXInstanceMember()); + + Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( + TmplAttr, Context, *this, TemplateArgs); + if (NewAttr) +New->addAttr(NewAttr); +} + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList , const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -945,6 +965,7 @@ } } + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Enum); SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); @@ -1033,6 +1054,7 @@ } if (EnumConst) { + SemaRef.InstantiateAttrsForDecl(TemplateArgs, EC, EnumConst); SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); EnumConst->setAccess(Enum->getAccess()); Index: utils/TableGen/ClangAttrEmitter.cpp === --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -2452,26 +2452,21 @@ OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { - emitSourceFileHeader("Template instantiation code for attributes", OS); - - std::vectorAttrs = Records.getAllDerivedDefinitions("Attr"); - - OS << "namespace clang {\n" - << "namespace sema {\n\n" - << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " - << "Sema ,\n" - << "const MultiLevelTemplateArgumentList ) {\n" - << " switch (At->getKind()) {\n"; +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , +bool AppliesToDecl) { + OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record = *Attr; if (!R.getValueAsBit("ASTNode")) continue; OS << "case attr::" << R.getName() << ": {\n"; -bool ShouldClone = R.getValueAsBit("Clone"); + +bool ShouldClone = +R.getValueAsBit("Clone") && +R.getValueAsBit("AppliesToTemplateDeclaration") == AppliesToDecl; if (!ShouldClone) { OS << " return nullptr;\n"; @@ -2508,8
[PATCH] D27486: Correct class-template deprecation behavior
aaron.ballman added inline comments. Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:322 + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, + ND && ND->isCXXInstanceMember()); + No need to check for `ND` here; already done above. You might also want to remove `ThisContext` and just sink the initialization. Comment at: utils/TableGen/ClangAttrEmitter.cpp:2520 + << "const MultiLevelTemplateArgumentList ) {\n"; + EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*DeclTime=*/false); + OS << "}\n\n" DeclTime -> AppliesToDecl Comment at: utils/TableGen/ClangAttrEmitter.cpp:2525 + << "const MultiLevelTemplateArgumentList ) {\n"; + EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*DeclTime=*/true); + DeclTime -> AppliesToDecl https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane updated this revision to Diff 83072. erichkeane marked 2 inline comments as done. erichkeane added a comment. Updated based on Aarons comments. https://reviews.llvm.org/D27486 Files: include/clang/Basic/Attr.td include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp utils/TableGen/ClangAttrEmitter.cpp Index: lib/Sema/SemaTemplateInstantiate.cpp === --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1882,6 +1882,8 @@ namespace sema { Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , Sema , const MultiLevelTemplateArgumentList ); +Attr *instantiateTemplateAttributeForDecl(const Attr *At, ASTContext , Sema , +const MultiLevelTemplateArgumentList ); } } Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2401,6 +2401,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -308,6 +308,27 @@ Attr.getRange()); } +void Sema::InstantiateAttrsForDecl( +const MultiLevelTemplateArgumentList , const Decl *Tmpl, +Decl *New, LateInstantiatedAttrVec *LateAttrs, +LocalInstantiationScope *OuterMostScope) { + if (NamedDecl *ND = dyn_cast(New)) { +for (const auto *TmplAttr : Tmpl->attrs()) { + // FIXME: If any of the special case versions from InstantiateAttrs become + // applicable to template declaration, we'll need to add them here. + CXXRecordDecl *ThisContext = + dyn_cast_or_null(ND->getDeclContext()); + CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, + ND && ND->isCXXInstanceMember()); + + Attr *NewAttr = sema::instantiateTemplateAttributeForDecl( + TmplAttr, Context, *this, TemplateArgs); + if (NewAttr) +New->addAttr(NewAttr); +} + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList , const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -945,6 +966,7 @@ } } + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Enum); SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); @@ -1033,6 +1055,7 @@ } if (EnumConst) { + SemaRef.InstantiateAttrsForDecl(TemplateArgs, EC, EnumConst); SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); EnumConst->setAccess(Enum->getAccess()); Index: utils/TableGen/ClangAttrEmitter.cpp === --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -2452,26 +2452,21 @@ OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { - emitSourceFileHeader("Template instantiation code for attributes", OS); - - std::vectorAttrs = Records.getAllDerivedDefinitions("Attr"); - - OS << "namespace clang {\n" - << "namespace sema {\n\n" - << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " - << "Sema ,\n" - << "const MultiLevelTemplateArgumentList ) {\n" - << " switch (At->getKind()) {\n"; +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , +bool AppliesToDecl) { + OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record = *Attr; if (!R.getValueAsBit("ASTNode")) continue; OS << "case attr::" << R.getName() << ": {\n"; -bool ShouldClone = R.getValueAsBit("Clone"); + +bool ShouldClone = +R.getValueAsBit("Clone") && +R.getValueAsBit("AppliesToTemplateDeclaration") ==
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane marked 6 inline comments as done. erichkeane added a comment. All Aaron's comments addressed in a patch that is on its way! Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:320 +CXXRecordDecl *ThisContext = +dyn_cast_or_null(ND->getDeclContext()); +CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, aaron.ballman wrote: > Are you sure `ND` is always non-null? If so, then you should use `cast<>` > above instead of `dyn_cast<>`. I hadn't thought much about it actually, this is from a section in InstantiateAttrs (see 410 in this file). Also reinspecting, it seems that ND can be moved above the for-loop as well, so I'm going to do that, so that we can perhaps save the attributes in that case. Comment at: utils/TableGen/ClangAttrEmitter.cpp:2456 +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , bool DeclTime) { + OS << " switch (At->getKind()) {\n"; aaron.ballman wrote: > What does "time" mean in `DeclTime`? Right, good point. I'll choose a better name in the next patch. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
aaron.ballman added inline comments. Comment at: include/clang/Basic/Attr.td:301 bit DuplicatesAllowedWhileMerging = 0; + // Set to true if this attribute should apply to template declaration, + // remains false if this should only be applied on definition. template declaration -> template declarations Comment at: include/clang/Basic/Attr.td:302 + // Set to true if this attribute should apply to template declaration, + // remains false if this should only be applied on definition. + bit AppliesToTemplateDeclaration = 0; on definition -> to the definition Comment at: include/clang/Sema/Sema.h:7388-7391 + void InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList , +const Decl *Pattern, Decl *Inst, +LateInstantiatedAttrVec *LateAttrs = nullptr, +LocalInstantiationScope *OuterMostScope = nullptr); Did clang-format produce this formatting? Comment at: lib/Sema/SemaTemplateInstantiateDecl.cpp:320 +CXXRecordDecl *ThisContext = +dyn_cast_or_null(ND->getDeclContext()); +CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, Are you sure `ND` is always non-null? If so, then you should use `cast<>` above instead of `dyn_cast<>`. Comment at: utils/TableGen/ClangAttrEmitter.cpp:2456 +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , bool DeclTime) { + OS << " switch (At->getKind()) {\n"; What does "time" mean in `DeclTime`? Comment at: utils/TableGen/ClangAttrEmitter.cpp:2507 +} +// Emits code to instantiate dependent attributes on templates. +void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { Add a newline above this comment to separate it from the previous function body. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane updated this revision to Diff 82909. erichkeane added a comment. Updated based on Richard Smith's suggestion, all tests pass with no alteration, and the initial incorrect behavior was corrected in an existing test. https://reviews.llvm.org/D27486 Files: include/clang/Basic/Attr.td include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp utils/TableGen/ClangAttrEmitter.cpp Index: lib/Sema/SemaTemplateInstantiate.cpp === --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1882,6 +1882,8 @@ namespace sema { Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , Sema , const MultiLevelTemplateArgumentList ); +Attr *instantiateTemplateAttributeForDecl(const Attr *At, ASTContext , Sema , +const MultiLevelTemplateArgumentList ); } } Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2401,6 +2401,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -308,6 +308,26 @@ Attr.getRange()); } +void Sema::InstantiateAttrsForDecl( +const MultiLevelTemplateArgumentList , const Decl *Tmpl, +Decl *New, LateInstantiatedAttrVec *LateAttrs, +LocalInstantiationScope *OuterMostScope) { + for (const auto *TmplAttr : Tmpl->attrs()) { +// FIXME: If any of the special case versions from InstantiateAttrs become +// applicable to template declaration, we'll need to add them here. +NamedDecl *ND = dyn_cast(New); +CXXRecordDecl *ThisContext = +dyn_cast_or_null(ND->getDeclContext()); +CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, + ND && ND->isCXXInstanceMember()); + +Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(TmplAttr, Context, *this, + TemplateArgs); +if (NewAttr) + New->addAttr(NewAttr); + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList , const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -945,6 +965,7 @@ } } + SemaRef.InstantiateAttrsForDecl(TemplateArgs, D, Enum); SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation); @@ -1033,6 +1054,7 @@ } if (EnumConst) { + SemaRef.InstantiateAttrsForDecl(TemplateArgs, EC, EnumConst); SemaRef.InstantiateAttrs(TemplateArgs, EC, EnumConst); EnumConst->setAccess(Enum->getAccess()); Index: utils/TableGen/ClangAttrEmitter.cpp === --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -2452,26 +2452,20 @@ OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { - emitSourceFileHeader("Template instantiation code for attributes", OS); - - std::vectorAttrs = Records.getAllDerivedDefinitions("Attr"); - - OS << "namespace clang {\n" - << "namespace sema {\n\n" - << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " - << "Sema ,\n" - << "const MultiLevelTemplateArgumentList ) {\n" - << " switch (At->getKind()) {\n"; +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , bool DeclTime) { + OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record = *Attr; if (!R.getValueAsBit("ASTNode")) continue; OS << "case attr::" << R.getName() << ": {\n"; -bool ShouldClone = R.getValueAsBit("Clone"); + +bool ShouldClone = +R.getValueAsBit("Clone") && +
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane updated this revision to Diff 80907. erichkeane added a comment. I've been trying to do what @rsmith suggested, so this is a WIP checkpoint, I was hoping you could take a look and tell me if I'm on the right track. I beleive I'm very nearly done, and all but 1 of the tests pass, which if you have spare cycles and could suggest something, I would much appreciate it. Currently: template struct C { enum [[deprecated]] Enum {c0;}}; void foo() { CEnum x; // Used to warn, no longer does x = C::c0; // Used to warn, no longer does } https://reviews.llvm.org/D27486 Files: include/clang/Basic/Attr.td include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp utils/TableGen/ClangAttrEmitter.cpp Index: lib/Sema/SemaTemplateInstantiate.cpp === --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1858,6 +1858,8 @@ namespace sema { Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , Sema , const MultiLevelTemplateArgumentList ); +Attr *instantiateTemplateAttributeForDecl(const Attr *At, ASTContext , Sema , +const MultiLevelTemplateArgumentList ); } } Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2352,6 +2352,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(Converted); + InstantiateAttrsForDecl(TemplateArgLists, + ClassTemplate->getTemplatedDecl(), Decl); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: lib/Sema/SemaTemplateInstantiateDecl.cpp === --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -308,6 +308,26 @@ Attr.getRange()); } +void Sema::InstantiateAttrsForDecl( +const MultiLevelTemplateArgumentList , const Decl *Tmpl, +Decl *New, LateInstantiatedAttrVec *LateAttrs, +LocalInstantiationScope *OuterMostScope) { + for (const auto *TmplAttr : Tmpl->attrs()) { +// FIXME: If any of the special case versions from InstantiateAttrs become +// applicable to template declaration, we'll need to add them here. +NamedDecl *ND = dyn_cast(New); +CXXRecordDecl *ThisContext = +dyn_cast_or_null(ND->getDeclContext()); +CXXThisScopeRAII ThisScope(*this, ThisContext, /*TypeQuals*/ 0, + ND && ND->isCXXInstanceMember()); + +Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(TmplAttr, Context, *this, + TemplateArgs); +if (NewAttr) + New->addAttr(NewAttr); + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList , const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, Index: utils/TableGen/ClangAttrEmitter.cpp === --- utils/TableGen/ClangAttrEmitter.cpp +++ utils/TableGen/ClangAttrEmitter.cpp @@ -2452,26 +2452,20 @@ OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper , raw_ostream ) { - emitSourceFileHeader("Template instantiation code for attributes", OS); - - std::vectorAttrs = Records.getAllDerivedDefinitions("Attr"); - - OS << "namespace clang {\n" - << "namespace sema {\n\n" - << "Attr *instantiateTemplateAttribute(const Attr *At, ASTContext , " - << "Sema ,\n" - << "const MultiLevelTemplateArgumentList ) {\n" - << " switch (At->getKind()) {\n"; +void EmitClangAttrTemplateInstantiateHelper(const std::vector , +raw_ostream , bool DeclTime) { + OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record = *Attr; if (!R.getValueAsBit("ASTNode")) continue; OS << "case attr::" << R.getName() << ": {\n"; -bool ShouldClone = R.getValueAsBit("Clone"); + +bool ShouldClone = +R.getValueAsBit("Clone") && +R.getValueAsBit("AppliesToTemplateDeclaration") == DeclTime; if (!ShouldClone) { OS << " return nullptr;\n"; @@ -2508,8 +2502,27
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. Thanks David! To all - I'm actually doing my best to rewrite this based on Richard's suggestions, so look for a 'in progress' update to this review as soon as I get something that is reasonably presentable. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
majnemer added inline comments. Comment at: lib/Sema/SemaTemplate.cpp:2355 Converted, nullptr); + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) Please capitalize `Attr`. Comment at: lib/Sema/SemaTemplate.cpp:2356 + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) +Decl->addAttr(attr->clone(Context)); I think you can remove the `clang::` https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane added a comment. In https://reviews.llvm.org/D27486#615174, @rsmith wrote: > Thanks! > > If you look at `Sema::InstantiateClass`, we instantiate all of the attributes > there. The problem seems to be that that happens only when instantiating the > class definition, which happens after the point at which we would diagnose > use of a deprecated declaration. > > This change will result in us having two copies of the `deprecated` attribute > after we instantiate the class definition -- one from instantiating the > declaration and another from instantiating the definition. Well darn, I didn't notice this. > Perhaps a better way to handle this would be to add a flag to the attribute > definitions (in Attr.td) to indicate whether they apply to a declaration or > just a definition (and thus whether they should be instantiated with a > declaration, or only with a definition), and then instantiate the relevant > subset when creating the `ClassTemplateSpecializationDecl` (and other kinds > of decl -- I expect the same thing will happen for member classes of class > templates, for function templates, and so on). I can definitely look into this. I have a feeling (based on the fact that this attribute IS picked up by function-template-instantiations) that it likely wouldn't be necessary for the others, but I can start to look into the scaffolding to get this to happen. > @aaron.ballman Does that seem reasonable to you? If so, we should do some > investigation of the attribute set to figure out what the best default is. As far as this investigation, I'd suspect that the current behavior (never applies to declaration) is likely the correct 'default' is. I suspect that there is also a massive work-item to go through the current list to see which SHOULD apply to declarations. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
rsmith added a comment. Thanks! If you look at `Sema::InstantiateClass`, we instantiate all of the attributes there. The problem seems to be that that happens only when instantiating the class definition, which happens after the point at which we would diagnose use of a deprecated declaration. This change will result in us having two copies of the `deprecated` attribute after we instantiate the class definition -- one from instantiating the declaration and another from instantiating the definition. Perhaps a better way to handle this would be to add a flag to the attribute definitions (in Attr.td) to indicate whether they apply to a declaration or just a definition (and thus whether they should be instantiated with a declaration, or only with a definition), and then instantiate the relevant subset when creating the `ClassTemplateSpecializationDecl` (and other kinds of decl -- I expect the same thing will happen for member classes of class templates, for function templates, and so on). @aaron.ballman Does that seem reasonable to you? If so, we should do some investigation of the attribute set to figure out what the best default is. https://reviews.llvm.org/D27486 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane removed rL LLVM as the repository for this revision. erichkeane updated this revision to Diff 80489. erichkeane added a comment. Corrected single line statement formatting re-squiggly braces. https://reviews.llvm.org/D27486 Files: lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2352,6 +2352,9 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) +Decl->addAttr(attr->clone(Context)); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp === --- test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,7 +23,8 @@ X x1; X x2; // expected-warning {{'X' is deprecated}} -template class [[deprecated]] X2 {}; +template class [[deprecated]] X2 {}; //expected-note {{'X2' has been explicitly marked deprecated here}} template <> class X2 {}; -X2 x3; // FIXME: no warning! -X2 x4; +X2 x3; // expected-warning {{'X2' is deprecated}} +X2 x4; // No warning, the specialization removes it. + Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2352,6 +2352,9 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) +Decl->addAttr(attr->clone(Context)); ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp === --- test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,7 +23,8 @@ X x1; X x2; // expected-warning {{'X' is deprecated}} -template class [[deprecated]] X2 {}; +template class [[deprecated]] X2 {}; //expected-note {{'X2' has been explicitly marked deprecated here}} template <> class X2 {}; -X2 x3; // FIXME: no warning! -X2 x4; +X2 x3; // expected-warning {{'X2' is deprecated}} +X2 x4; // No warning, the specialization removes it. + ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D27486: Correct class-template deprecation behavior
erichkeane created this revision. erichkeane added reviewers: cfe-commits, chandlerc, majnemer. erichkeane set the repository for this revision to rL LLVM. Based on the comment in the test, and my reading of the standard, a deprecated warning should be issued in the following case: template [[deprecated]] class Foo{}; Foo f; This was not the case, because the ClassTemplateSpecializationDecl creation did not also copy the deprecated attribute. Note: I did NOT audit the complete set of attributes to see WHICH ones should be copied, so instead I simply copy ONLY the deprecated attribute. Repository: rL LLVM https://reviews.llvm.org/D27486 Files: lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2352,6 +2352,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) { +Decl->addAttr(attr->clone(Context)); + } ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp === --- test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,7 +23,8 @@ X x1; X x2; // expected-warning {{'X' is deprecated}} -template class [[deprecated]] X2 {}; +template class [[deprecated]] X2 {}; //expected-note {{'X2' has been explicitly marked deprecated here}} template <> class X2 {}; -X2 x3; // FIXME: no warning! -X2 x4; +X2 x3; // expected-warning {{'X2' is deprecated}} +X2 x4; // No warning, the specialization removes it. + Index: lib/Sema/SemaTemplate.cpp === --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -2352,6 +2352,10 @@ ClassTemplate->getLocation(), ClassTemplate, Converted, nullptr); + if (auto *attr = ClassTemplate->getTemplatedDecl() + ->getAttr()) { +Decl->addAttr(attr->clone(Context)); + } ClassTemplate->AddSpecialization(Decl, InsertPos); if (ClassTemplate->isOutOfLine()) Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); Index: test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp === --- test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,7 +23,8 @@ X x1; X x2; // expected-warning {{'X' is deprecated}} -template class [[deprecated]] X2 {}; +template class [[deprecated]] X2 {}; //expected-note {{'X2' has been explicitly marked deprecated here}} template <> class X2 {}; -X2 x3; // FIXME: no warning! -X2 x4; +X2 x3; // expected-warning {{'X2' is deprecated}} +X2 x4; // No warning, the specialization removes it. + ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits