Skip to content

Commit d95344c

Browse files
committed
Move into separate function, call in CheckCompleteVariableDeclaration
1 parent ebd23f2 commit d95344c

File tree

2 files changed

+50
-45
lines changed

2 files changed

+50
-45
lines changed

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3669,6 +3669,7 @@ class Sema final : public SemaBase {
36693669
/// cause problems if the variable is mutable, its initialization is
36703670
/// effectful, or its address is taken.
36713671
bool GloballyUniqueObjectMightBeAccidentallyDuplicated(const VarDecl *Dcl);
3672+
void DiagnoseDangerousUniqueObjectDuplication(const VarDecl *Dcl);
36723673

36733674
/// AddInitializerToDecl - Adds the initializer Init to the
36743675
/// declaration dcl. If DirectInit is true, this is C++ direct

clang/lib/Sema/SemaDecl.cpp

Lines changed: 49 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13436,6 +13436,53 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated(
1343613436
return true;
1343713437
}
1343813438

13439+
void Sema::DiagnoseDangerousUniqueObjectDuplication(const VarDecl* VD) {
13440+
// If this object has external linkage and hidden visibility, it might be
13441+
// duplicated when built into a shared library, which causes problems if it's
13442+
// mutable (since the copies won't be in sync) or its initialization has side
13443+
// effects (since it will run once per copy instead of once globally)
13444+
// FIXME: Windows uses dllexport/dllimport instead of visibility, and we don't
13445+
// handle that yet. Disable the warning on Windows for now.
13446+
// FIXME: Checking templates can cause false positives if the template in
13447+
// question is never instantiated (e.g. only specialized templates are used).
13448+
if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
13449+
!VD->isTemplated() &&
13450+
GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) {
13451+
// Check mutability. For pointers, ensure that both the pointer and the
13452+
// pointee are (recursively) const.
13453+
QualType Type = VD->getType().getNonReferenceType();
13454+
if (!Type.isConstant(VD->getASTContext())) {
13455+
Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable)
13456+
<< VD;
13457+
} else {
13458+
while (Type->isPointerType()) {
13459+
Type = Type->getPointeeType();
13460+
if (Type->isFunctionType())
13461+
break;
13462+
if (!Type.isConstant(VD->getASTContext())) {
13463+
Diag(VD->getLocation(),
13464+
diag::warn_possible_object_duplication_mutable)
13465+
<< VD;
13466+
break;
13467+
}
13468+
}
13469+
}
13470+
13471+
// To keep false positives low, only warn if we're certain that the
13472+
// initializer has side effects. Don't warn on operator new, since a mutable
13473+
// pointer will trigger the previous warning, and an immutable pointer
13474+
// getting duplicated just results in a little extra memory usage.
13475+
const Expr *Init = VD->getAnyInitializer();
13476+
if (Init &&
13477+
Init->HasSideEffects(VD->getASTContext(),
13478+
/*IncludePossibleEffects=*/false) &&
13479+
!isa<CXXNewExpr>(Init->IgnoreParenImpCasts())) {
13480+
Diag(Init->getExprLoc(), diag::warn_possible_object_duplication_init)
13481+
<< VD;
13482+
}
13483+
}
13484+
}
13485+
1343913486
void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
1344013487
// If there is no declaration, there was an error parsing it. Just ignore
1344113488
// the initializer.
@@ -14655,6 +14702,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
1465514702
return;
1465614703
}
1465714704

14705+
DiagnoseDangerousUniqueObjectDuplication(var);
14706+
1465814707
// Require the destructor.
1465914708
if (!type->isDependentType())
1466014709
if (const RecordType *recordType = baseType->getAs<RecordType>())
@@ -14842,51 +14891,6 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
1484214891
if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible())
1484314892
AddPushedVisibilityAttribute(VD);
1484414893

14845-
// If this object has external linkage and hidden visibility, it might be
14846-
// duplicated when built into a shared library, which causes problems if it's
14847-
// mutable (since the copies won't be in sync) or its initialization has side
14848-
// effects (since it will run once per copy instead of once globally)
14849-
// FIXME: Windows uses dllexport/dllimport instead of visibility, and we don't
14850-
// handle that yet. Disable the warning on Windows for now.
14851-
// FIXME: Checking templates can cause false positives if the template in
14852-
// question is never instantiated (e.g. only specialized templates are used).
14853-
if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() &&
14854-
!VD->isTemplated() &&
14855-
GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) {
14856-
// Check mutability. For pointers, ensure that both the pointer and the
14857-
// pointee are (recursively) const.
14858-
QualType Type = VD->getType().getNonReferenceType();
14859-
if (!Type.isConstant(VD->getASTContext())) {
14860-
Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable)
14861-
<< VD;
14862-
} else {
14863-
while (Type->isPointerType()) {
14864-
Type = Type->getPointeeType();
14865-
if (Type->isFunctionType())
14866-
break;
14867-
if (!Type.isConstant(VD->getASTContext())) {
14868-
Diag(VD->getLocation(),
14869-
diag::warn_possible_object_duplication_mutable)
14870-
<< VD;
14871-
break;
14872-
}
14873-
}
14874-
}
14875-
14876-
// To keep false positives low, only warn if we're certain that the
14877-
// initializer has side effects. Don't warn on operator new, since a mutable
14878-
// pointer will trigger the previous warning, and an immutable pointer
14879-
// getting duplicated just results in a little extra memory usage.
14880-
const Expr *Init = VD->getAnyInitializer();
14881-
if (Init &&
14882-
Init->HasSideEffects(VD->getASTContext(),
14883-
/*IncludePossibleEffects=*/false) &&
14884-
!isa<CXXNewExpr>(Init->IgnoreParenImpCasts())) {
14885-
Diag(Init->getExprLoc(), diag::warn_possible_object_duplication_init)
14886-
<< VD;
14887-
}
14888-
}
14889-
1489014894
// FIXME: Warn on unused var template partial specializations.
1489114895
if (VD->isFileVarDecl() && !isa<VarTemplatePartialSpecializationDecl>(VD))
1489214896
MarkUnusedFileScopedDecl(VD);

0 commit comments

Comments
 (0)