From: Martin Bohme Date: Wed, 22 Mar 2017 13:34:37 +0000 (+0000) Subject: Revert "Correct class-template deprecation behavior" X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d29393efed93fd291655ab02a4ebf42922c9a554;p=clang Revert "Correct class-template deprecation behavior" This reverts commit r298410 (which produces incorrect warnings, see comments on https://reviews.llvm.org/rL298410). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@298504 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 38ae1ed21e..ff62e10f8a 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -302,9 +302,6 @@ class Attr { // 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 MeaningfulToClassTemplateDefinition = 0; // Lists language options, one of which is required to be true for the // attribute to be applicable. If empty, no language options are required. list LangOpts = []; @@ -376,7 +373,6 @@ def AbiTag : Attr { let Args = [VariadicStringArgument<"Tags">]; let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, "ExpectedStructClassVariableFunctionOrInlineNamespace">; - let MeaningfulToClassTemplateDefinition = 1; let Documentation = [AbiTagsDocs]; } @@ -809,7 +805,6 @@ def Deprecated : InheritableAttr { // An optional string argument that enables us to provide a // Fix-It. StringArgument<"Replacement", 1>]; - let MeaningfulToClassTemplateDefinition = 1; let Documentation = [DeprecatedDocs]; } @@ -1728,7 +1723,6 @@ def Visibility : InheritableAttr { let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; - let MeaningfulToClassTemplateDefinition = 1; let Documentation = [Undocumented]; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index d3661ae0d3..9588ab4212 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -7505,12 +7505,6 @@ public: LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); - void - InstantiateAttrsForDecl(const MultiLevelTemplateArgumentList &TemplateArgs, - const Decl *Pattern, Decl *Inst, - LateInstantiatedAttrVec *LateAttrs = nullptr, - LocalInstantiationScope *OuterMostScope = nullptr); - bool InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index b3dc71987f..1c350a7e38 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -6723,7 +6723,6 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, // Diagnostics for deprecated or unavailable. unsigned diag, diag_message, diag_fwdclass_message; unsigned diag_available_here = diag::note_availability_specified_here; - SourceLocation NoteLocation = D->getLocation(); // Matches 'diag::note_property_attribute' options. unsigned property_note_select; @@ -6746,8 +6745,6 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, diag_fwdclass_message = diag::warn_deprecated_fwdclass_message; property_note_select = /* deprecated */ 0; available_here_select_kind = /* deprecated */ 2; - if (auto *attr = D->getAttr()) - NoteLocation = attr->getLocation(); break; case AR_Unavailable: @@ -6866,7 +6863,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, } } else - S.Diag(NoteLocation, diag_available_here) + S.Diag(D->getLocation(), diag_available_here) << D << available_here_select_kind; if (K == AR_NotYetIntroduced) diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 1699319238..f6c6ccbd41 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2846,13 +2846,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); } - if (Decl->getSpecializationKind() == TSK_Undeclared) { - MultiLevelTemplateArgumentList TemplateArgLists; - TemplateArgLists.addOuterTemplateArguments(Converted); - InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(), - Decl); - } - // Diagnose uses of this specialization. (void)DiagnoseUseOfDecl(Decl, TemplateLoc); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 67e330a6da..314dfe3256 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1939,9 +1939,6 @@ namespace clang { namespace sema { Attr *instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs); - Attr *instantiateTemplateAttributeForDecl( - const Attr *At, ASTContext &C, Sema &S, - const MultiLevelTemplateArgumentList &TemplateArgs); } } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6a4e5324b2..cab55ea0bf 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -328,35 +328,6 @@ static void instantiateOMPDeclareSimdDeclAttr( Attr.getRange()); } -bool DeclContainsAttr(Decl* D, attr::Kind K) { - if (!D->hasAttrs()) - return false; - for (auto&& attr : D->getAttrs()) - if (attr->getKind() == K) - return true; - return false; -} - -void Sema::InstantiateAttrsForDecl( - const MultiLevelTemplateArgumentList &TemplateArgs, 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 && !DeclContainsAttr(New, NewAttr->getKind())) - New->addAttr(NewAttr); - } - } -} - void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -450,8 +421,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); - - if (NewAttr && !DeclContainsAttr(New, NewAttr->getKind())) + if (NewAttr) New->addAttr(NewAttr); } } diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp index 58c7c0cfac..a27cea84db 100644 --- a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp @@ -23,38 +23,7 @@ template <> class [[deprecated]] X {}; // expected-note {{'X' has been X x1; X x2; // expected-warning {{'X' is deprecated}} -template class [[deprecated]] X2 {}; //expected-note {{'X2' has been explicitly marked deprecated here}} +template class [[deprecated]] X2 {}; template <> class X2 {}; -X2 x3; // expected-warning {{'X2' is deprecated}} -X2 x4; // No warning, the specialization removes it. - -template class [[deprecated]] X3; //expected-note {{'X3' has been explicitly marked deprecated here}} -template <> class X3; -X3 *x5; // expected-warning {{'X3' is deprecated}} -X3 *x6; // No warning, the specialization removes it. - -template struct A; -A *p; -template struct [[deprecated]] A;//expected-note {{'A' has been explicitly marked deprecated here}} expected-note {{'A' has been explicitly marked deprecated here}} -A *q; // expected-warning {{'A' is deprecated}} -A *r; // expected-warning {{'A' is deprecated}} - -template struct B; -B *p2; -template struct [[deprecated]] B;//expected-note {{'B' has been explicitly marked deprecated here}} expected-note {{'B' has been explicitly marked deprecated here}} -B *q2; // expected-warning {{'B' is deprecated}} -B *r2; // expected-warning {{'B' is deprecated}} - -template -T some_func(T t) { - struct [[deprecated]] FunS{}; // expected-note {{'FunS' has been explicitly marked deprecated here}} - FunS f;// expected-warning {{'FunS' is deprecated}} - -} - -template -[[deprecated]]T some_func2(T t) { - struct FunS2{}; - FunS2 f;// No warning, entire function is deprecated, so usage here should be fine. - -} +X2 x3; // FIXME: no warning! +X2 x4; diff --git a/test/Sema/attr-deprecated.c b/test/Sema/attr-deprecated.c index d6f560f175..8566a0e943 100644 --- a/test/Sema/attr-deprecated.c +++ b/test/Sema/attr-deprecated.c @@ -1,10 +1,10 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only int f() __attribute__((deprecated)); // expected-note 2 {{'f' has been explicitly marked deprecated here}} -void g() __attribute__((deprecated));// expected-note {{'g' has been explicitly marked deprecated here}} -void g(); +void g() __attribute__((deprecated)); +void g(); // expected-note {{'g' has been explicitly marked deprecated here}} -extern int var __attribute__((deprecated)); // expected-note 2 {{'var' has been explicitly marked deprecated here}} +extern int var __attribute__((deprecated)); // expected-note {{'var' has been explicitly marked deprecated here}} int a() { int (*ptr)() = f; // expected-warning {{'f' is deprecated}} @@ -17,13 +17,13 @@ int a() { } // test if attributes propagate to variables -extern int var; +extern int var; // expected-note {{'var' has been explicitly marked deprecated here}} int w() { return var; // expected-warning {{'var' is deprecated}} } -int old_fn() __attribute__ ((deprecated));// expected-note {{'old_fn' has been explicitly marked deprecated here}} -int old_fn(); +int old_fn() __attribute__ ((deprecated)); +int old_fn(); // expected-note {{'old_fn' has been explicitly marked deprecated here}} int (*fn_ptr)() = old_fn; // expected-warning {{'old_fn' is deprecated}} int old_fn() { @@ -44,8 +44,8 @@ void test1(struct foo *F) { typedef struct foo foo_dep __attribute__((deprecated)); // expected-note 12 {{'foo_dep' has been explicitly marked deprecated here}} foo_dep *test2; // expected-warning {{'foo_dep' is deprecated}} -struct __attribute__((deprecated, // expected-note 2 {{'bar_dep' has been explicitly marked deprecated here}} - invalid_attribute)) bar_dep ; // expected-warning {{unknown attribute 'invalid_attribute' ignored}} +struct __attribute__((deprecated, + invalid_attribute)) bar_dep ; // expected-warning {{unknown attribute 'invalid_attribute' ignored}} expected-note 2 {{'bar_dep' has been explicitly marked deprecated here}} struct bar_dep *test3; // expected-warning {{'bar_dep' is deprecated}} @@ -121,11 +121,11 @@ struct test22 { __attribute((deprecated)) foo_dep e, f; }; -typedef int test23_ty __attribute((deprecated)); // expected-note {{'test23_ty' has been explicitly marked deprecated here}} +typedef int test23_ty __attribute((deprecated)); // Redefining a typedef is a C11 feature. #if __STDC_VERSION__ <= 199901L // expected-note@-3 {{'test23_ty' has been explicitly marked deprecated here}} #else -typedef int test23_ty; +typedef int test23_ty; // expected-note {{'test23_ty' has been explicitly marked deprecated here}} #endif test23_ty test23_v; // expected-warning {{'test23_ty' is deprecated}} diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp index 1680c5c676..eab5a1c0ec 100644 --- a/test/SemaCXX/attr-deprecated.cpp +++ b/test/SemaCXX/attr-deprecated.cpp @@ -56,14 +56,14 @@ void f(B* b, C *c) { } struct D { - virtual void f() __attribute__((deprecated));// expected-note{{'f' has been explicitly marked deprecated here}} - virtual void f(int) __attribute__((deprecated));// expected-note{{'f' has been explicitly marked deprecated here}} - virtual void f(int, int) __attribute__((deprecated));// expected-note{{'f' has been explicitly marked deprecated here}} + virtual void f() __attribute__((deprecated)); + virtual void f(int) __attribute__((deprecated)); + virtual void f(int, int) __attribute__((deprecated)); }; -void D::f() { } -void D::f(int v) { } -void D::f(int v1, int v2) { } +void D::f() { } // expected-note{{'f' has been explicitly marked deprecated here}} +void D::f(int v) { } // expected-note{{'f' has been explicitly marked deprecated here}} +void D::f(int v1, int v2) { } // expected-note{{'f' has been explicitly marked deprecated here}} void f(D* d) { d->f(); // expected-warning{{'f' is deprecated}} diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m index 229fc6bab7..59087bdf11 100644 --- a/test/SemaObjC/attr-deprecated.m +++ b/test/SemaObjC/attr-deprecated.m @@ -83,8 +83,8 @@ int t5() { } -__attribute ((deprecated)) // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}} -@interface DEPRECATED { +__attribute ((deprecated)) +@interface DEPRECATED { // expected-note 2 {{'DEPRECATED' has been explicitly marked deprecated here}} @public int ivar; DEPRECATED *ivar2; // no warning. } diff --git a/test/SemaObjC/special-dep-unavail-warning.m b/test/SemaObjC/special-dep-unavail-warning.m index b667c3c51c..9e16b331c2 100644 --- a/test/SemaObjC/special-dep-unavail-warning.m +++ b/test/SemaObjC/special-dep-unavail-warning.m @@ -44,8 +44,8 @@ void test(C *c) { } // rdar://10268422 -__attribute ((deprecated)) // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}} -@interface DEPRECATED +__attribute ((deprecated)) +@interface DEPRECATED // expected-note {{'DEPRECATED' has been explicitly marked deprecated here}} +(id)new; @end diff --git a/test/SemaObjC/warn-deprecated-implementations.m b/test/SemaObjC/warn-deprecated-implementations.m index 4ef45b4835..6e208b5be7 100644 --- a/test/SemaObjC/warn-deprecated-implementations.m +++ b/test/SemaObjC/warn-deprecated-implementations.m @@ -28,8 +28,8 @@ - (void) G {} // No warning, implementing its own deprecated method @end -__attribute__((deprecated)) // expected-note 2 {{'CL' has been explicitly marked deprecated here}} -@interface CL // expected-note 2 {{class declared here}} +__attribute__((deprecated)) +@interface CL // expected-note 2 {{class declared here}} // expected-note 2 {{'CL' has been explicitly marked deprecated here}} @end @implementation CL // expected-warning {{Implementing deprecated class}} diff --git a/utils/TableGen/ClangAttrEmitter.cpp b/utils/TableGen/ClangAttrEmitter.cpp index c516b53101..990b860dea 100644 --- a/utils/TableGen/ClangAttrEmitter.cpp +++ b/utils/TableGen/ClangAttrEmitter.cpp @@ -2451,19 +2451,26 @@ void EmitClangAttrASTVisitor(RecordKeeper &Records, raw_ostream &OS) { OS << "#endif // ATTR_VISITOR_DECLS_ONLY\n"; } -void EmitClangAttrTemplateInstantiateHelper(const std::vector &Attrs, - raw_ostream &OS, - bool AppliesToDecl) { +// Emits code to instantiate dependent attributes on templates. +void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { + 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 &C, " + << "Sema &S,\n" + << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n" + << " switch (At->getKind()) {\n"; - OS << " switch (At->getKind()) {\n"; for (const auto *Attr : Attrs) { const Record &R = *Attr; if (!R.getValueAsBit("ASTNode")) continue; + OS << " case attr::" << R.getName() << ": {\n"; - bool ShouldClone = R.getValueAsBit("Clone") && - (!AppliesToDecl || - R.getValueAsBit("MeaningfulToClassTemplateDefinition")); + bool ShouldClone = R.getValueAsBit("Clone"); if (!ShouldClone) { OS << " return nullptr;\n"; @@ -2500,27 +2507,8 @@ void EmitClangAttrTemplateInstantiateHelper(const std::vector &Attrs, } OS << " } // end switch\n" << " llvm_unreachable(\"Unknown attribute!\");\n" - << " return nullptr;\n"; -} - -// Emits code to instantiate dependent attributes on templates. -void EmitClangAttrTemplateInstantiate(RecordKeeper &Records, raw_ostream &OS) { - 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 &C, " - << "Sema &S,\n" - << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; - EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/false); - OS << "}\n\n" - << "Attr *instantiateTemplateAttributeForDecl(const Attr *At,\n" - << " ASTContext &C, Sema &S,\n" - << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"; - EmitClangAttrTemplateInstantiateHelper(Attrs, OS, /*AppliesToDecl*/true); - OS << "}\n\n" + << " return nullptr;\n" + << "}\n\n" << "} // end namespace sema\n" << "} // end namespace clang\n"; }