Skip to content

Commit a134477

Browse files
committed
Revert "Add new 'preferred_name' attribute."
This change exposed a pre-existing issue with deserialization cycles caused by a combination of attributes and template instantiations violating the deserialization ordering restrictions; see PR48434 for details. A previous commit attempted to work around PR48434, but appears to have only been a partial fix, and fixing this properly seems non-trivial. Backing out for now to unblock things. This reverts commit 98f76ad and commit a64c26a.
1 parent 4415678 commit a134477

File tree

16 files changed

+63
-380
lines changed

16 files changed

+63
-380
lines changed

clang/include/clang/AST/TypeProperties.td

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,8 @@ let Class = TagType in {
484484
let Read = [{ node->isDependentType() }];
485485
}
486486
def : Property<"declaration", DeclRef> {
487-
// We don't know which declaration was originally referenced here, and we
488-
// cannot reference a declaration that follows the use (because that can
489-
// introduce deserialization cycles), so conservatively generate a
490-
// reference to the first declaration.
491-
// FIXME: If this is a reference to a class template specialization, that
492-
// can still introduce a deserialization cycle.
487+
// Serializing a reference to the canonical declaration is apparently
488+
// necessary to make module-merging work.
493489
let Read = [{ node->getDecl()->getCanonicalDecl() }];
494490
}
495491
}

clang/include/clang/Basic/Attr.td

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,6 @@ def FunctionTmpl
126126
FunctionDecl::TK_FunctionTemplate}],
127127
"function templates">;
128128

129-
def ClassTmpl : SubsetSubject<CXXRecord, [{S->getDescribedClassTemplate()}],
130-
"class templates">;
131-
132129
// FIXME: this hack is needed because DeclNodes.td defines the base Decl node
133130
// type to be a class, not a definition. This makes it impossible to create an
134131
// attribute subject which accepts a Decl. Normally, this is not a problem,
@@ -2394,16 +2391,6 @@ def Pascal : DeclOrTypeAttr {
23942391
let Documentation = [Undocumented];
23952392
}
23962393

2397-
def PreferredName : InheritableAttr {
2398-
let Spellings = [Clang<"preferred_name", /*AllowInC*/0>];
2399-
let Subjects = SubjectList<[ClassTmpl]>;
2400-
let Args = [TypeArgument<"TypedefType">];
2401-
let Documentation = [PreferredNameDocs];
2402-
let InheritEvenIfAlreadyPresent = 1;
2403-
let MeaningfulToClassTemplateDefinition = 1;
2404-
let TemplateDependent = 1;
2405-
}
2406-
24072394
def PreserveMost : DeclOrTypeAttr {
24082395
let Spellings = [Clang<"preserve_most">];
24092396
let Documentation = [PreserveMostDocs];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4471,30 +4471,6 @@ the old mangled name and the new code will use the new mangled name with tags.
44714471
}];
44724472
}
44734473

4474-
def PreferredNameDocs : Documentation {
4475-
let Category = DocCatDecl;
4476-
let Content = [{
4477-
The ``preferred_name`` attribute can be applied to a class template, and
4478-
specifies a preferred way of naming a specialization of the template. The
4479-
preferred name will be used whenever the corresponding template specialization
4480-
would otherwise be printed in a diagnostic or similar context.
4481-
4482-
The preferred name must be a typedef or type alias declaration that refers to a
4483-
specialization of the class template (not including any type qualifiers). In
4484-
general this requires the template to be declared at least twice. For example:
4485-
4486-
.. code-block:: c++
4487-
4488-
template<typename T> struct basic_string;
4489-
using string = basic_string<char>;
4490-
using wstring = basic_string<wchar_t>;
4491-
template<typename T> struct [[clang::preferred_name(string),
4492-
clang::preferred_name(wstring)]] basic_string {
4493-
// ...
4494-
};
4495-
}];
4496-
}
4497-
44984474
def PreserveMostDocs : Documentation {
44994475
let Category = DocCatCallingConvs;
45004476
let Content = [{

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3941,9 +3941,6 @@ def note_protocol_decl : Note<
39413941
"protocol is declared here">;
39423942
def note_protocol_decl_undefined : Note<
39433943
"protocol %0 has no definition">;
3944-
def err_attribute_preferred_name_arg_invalid : Error<
3945-
"argument %0 to 'preferred_name' attribute is not a typedef for "
3946-
"a specialization of %1">;
39473944

39483945
// objc_designated_initializer attribute diagnostics.
39493946
def warn_objc_designated_init_missing_super_call : Warning<

clang/lib/AST/TypePrinter.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,15 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "clang/AST/PrettyPrinter.h"
1314
#include "clang/AST/ASTContext.h"
14-
#include "clang/AST/Attr.h"
1515
#include "clang/AST/Decl.h"
1616
#include "clang/AST/DeclBase.h"
1717
#include "clang/AST/DeclCXX.h"
1818
#include "clang/AST/DeclObjC.h"
1919
#include "clang/AST/DeclTemplate.h"
2020
#include "clang/AST/Expr.h"
2121
#include "clang/AST/NestedNameSpecifier.h"
22-
#include "clang/AST/PrettyPrinter.h"
2322
#include "clang/AST/TemplateBase.h"
2423
#include "clang/AST/TemplateName.h"
2524
#include "clang/AST/Type.h"
@@ -1349,19 +1348,6 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
13491348
}
13501349

13511350
void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
1352-
// Print the preferred name if we have one for this type.
1353-
if (const auto *Spec =
1354-
dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) {
1355-
for (const auto *PNA : Spec->getSpecializedTemplate()
1356-
->getTemplatedDecl()
1357-
->getMostRecentDecl()
1358-
->specific_attrs<PreferredNameAttr>()) {
1359-
if (declaresSameEntity(PNA->getTypedefType()->getAsCXXRecordDecl(), Spec))
1360-
return printTypeSpec(
1361-
PNA->getTypedefType()->castAs<TypedefType>()->getDecl(), OS);
1362-
}
1363-
}
1364-
13651351
printTag(T->getDecl(), OS);
13661352
}
13671353

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,43 +1380,6 @@ static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
13801380
S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL;
13811381
}
13821382

1383-
static void handlePreferredName(Sema &S, Decl *D, const ParsedAttr &AL) {
1384-
auto *RD = cast<CXXRecordDecl>(D);
1385-
ClassTemplateDecl *CTD = RD->getDescribedClassTemplate();
1386-
assert(CTD && "attribute does not appertain to this declaration");
1387-
1388-
ParsedType PT = AL.getTypeArg();
1389-
TypeSourceInfo *TSI = nullptr;
1390-
QualType T = S.GetTypeFromParser(PT, &TSI);
1391-
if (!TSI)
1392-
TSI = S.Context.getTrivialTypeSourceInfo(T, AL.getLoc());
1393-
1394-
if (!T.hasQualifiers() && T->getAs<TypedefType>()) {
1395-
// Find the template name, if this type names a template specialization.
1396-
const TemplateDecl *Template = nullptr;
1397-
if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
1398-
T->getAsCXXRecordDecl())) {
1399-
Template = CTSD->getSpecializedTemplate();
1400-
} else if (const auto *TST = T->getAs<TemplateSpecializationType>()) {
1401-
while (TST && TST->isTypeAlias())
1402-
TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
1403-
if (TST)
1404-
Template = TST->getTemplateName().getAsTemplateDecl();
1405-
}
1406-
1407-
if (Template && declaresSameEntity(Template, CTD)) {
1408-
D->addAttr(::new (S.Context) PreferredNameAttr(S.Context, AL, TSI));
1409-
return;
1410-
}
1411-
}
1412-
1413-
S.Diag(AL.getLoc(), diag::err_attribute_preferred_name_arg_invalid)
1414-
<< T << CTD;
1415-
if (const auto *TT = T->getAs<TypedefType>())
1416-
S.Diag(TT->getDecl()->getLocation(), diag::note_entity_declared_at)
1417-
<< TT->getDecl();
1418-
}
1419-
14201383
static bool checkIBOutletCommon(Sema &S, Decl *D, const ParsedAttr &AL) {
14211384
// The IBOutlet/IBOutletCollection attributes only apply to instance
14221385
// variables or properties of Objective-C classes. The outlet must also
@@ -7815,9 +7778,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
78157778
case ParsedAttr::AT_Packed:
78167779
handlePackedAttr(S, D, AL);
78177780
break;
7818-
case ParsedAttr::AT_PreferredName:
7819-
handlePreferredName(S, D, AL);
7820-
break;
78217781
case ParsedAttr::AT_Section:
78227782
handleSectionAttr(S, D, AL);
78237783
break;

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,15 +3792,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
37923792
Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext());
37933793
}
37943794

3795-
if (Decl->getSpecializationKind() == TSK_Undeclared &&
3796-
ClassTemplate->getTemplatedDecl()->hasAttrs()) {
3797-
InstantiatingTemplate Inst(*this, TemplateLoc, Decl);
3798-
if (!Inst.isInvalid()) {
3799-
MultiLevelTemplateArgumentList TemplateArgLists;
3800-
TemplateArgLists.addOuterTemplateArguments(Converted);
3801-
InstantiateAttrsForDecl(TemplateArgLists,
3802-
ClassTemplate->getTemplatedDecl(), Decl);
3803-
}
3795+
if (Decl->getSpecializationKind() == TSK_Undeclared) {
3796+
MultiLevelTemplateArgumentList TemplateArgLists;
3797+
TemplateArgLists.addOuterTemplateArguments(Converted);
3798+
InstantiateAttrsForDecl(TemplateArgLists, ClassTemplate->getTemplatedDecl(),
3799+
Decl);
38043800
}
38053801

38063802
// Diagnose uses of this specialization.

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -548,30 +548,12 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
548548
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
549549
}
550550

551-
/// Determine whether the attribute A might be relevent to the declaration D.
552-
/// If not, we can skip instantiating it. The attribute may or may not have
553-
/// been instantiated yet.
554-
static bool isRelevantAttr(Sema &S, const Decl *D, const Attr *A) {
555-
// Never instantiate preferred_name attributes; they're relevant only on the
556-
// template.
557-
if (const auto *PNA = dyn_cast<PreferredNameAttr>(A))
558-
return false;
559-
560-
return true;
561-
}
562-
563551
void Sema::InstantiateAttrsForDecl(
564552
const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl,
565553
Decl *New, LateInstantiatedAttrVec *LateAttrs,
566554
LocalInstantiationScope *OuterMostScope) {
567555
if (NamedDecl *ND = dyn_cast<NamedDecl>(New)) {
568-
// FIXME: This function is called multiple times for the same template
569-
// specialization. We should only instantiate attributes that were added
570-
// since the previous instantiation.
571556
for (const auto *TmplAttr : Tmpl->attrs()) {
572-
if (!isRelevantAttr(*this, New, TmplAttr))
573-
continue;
574-
575557
// FIXME: If any of the special case versions from InstantiateAttrs become
576558
// applicable to template declaration, we'll need to add them here.
577559
CXXThisScopeRAII ThisScope(
@@ -580,7 +562,7 @@ void Sema::InstantiateAttrsForDecl(
580562

581563
Attr *NewAttr = sema::instantiateTemplateAttributeForDecl(
582564
TmplAttr, Context, *this, TemplateArgs);
583-
if (NewAttr && isRelevantAttr(*this, New, NewAttr))
565+
if (NewAttr)
584566
New->addAttr(NewAttr);
585567
}
586568
}
@@ -605,9 +587,6 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
605587
LateInstantiatedAttrVec *LateAttrs,
606588
LocalInstantiationScope *OuterMostScope) {
607589
for (const auto *TmplAttr : Tmpl->attrs()) {
608-
if (!isRelevantAttr(*this, New, TmplAttr))
609-
continue;
610-
611590
// FIXME: This should be generalized to more than just the AlignedAttr.
612591
const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr);
613592
if (Aligned && Aligned->isAlignmentDependent()) {
@@ -730,7 +709,7 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
730709

731710
Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context,
732711
*this, TemplateArgs);
733-
if (NewAttr && isRelevantAttr(*this, New, TmplAttr))
712+
if (NewAttr)
734713
New->addAttr(NewAttr);
735714
}
736715
}

clang/test/PCH/decl-attrs.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

clang/test/SemaTemplate/attributes.cpp

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -63,63 +63,3 @@ namespace PR9049 {
6363
// CHECK: AnnotateAttr {{.*}} "ANNOTATE_BAR"
6464
template<typename T> [[clang::annotate("ANNOTATE_FOO"), clang::annotate("ANNOTATE_BAR")]] void HasAnnotations();
6565
void UseAnnotations() { HasAnnotations<int>(); }
66-
67-
namespace preferred_name {
68-
int x [[clang::preferred_name("frank")]]; // expected-error {{expected a type}}
69-
int y [[clang::preferred_name(int)]]; // expected-warning {{'preferred_name' attribute only applies to class templates}}
70-
struct [[clang::preferred_name(int)]] A; // expected-warning {{'preferred_name' attribute only applies to class templates}}
71-
template<typename T> struct [[clang::preferred_name(int)]] B; // expected-error {{argument 'int' to 'preferred_name' attribute is not a typedef for a specialization of 'B'}}
72-
template<typename T> struct C;
73-
using X = C<int>; // expected-note {{'X' declared here}}
74-
typedef C<float> Y;
75-
using Z = const C<double>; // expected-note {{'Z' declared here}}
76-
template<typename T> struct [[clang::preferred_name(C<int>)]] C; // expected-error {{argument 'C<int>' to 'preferred_name' attribute is not a typedef for a specialization of 'C'}}
77-
template<typename T> struct [[clang::preferred_name(X), clang::preferred_name(Y)]] C;
78-
template<typename T> struct [[clang::preferred_name(const X)]] C; // expected-error {{argument 'const preferred_name::X'}}
79-
template<typename T> struct [[clang::preferred_name(Z)]] C; // expected-error {{argument 'preferred_name::Z' (aka 'const C<double>')}}
80-
template<typename T> struct C {};
81-
82-
// CHECK: ClassTemplateDecl {{.*}} <line:[[@LINE-10]]:{{.*}} C
83-
// CHECK: ClassTemplateSpecializationDecl {{.*}} struct C definition
84-
// CHECK: TemplateArgument type 'int'
85-
// CHECK-NOT: PreferredNameAttr
86-
// CHECK: CXXRecordDecl
87-
// CHECK: ClassTemplateSpecializationDecl {{.*}} struct C definition
88-
// CHECK: TemplateArgument type 'float'
89-
// CHECK-NOT: PreferredNameAttr
90-
// CHECK: CXXRecordDecl
91-
// CHECK: ClassTemplateSpecializationDecl {{.*}} struct C definition
92-
// CHECK: TemplateArgument type 'double'
93-
// CHECK-NOT: PreferredNameAttr
94-
// CHECK: CXXRecordDecl
95-
96-
// Check this doesn't cause us to instantiate the same attribute multiple times.
97-
C<float> *cf1;
98-
C<float> *cf2;
99-
100-
void f(C<int> a, C<float> b, C<double> c) {
101-
auto p = a;
102-
auto q = b;
103-
auto r = c;
104-
p.f(); // expected-error {{no member named 'f' in 'preferred_name::X'}}
105-
q.f(); // expected-error {{no member named 'f' in 'preferred_name::Y'}}
106-
r.f(); // expected-error {{no member named 'f' in 'preferred_name::C<double>'}}
107-
}
108-
109-
template<typename T> struct D;
110-
using DInt = D<int>;
111-
template<typename T> struct __attribute__((__preferred_name__(DInt))) D {};
112-
template struct D<int>;
113-
int use_dint = D<int>().get(); // expected-error {{no member named 'get' in 'preferred_name::DInt'}}
114-
115-
template<typename T> struct MemberTemplate {
116-
template<typename U> struct Iter;
117-
using iterator = Iter<T>;
118-
using const_iterator = Iter<const T>;
119-
template<typename U>
120-
struct [[clang::preferred_name(iterator),
121-
clang::preferred_name(const_iterator)]] Iter {};
122-
};
123-
auto it = MemberTemplate<int>::Iter<const int>();
124-
int n = it; // expected-error {{no viable conversion from 'preferred_name::MemberTemplate<int>::Iter<const int>' to 'int'}}
125-
}

0 commit comments

Comments
 (0)