Skip to content

Commit

Permalink
Revert "Warn when unique objects might be duplicated in shared librar…
Browse files Browse the repository at this point in the history
…ies (llvm#117622)"

There are some buildbot breakages, see the PR. Reverting for now.

This reverts commit d5684b8.
  • Loading branch information
zmodem committed Feb 3, 2025
1 parent d03b5de commit cdeeb39
Show file tree
Hide file tree
Showing 7 changed files with 0 additions and 323 deletions.
4 changes: 0 additions & 4 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ Attribute Changes in Clang
Improvements to Clang's diagnostics
-----------------------------------

- The ``-Wunique-object-duplication`` warning has been added to warn about objects
which are supposed to only exist once per program, but may get duplicated when
built into a shared library.

Improvements to Clang's time-trace
----------------------------------

Expand Down
30 changes: 0 additions & 30 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -694,36 +694,6 @@ def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess",
NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>;
def StaticInInline : DiagGroup<"static-in-inline">;
def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
def UniqueObjectDuplication : DiagGroup<"unique-object-duplication"> {
code Documentation = [{
Warns when objects which are supposed to be globally unique might get duplicated
when built into a shared library.

If an object with hidden visibility is built into a shared library, each instance
of the library will get its own copy. This can cause very subtle bugs if there was
only supposed to be one copy of the object in question: singletons aren't single,
changes to one object won't affect the others, the object's initializer will run
once per copy, etc.

Specifically, this warning fires when it detects an object which:
1. Appears in a header file (so it might get compiled into multiple libaries), and
2. Has external linkage (otherwise it's supposed to be duplicated), and
3. Has hidden visibility.

As well as one of the following:
1. The object is mutable, or
2. The object's initializer definitely has side effects.

The warning is best resolved by making the object ``const`` (if possible), or by explicitly
giving the object non-hidden visibility, e.g. using ``__attribute((visibility("default")))``.
Note that all levels of a pointer variable must be constant; ``const int*`` will
trigger the warning because the pointer itself is mutable.

This warning is currently disabled on Windows since it uses import/export rules
instead of visibility.
}];
}

def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
// Allow differentiation between GNU statement expressions in a macro versus
Expand Down
9 changes: 0 additions & 9 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -6167,15 +6167,6 @@ def warn_static_local_in_extern_inline : Warning<
def note_convert_inline_to_static : Note<
"use 'static' to give inline function %0 internal linkage">;

def warn_possible_object_duplication_mutable : Warning<
"%0 may be duplicated when built into a shared library: "
"it is mutable, has hidden visibility, and external linkage">,
InGroup<UniqueObjectDuplication>, DefaultIgnore;
def warn_possible_object_duplication_init : Warning<
"initializeation of %0 may run twice when built into a shared library: "
"it has hidden visibility and external linkage">,
InGroup<UniqueObjectDuplication>, DefaultIgnore;

def ext_redefinition_of_typedef : ExtWarn<
"redefinition of typedef %0 is a C11 feature">,
InGroup<DiagGroup<"typedef-redefinition"> >;
Expand Down
6 changes: 0 additions & 6 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3664,12 +3664,6 @@ class Sema final : public SemaBase {
NonTrivialCUnionContext UseContext,
unsigned NonTrivialKind);

/// Certain globally-unique variables might be accidentally duplicated if
/// built into multiple shared libraries with hidden visibility. This can
/// cause problems if the variable is mutable, its initialization is
/// effectful, or its address is taken.
bool GloballyUniqueObjectMightBeAccidentallyDuplicated(const VarDecl *Dcl);

/// AddInitializerToDecl - Adds the initializer Init to the
/// declaration dcl. If DirectInit is true, this is C++ direct
/// initialization rather than copy initialization.
Expand Down
101 changes: 0 additions & 101 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13380,62 +13380,6 @@ void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc,
.visit(QT, nullptr, false);
}

bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated(
const VarDecl *Dcl) {
if (!getLangOpts().CPlusPlus)
return false;

// We only need to warn if the definition is in a header file, so wait to
// diagnose until we've seen the definition.
if (!Dcl->isThisDeclarationADefinition())
return false;

// If an object is defined in a source file, its definition can't get
// duplicated since it will never appear in more than one TU.
if (Dcl->getASTContext().getSourceManager().isInMainFile(Dcl->getLocation()))
return false;

// If the variable we're looking at is a static local, then we actually care
// about the properties of the function containing it.
const ValueDecl *Target = Dcl;
// VarDecls and FunctionDecls have different functions for checking
// inline-ness, so we have to do it manually.
bool TargetIsInline = Dcl->isInline();

// Update the Target and TargetIsInline property if necessary
if (Dcl->isStaticLocal()) {
const DeclContext *Ctx = Dcl->getDeclContext();
if (!Ctx)
return false;

const FunctionDecl *FunDcl =
dyn_cast_if_present<FunctionDecl>(Ctx->getNonClosureAncestor());
if (!FunDcl)
return false;

Target = FunDcl;
// IsInlined() checks for the C++ inline property
TargetIsInline = FunDcl->isInlined();
}

// Non-inline variables can only legally appear in one TU
// FIXME: This also applies to templated variables, but that can rarely lead
// to false positives so templates are disabled for now.
if (!TargetIsInline)
return false;

// If the object isn't hidden, the dynamic linker will prevent duplication.
clang::LinkageInfo Lnk = Target->getLinkageAndVisibility();
if (Lnk.getVisibility() != HiddenVisibility)
return false;

// If the obj doesn't have external linkage, it's supposed to be duplicated.
if (!isExternalFormalLinkage(Lnk.getLinkage()))
return false;

return true;
}

void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
// If there is no declaration, there was an error parsing it. Just ignore
// the initializer.
Expand Down Expand Up @@ -14842,51 +14786,6 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
AddPushedVisibilityAttribute(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
// mutable (since the copies won't be in sync) or its initialization has side
// effects (since it will run once per copy instead of once globally)
// FIXME: Windows uses dllexport/dllimport instead of visibility, and we don't
// handle that yet. Disable the warning on Windows for now.
// FIXME: Checking templates can cause false positives if the template in
// question is never instantiated (e.g. only specialized templates are used).
if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
!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())) {
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
// initializer has side effects. Don't warn on operator new, since a mutable
// pointer will trigger the previous warning, and an immutable pointer
// getting duplicated just results in a little extra memory usage.
const Expr *Init = VD->getAnyInitializer();
if (Init &&
Init->HasSideEffects(VD->getASTContext(),
/*IncludePossibleEffects=*/false) &&
!isa<CXXNewExpr>(Init->IgnoreParenImpCasts())) {
Diag(Init->getExprLoc(), diag::warn_possible_object_duplication_init)
<< VD;
}
}

// FIXME: Warn on unused var template partial specializations.
if (VD->isFileVarDecl() && !isa<VarTemplatePartialSpecializationDecl>(VD))
MarkUnusedFileScopedDecl(VD);
Expand Down
16 changes: 0 additions & 16 deletions clang/test/SemaCXX/unique_object_duplication.cpp

This file was deleted.

157 changes: 0 additions & 157 deletions clang/test/SemaCXX/unique_object_duplication.h

This file was deleted.

0 comments on commit cdeeb39

Please sign in to comment.