if (DiagD->isReferenced()) {
Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
<< /*variable*/1 << DiagD->getDeclName();
- } else if (SourceMgr.isInMainFile(DiagD->getLocation())) {
- // If the declaration is in a header which is included into multiple
- // TUs, it will declare one variable per TU, and one of the other
- // variables may be used. So, only warn if the declaration is in the
- // main file.
+ } else {
Diag(DiagD->getLocation(), diag::warn_unused_variable)
<< DiagD->getDeclName();
}
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);
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;
}
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;
}
class B {
static A a;
+ static A b;
+ static const int x = sizeof(b);
};
}
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -Wno-c++11-extensions -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wunused -Wunused-member-function -std=c++11 %s
+#ifdef HEADER
+
+static void headerstatic() {} // expected-warning{{unused}}
+static inline void headerstaticinline() {}
+
+namespace {
+ void headeranon() {} // expected-warning{{unused}}
+ inline void headerinlineanon() {}
+}
+
+namespace test7
+{
+ template<typename T>
+ static inline void foo(T) { }
+
+ // This should not emit an unused-function warning since it inherits
+ // the static storage type from the base template.
+ template<>
+ inline void foo(int) { }
+
+ // Partial specialization
+ template<typename T, typename U>
+ static inline void bar(T, U) { }
+
+ template<typename U>
+ inline void bar(int, U) { }
+
+ template<>
+ inline void bar(int, int) { }
+};
+
+#else
+#define HEADER
+#include "warn-unused-filescoped.cpp"
+
static void f1(); // expected-warning{{unused}}
namespace {
void S::m3() { } // expected-warning{{unused}}
-static inline void f4() { }
-const unsigned int cx = 0;
+static inline void f4() { } // expected-warning{{unused}}
+const unsigned int cx = 0; // expected-warning{{unused}}
+const unsigned int cy = 0;
+int f5() { return cy; }
static int x1; // expected-warning{{unused}}
// FIXME: We should produce warnings for both of these.
static const int m = n;
int x = sizeof(m);
- static const double d = 0.0;
+ static const double d = 0.0; // expected-warning{{not needed and will not be emitted}}
int y = sizeof(d);
}
};
}
-namespace test7
-{
- template<typename T>
- static inline void foo(T) { }
-
- // This should not emit an unused-function warning since it inherits
- // the static storage type from the base template.
- template<>
- inline void foo(int) { }
-
- // Partial specialization
- template<typename T, typename U>
- static inline void bar(T, U) { }
-
- template<typename U>
- inline void bar(int, U) { }
-
- template<>
- inline void bar(int, int) { }
-};
-
namespace pr14776 {
namespace {
struct X {};
X a = X(); // expected-warning {{unused variable 'a'}}
auto b = X(); // expected-warning {{unused variable 'b'}}
}
+
+#endif