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 &C, Sema &S,
const MultiLevelTemplateArgumentList &TemplateArgs);
+ Attr *instantiateTemplateAttributeForDecl(const Attr *At, ASTContext &C, Sema &S,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
}
}
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 &TemplateArgs, const Decl *Tmpl,
+ Decl *New, LateInstantiatedAttrVec *LateAttrs,
+ LocalInstantiationScope *OuterMostScope) {
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(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<CXXRecordDecl>(ND->getDeclContext()),
+ /*TypeQuals*/ 0, ND->isCXXInstanceMember());
+
+ Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
+ TmplAttr, Context, *this, TemplateArgs);
+ if (NewAttr)
+ New->addAttr(NewAttr);
+ }
+ }
+}
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
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 &Records, raw_ostream &OS) {
- emitSourceFileHeader("Template instantiation code for attributes", OS);
-
- std::vector<Record*> 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";
+void EmitClangAttrTemplateInstantiateHelper(const std::vector<Record *> &Attrs,
+ raw_ostream &OS,
+ bool AppliesToDecl) {
+ 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");
+
+ bool ShouldClone =
+ R.getValueAsBit("Clone") &&
+ R.getValueAsBit("AppliesToTemplateDeclaration") == AppliesToDecl;
if (!ShouldClone) {
OS << " return nullptr;\n";
@@ -2508,8 +2503,28 @@
}
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 &Records, raw_ostream &OS) {
+ emitSourceFileHeader("Template instantiation code for attributes", OS);
+
+ std::vector<Record*> 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"
<< "} // end namespace sema\n"
<< "} // end namespace clang\n";
}
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -7385,6 +7385,12 @@
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,
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -298,6 +298,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 should apply to template declarations,
+ // remains false if this should only be applied to the definition.
+ bit AppliesToTemplateDeclaration = 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<LangOpt> LangOpts = [];
@@ -765,6 +768,7 @@
// Fix-It.
StringArgument<"Replacement", 1>];
let Documentation = [DeprecatedDocs];
+ let AppliesToTemplateDeclaration = 1;
}
def Destructor : InheritableAttr {
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<char> x1;
X<int> x2; // expected-warning {{'X<int>' is deprecated}}
-template <typename T> class [[deprecated]] X2 {};
+template <typename T> class [[deprecated]] X2 {}; //expected-note {{'X2<char>' has been explicitly marked deprecated here}}
template <> class X2<int> {};
-X2<char> x3; // FIXME: no warning!
-X2<int> x4;
+X2<char> x3; // expected-warning {{'X2<char>' is deprecated}}
+X2<int> x4; // No warning, the specialization removes it.
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits