@@ -1071,24 +1071,37 @@ static bool ensureDeclared(Sema &S, QualType QT, SourceLocation SpecLoc) {
1071
1071
1072
1072
static bool isReflectableDecl (ASTContext &C, const Decl *D) {
1073
1073
assert (D && " null declaration" );
1074
- if (isa<AccessSpecDecl>(D) || isa<EmptyDecl>(D) || isa<FriendDecl>(D))
1075
- return false ;
1074
+
1076
1075
if (isa<NamespaceAliasDecl>(D))
1077
1076
return true ;
1077
+
1078
+ if (!isa<VarDecl, FunctionDecl, TypeDecl, FieldDecl, TemplateDecl,
1079
+ NamespaceDecl, NamespaceAliasDecl, TranslationUnitDecl>(D))
1080
+ return false ;
1081
+
1078
1082
if (auto *Class = dyn_cast<CXXRecordDecl>(D))
1079
1083
if (Class->isInjectedClassName ())
1080
1084
return false ;
1081
- if (isa<StaticAssertDecl>(D))
1082
- return false ;
1083
1085
1084
1086
return D->getCanonicalDecl () == D;
1085
1087
}
1086
1088
1087
1089
// / Filter non-reflectable members.
1088
1090
static Decl *findIterableMember (ASTContext &C, Decl *D, bool Inclusive) {
1089
- if (!D || (Inclusive && isReflectableDecl (C, D)) )
1091
+ if (!D)
1090
1092
return D;
1091
1093
1094
+ if (Inclusive) {
1095
+ if (isReflectableDecl (C, D))
1096
+ return D;
1097
+
1098
+ // Handle the case where the first Decl is a LinkageSpecDecl.
1099
+ if (auto *LSDecl = dyn_cast_or_null<LinkageSpecDecl>(D)) {
1100
+ Decl *RecD = findIterableMember (C, *LSDecl->decls_begin (), true );
1101
+ if (RecD) return RecD;
1102
+ }
1103
+ }
1104
+
1092
1105
do {
1093
1106
DeclContext *DC = D->getDeclContext ();
1094
1107
@@ -1100,17 +1113,30 @@ static Decl *findIterableMember(ASTContext &C, Decl *D, bool Inclusive) {
1100
1113
// declarations whose DeclContext is different from the previous Decl;
1101
1114
// otherwise, we may inadvertently break the chain of redeclarations in
1102
1115
// difficult to predit ways.
1103
- D = D-> getNextDeclInContext ();
1104
- while (D && D->getDeclContext () != DC)
1105
- D = D->getNextDeclInContext ( );
1116
+ do {
1117
+ D = D->getNextDeclInContext ();
1118
+ } while (D && D->getDeclContext () != DC );
1106
1119
1120
+ // In the case of namespaces, walk the redeclaration chain.
1107
1121
if (auto *NSDecl = dyn_cast<NamespaceDecl>(DC)) {
1108
1122
while (!D && NSDecl) {
1109
1123
NSDecl = NSDecl->getPreviousDecl ();
1110
1124
D = NSDecl ? *NSDecl->decls_begin () : nullptr ;
1111
1125
}
1112
1126
}
1127
+
1128
+ // We need to recursively descend into LinkageSpecDecls to iterate over the
1129
+ // members declared therein (e.g., `extern "C"` blocks).
1130
+ if (auto *LSDecl = dyn_cast_or_null<LinkageSpecDecl>(D)) {
1131
+ Decl *RecD = findIterableMember (C, *LSDecl->decls_begin (), true );
1132
+ if (RecD) return RecD;
1133
+ }
1134
+
1135
+ // Pop back out of a recursively entered LinkageSpecDecl.
1136
+ if (!D && isa<LinkageSpecDecl>(DC))
1137
+ return findIterableMember (C, cast<Decl>(DC), false );
1113
1138
} while (D && !isReflectableDecl (C, D));
1139
+
1114
1140
return D;
1115
1141
}
1116
1142
0 commit comments