Skip to content

Commit 6dca33c

Browse files
authored
Check for mutability better (#127843)
This PR adds a function to determine if a type "looks" mutable. Since it's impossible to be totally sure if something can or can't be modified in C++, this makes a best-effort attempt to determine if variables of that type can be modified or not. The motivation for this change is the -Wunique-object-duplication warning, which had a false positive due to a missed case while checking for mutability. Pulling the logic into a separate function allows it to be written much more cleanly. There should be no behavior change, except that we no longer report function references to be mutable.
1 parent d2d1f14 commit 6dca33c

File tree

2 files changed

+22
-16
lines changed

2 files changed

+22
-16
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13441,6 +13441,23 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated(
1344113441
return true;
1344213442
}
1344313443

13444+
// Determine whether the object seems mutable for the purpose of diagnosing
13445+
// possible unique object duplication, i.e. non-const-qualified, and
13446+
// not an always-constant type like a function.
13447+
// Not perfect: doesn't account for mutable members, for example, or
13448+
// elements of container types.
13449+
// For nested pointers, any individual level being non-const is sufficient.
13450+
static bool looksMutable(QualType T, const ASTContext &Ctx) {
13451+
T = T.getNonReferenceType();
13452+
if (T->isFunctionType())
13453+
return false;
13454+
if (!T.isConstant(Ctx))
13455+
return true;
13456+
if (T->isPointerType())
13457+
return looksMutable(T->getPointeeType(), Ctx);
13458+
return false;
13459+
}
13460+
1344413461
void Sema::DiagnoseUniqueObjectDuplication(const VarDecl *VD) {
1344513462
// If this object has external linkage and hidden visibility, it might be
1344613463
// duplicated when built into a shared library, which causes problems if it's
@@ -13455,24 +13472,10 @@ void Sema::DiagnoseUniqueObjectDuplication(const VarDecl *VD) {
1345513472
!VD->isTemplated() &&
1345613473
GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) {
1345713474

13458-
// Check mutability. For pointers, ensure that both the pointer and the
13459-
// pointee are (recursively) const.
13460-
QualType Type = VD->getType().getNonReferenceType();
13461-
if (!Type.isConstant(VD->getASTContext())) {
13475+
QualType Type = VD->getType();
13476+
if (looksMutable(Type, VD->getASTContext())) {
1346213477
Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable)
1346313478
<< VD;
13464-
} else {
13465-
while (Type->isPointerType()) {
13466-
Type = Type->getPointeeType();
13467-
if (Type->isFunctionType())
13468-
break;
13469-
if (!Type.isConstant(VD->getASTContext())) {
13470-
Diag(VD->getLocation(),
13471-
diag::warn_possible_object_duplication_mutable)
13472-
<< VD;
13473-
break;
13474-
}
13475-
}
1347613479
}
1347713480

1347813481
// To keep false positives low, only warn if we're certain that the

clang/test/SemaCXX/unique_object_duplication.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ inline void has_thread_local() {
9999
thread_local int disallowedThreadLocal = 0; // hidden-warning {{'disallowedThreadLocal' may be duplicated when built into a shared library: it is mutable, has hidden visibility, and external linkage}}
100100
}
101101

102+
// Functions themselves are always immutable, so referencing them is okay
103+
inline auto& allowedFunctionReference = has_static_locals_external;
104+
102105
} // namespace StaticLocalTest
103106

104107
/******************************************************************************

0 commit comments

Comments
 (0)