Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13440,6 +13440,23 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated(
return true;
}

// Determine whether the object seems mutable for the purpose of diagnosing
// possible unique object duplication, i.e. non-const-qualified, and
// not an always-constant type like a function.
// Not perfect: doesn't account for mutable members, for example, or
// elements of container types.
// For nested pointers, any individual level being non-const is sufficient.
bool looksMutable(QualType T, const ASTContext &Ctx) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: make it static since it's local to this file

T = T.getNonReferenceType();
if (T->isFunctionType())
return false;
if (!T.isConstant(Ctx))
return true;
if (T->isPointerType())
return looksMutable(T->getPointeeType(), Ctx);
return false;
}

void Sema::DiagnoseUniqueObjectDuplication(const VarDecl *VD) {
// If this object has external linkage and hidden visibility, it might be
// duplicated when built into a shared library, which causes problems if it's
Expand All @@ -13454,24 +13471,10 @@ void Sema::DiagnoseUniqueObjectDuplication(const VarDecl *VD) {
!VD->isTemplated() &&
GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) {

// Check mutability. For pointers, ensure that both the pointer and the
// pointee are (recursively) const.
QualType Type = VD->getType().getNonReferenceType();
if (!Type.isConstant(VD->getASTContext())) {
QualType Type = VD->getType();
if (looksMutable(Type, VD->getASTContext())) {
Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable)
<< VD;
} else {
while (Type->isPointerType()) {
Type = Type->getPointeeType();
if (Type->isFunctionType())
break;
if (!Type.isConstant(VD->getASTContext())) {
Diag(VD->getLocation(),
diag::warn_possible_object_duplication_mutable)
<< VD;
break;
}
}
}

// To keep false positives low, only warn if we're certain that the
Expand Down
3 changes: 3 additions & 0 deletions clang/test/SemaCXX/unique_object_duplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ inline void has_thread_local() {
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}}
}

// Functions themselves are always immutable, so referencing them is okay
inline auto& allowedFunctionReference = has_static_locals_external;

} // namespace StaticLocalTest

/******************************************************************************
Expand Down