forked from OSchip/llvm-project
Don't warn on "use" of undefined inline function that isn't actually an ODR
use. In order for this to fire, the function needed to be a templated function marked 'constexpr' and declared but not defined. This weird pattern appears in libstdc++'s alloc_traits.h. llvm-svn: 264471
This commit is contained in:
parent
27fa77e102
commit
0e32c5283a
|
@ -3593,9 +3593,15 @@ public:
|
|||
// for expressions referring to a decl; these exist because odr-use marking
|
||||
// needs to be delayed for some constant variables when we build one of the
|
||||
// named expressions.
|
||||
void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse);
|
||||
//
|
||||
// MightBeOdrUse indicates whether the use could possibly be an odr-use, and
|
||||
// should usually be true. This only needs to be set to false if the lack of
|
||||
// odr-use cannot be determined from the current context (for instance,
|
||||
// because the name denotes a virtual function and was written without an
|
||||
// explicit nested-name-specifier).
|
||||
void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse);
|
||||
void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
||||
bool OdrUse = true);
|
||||
bool MightBeOdrUse = true);
|
||||
void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
|
||||
void MarkDeclRefReferenced(DeclRefExpr *E);
|
||||
void MarkMemberReferenced(MemberExpr *E);
|
||||
|
|
|
@ -12770,7 +12770,7 @@ static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) {
|
|||
/// \brief Mark a function referenced, and check whether it is odr-used
|
||||
/// (C++ [basic.def.odr]p2, C99 6.9p3)
|
||||
void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
||||
bool OdrUse) {
|
||||
bool MightBeOdrUse) {
|
||||
assert(Func && "No function?");
|
||||
|
||||
Func->setReferenced();
|
||||
|
@ -12783,8 +12783,8 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
|||
// We (incorrectly) mark overload resolution as an unevaluated context, so we
|
||||
// can just check that here. Skip the rest of this function if we've already
|
||||
// marked the function as used.
|
||||
if (Func->isUsed(/*CheckUsedAttr=*/false) ||
|
||||
!IsPotentiallyEvaluatedContext(*this)) {
|
||||
bool OdrUse = MightBeOdrUse && IsPotentiallyEvaluatedContext(*this);
|
||||
if (Func->isUsed(/*CheckUsedAttr=*/false) || !OdrUse) {
|
||||
// C++11 [temp.inst]p3:
|
||||
// Unless a function template specialization has been explicitly
|
||||
// instantiated or explicitly specialized, the function template
|
||||
|
@ -12873,8 +12873,6 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
|||
if (FPT && isUnresolvedExceptionSpec(FPT->getExceptionSpecType()))
|
||||
ResolveExceptionSpec(Loc, FPT);
|
||||
|
||||
if (!OdrUse) return;
|
||||
|
||||
// Implicit instantiation of function templates and member functions of
|
||||
// class templates.
|
||||
if (Func->isImplicitlyInstantiable()) {
|
||||
|
@ -12922,10 +12920,12 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func,
|
|||
// Walk redefinitions, as some of them may be instantiable.
|
||||
for (auto i : Func->redecls()) {
|
||||
if (!i->isUsed(false) && i->isImplicitlyInstantiable())
|
||||
MarkFunctionReferenced(Loc, i);
|
||||
MarkFunctionReferenced(Loc, i, OdrUse);
|
||||
}
|
||||
}
|
||||
|
||||
if (!OdrUse) return;
|
||||
|
||||
// Keep track of used but undefined functions.
|
||||
if (!Func->isDefined()) {
|
||||
if (mightHaveNonExternalLinkage(Func))
|
||||
|
@ -13800,13 +13800,13 @@ void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
|
|||
}
|
||||
|
||||
static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
|
||||
Decl *D, Expr *E, bool OdrUse) {
|
||||
Decl *D, Expr *E, bool MightBeOdrUse) {
|
||||
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||
DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
|
||||
return;
|
||||
}
|
||||
|
||||
SemaRef.MarkAnyDeclReferenced(Loc, D, OdrUse);
|
||||
SemaRef.MarkAnyDeclReferenced(Loc, D, MightBeOdrUse);
|
||||
|
||||
// If this is a call to a method via a cast, also mark the method in the
|
||||
// derived class used in case codegen can devirtualize the call.
|
||||
|
@ -13828,7 +13828,7 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
|
|||
CXXMethodDecl *DM = MD->getCorrespondingMethodInClass(MostDerivedClassDecl);
|
||||
if (!DM || DM->isPure())
|
||||
return;
|
||||
SemaRef.MarkAnyDeclReferenced(Loc, DM, OdrUse);
|
||||
SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse);
|
||||
}
|
||||
|
||||
/// \brief Perform reference-marking and odr-use handling for a DeclRefExpr.
|
||||
|
@ -13851,30 +13851,31 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
|
|||
// overload resolution when referred to from a potentially-evaluated
|
||||
// expression, is odr-used, unless it is a pure virtual function and its
|
||||
// name is not explicitly qualified.
|
||||
bool OdrUse = true;
|
||||
bool MightBeOdrUse = true;
|
||||
if (E->performsVirtualDispatch(getLangOpts())) {
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl()))
|
||||
if (Method->isPure())
|
||||
OdrUse = false;
|
||||
MightBeOdrUse = false;
|
||||
}
|
||||
SourceLocation Loc = E->getMemberLoc().isValid() ?
|
||||
E->getMemberLoc() : E->getLocStart();
|
||||
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, OdrUse);
|
||||
MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, MightBeOdrUse);
|
||||
}
|
||||
|
||||
/// \brief Perform marking for a reference to an arbitrary declaration. It
|
||||
/// marks the declaration referenced, and performs odr-use checking for
|
||||
/// functions and variables. This method should not be used when building a
|
||||
/// normal expression which refers to a variable.
|
||||
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) {
|
||||
if (OdrUse) {
|
||||
void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D,
|
||||
bool MightBeOdrUse) {
|
||||
if (MightBeOdrUse) {
|
||||
if (auto *VD = dyn_cast<VarDecl>(D)) {
|
||||
MarkVariableReferenced(Loc, VD);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
MarkFunctionReferenced(Loc, FD, OdrUse);
|
||||
MarkFunctionReferenced(Loc, FD, MightBeOdrUse);
|
||||
return;
|
||||
}
|
||||
D->setReferenced();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -triple i686-pc-win32 -verify %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -triple i686-pc-win32 -verify -std=c++11 %s
|
||||
// PR14993
|
||||
|
||||
namespace test1 {
|
||||
|
@ -61,3 +61,8 @@ namespace test11 {
|
|||
inline void bar() __attribute__((dllimport));
|
||||
void test() { foo(); bar(); }
|
||||
}
|
||||
|
||||
namespace test12 {
|
||||
template<typename> constexpr int _S_chk(int *);
|
||||
decltype(_S_chk<int>(nullptr)) n;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue