Skip to content

Commit 52690db

Browse files
authored
[clang] Fix -Wdangling false negative regressions caused by 117315 (#118088)
A specialization declaration can have an attribute even if the primary template does not, particularly when the specialization is instantiated from an annotated using-alias declaration. Fix #118064
1 parent 2dc0de7 commit 52690db

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,27 @@ template <typename T> static bool isRecordWithAttr(QualType Type) {
258258
auto *RD = Type->getAsCXXRecordDecl();
259259
if (!RD)
260260
return false;
261+
// Generally, if a primary template class declaration is annotated with an
262+
// attribute, all its specializations generated from template instantiations
263+
// should inherit the attribute.
264+
//
265+
// However, since lifetime analysis occurs during parsing, we may encounter
266+
// cases where a full definition of the specialization is not required. In
267+
// such cases, the specialization declaration remains incomplete and lacks the
268+
// attribute. Therefore, we fall back to checking the primary template class.
269+
//
270+
// Note: it is possible for a specialization declaration to have an attribute
271+
// even if the primary template does not.
272+
//
273+
// FIXME: What if the primary template and explicit specialization
274+
// declarations have conflicting attributes? We should consider diagnosing
275+
// this scenario.
276+
bool Result = RD->hasAttr<T>();
277+
261278
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
262-
RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
263-
return RD->hasAttr<T>();
279+
Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
280+
281+
return Result;
264282
}
265283

266284
bool isPointerLikeType(QualType QT) {

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,3 +670,26 @@ void test13() {
670670
}
671671

672672
} // namespace GH100526
673+
674+
namespace std {
675+
template <typename T>
676+
class __set_iterator {};
677+
678+
template<typename T>
679+
struct BB {
680+
typedef __set_iterator<T> iterator;
681+
};
682+
683+
template <typename T>
684+
class set {
685+
public:
686+
typedef typename BB<T>::iterator iterator;
687+
iterator begin() const;
688+
};
689+
} // namespace std
690+
namespace GH118064{
691+
692+
void test() {
693+
auto y = std::set<int>{}.begin(); // expected-warning {{object backing the pointer}}
694+
}
695+
} // namespace GH118064

0 commit comments

Comments
 (0)