Make -Wunused warning rules more consistent.
This patch does a few different things.
This patch improves unused var diags for const vars: we no longer
unconditionally suppress diagnostics for const vars, instead only suppressing
the diagnostic when the declaration appears to be useful.
This patch also makes us more consistently use whether a variable/function
is declared in the main file to suppress diagnostics where appropriate.
Fixes <rdar://problem/14907887>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190382 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 34f7c46..36105e7 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1177,6 +1177,14 @@
return !D->isExternallyVisible();
}
+// FIXME: This needs to be refactored; some other isInMainFile users want
+// these semantics.
+static bool isMainFileLoc(const Sema &S, SourceLocation Loc) {
+ if (S.TUKind != TU_Complete)
+ return false;
+ return S.SourceMgr.isInMainFile(Loc);
+}
+
bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const {
assert(D);
@@ -1196,12 +1204,9 @@
if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD))
return false;
} else {
- // 'static inline' functions are used in headers; don't warn.
- // Make sure we get the storage class from the canonical declaration,
- // since otherwise we will get spurious warnings on specialized
- // static template functions.
- if (FD->getCanonicalDecl()->getStorageClass() == SC_Static &&
- FD->isInlineSpecified())
+ // 'static inline' functions are defined in headers; don't warn.
+ if (FD->isInlineSpecified() &&
+ !isMainFileLoc(*this, FD->getLocation()))
return false;
}
@@ -1209,21 +1214,26 @@
Context.DeclMustBeEmitted(FD))
return false;
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
- // Don't warn on variables of const-qualified or reference type, since their
- // values can be used even if though they're not odr-used, and because const
- // qualified variables can appear in headers in contexts where they're not
- // intended to be used.
- // FIXME: Use more principled rules for these exemptions.
- if (!VD->isFileVarDecl() ||
- VD->getType().isConstQualified() ||
- VD->getType()->isReferenceType() ||
- Context.DeclMustBeEmitted(VD))
+ // Constants and utility variables are defined in headers with internal
+ // linkage; don't warn. (Unlike functions, there isn't a convenient marker
+ // like "inline".)
+ if (!isMainFileLoc(*this, VD->getLocation()))
+ return false;
+
+ // If a variable usable in constant expressions is referenced,
+ // don't warn if it isn't used: if the value of a variable is required
+ // for the computation of a constant expression, it doesn't make sense to
+ // warn even if the variable isn't odr-used. (isReferenced doesn't
+ // precisely reflect that, but it's a decent approximation.)
+ if (VD->isReferenced() && VD->isUsableInConstantExpressions(Context))
+ return false;
+
+ if (Context.DeclMustBeEmitted(VD))
return false;
if (VD->isStaticDataMember() &&
VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
return false;
-
} else {
return false;
}