mirror of https://github.com/microsoft/clang.git
Lay the ground work for resoving PR7047. This doesn't actually fix it because
default arguments to template parameters don't have a DeclContext when instantiated, and so we can't detect that we're in an instantiation context as opposed to the definition context. However, it fixes the more commonly-occuring cases in TMP code that use devolve to this type of tautology after substitution. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108044 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6d00c1365d
commit
999194739e
|
@ -5292,6 +5292,16 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
|||
return LHSTy;
|
||||
}
|
||||
|
||||
static bool IsWithinTemplateSpecialization(Decl *D) {
|
||||
if (DeclContext *DC = D->getDeclContext()) {
|
||||
if (isa<ClassTemplateSpecializationDecl>(DC))
|
||||
return true;
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
|
||||
return FD->isFunctionTemplateSpecialization();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// C99 6.5.8, C++ [expr.rel]
|
||||
QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
||||
unsigned OpaqueOpc, bool isRelational) {
|
||||
|
@ -5310,13 +5320,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
|||
// x == x, x != x, x < x, etc. These always evaluate to a constant, and
|
||||
// often indicate logic errors in the program.
|
||||
// NOTE: Don't warn about comparisons of enum constants. These can arise
|
||||
// from macro expansions, and are usually quite deliberate.
|
||||
// from macro expansions, and are usually quite deliberate. Also don't
|
||||
// warn about comparisons which are only self comparisons within
|
||||
// a template specialization. The warnings should catch obvious cases in
|
||||
// the definition of the template anyways.
|
||||
Expr *LHSStripped = lex->IgnoreParens();
|
||||
Expr *RHSStripped = rex->IgnoreParens();
|
||||
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped))
|
||||
if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) {
|
||||
if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) {
|
||||
if (DRL->getDecl() == DRR->getDecl() &&
|
||||
!isa<EnumConstantDecl>(DRL->getDecl())) {
|
||||
!isa<EnumConstantDecl>(DRL->getDecl()) &&
|
||||
!IsWithinTemplateSpecialization(DRL->getDecl())) {
|
||||
DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always)
|
||||
<< 0 // self-
|
||||
<< (Opc == BinaryOperator::EQ
|
||||
|
@ -5344,6 +5358,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
|||
<< always_evals_to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isa<CastExpr>(LHSStripped))
|
||||
LHSStripped = LHSStripped->IgnoreParenCasts();
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
template <int A, int B> void foo() {
|
||||
(void)(A == A); // expected-warning {{self-comparison always evaluates to true}}
|
||||
(void)(A == B);
|
||||
}
|
||||
template <int A, int B> struct S1 {
|
||||
void foo() {
|
||||
(void)(A == A); // expected-warning {{self-comparison always evaluates to true}}
|
||||
(void)(A == B);
|
||||
}
|
||||
};
|
||||
|
||||
template <int A, int B> struct S2 {
|
||||
template <typename T> T foo() {
|
||||
(void)(A == A); // expected-warning {{self-comparison always evaluates to true}}
|
||||
(void)(A == B);
|
||||
}
|
||||
};
|
||||
|
||||
struct S3 {
|
||||
template <int A, int B> void foo() {
|
||||
(void)(A == A); // expected-warning {{self-comparison always evaluates to true}}
|
||||
(void)(A == B);
|
||||
}
|
||||
};
|
||||
|
||||
template <int A> struct S4 {
|
||||
template <int B> void foo() {
|
||||
(void)(A == A); // expected-warning {{self-comparison always evaluates to true}}
|
||||
(void)(A == B);
|
||||
}
|
||||
};
|
||||
|
||||
const int N = 42;
|
||||
template <int X> void foo2() {
|
||||
(void)(X == N);
|
||||
(void)(N == X);
|
||||
}
|
||||
|
||||
void test() {
|
||||
foo<1, 1>();
|
||||
S1<1, 1> s1; s1.foo();
|
||||
S2<1, 1> s2; s2.foo<void>();
|
||||
S3 s3; s3.foo<1, 1>();
|
||||
S4<1> s4; s4.foo<1>();
|
||||
foo2<N>();
|
||||
}
|
Loading…
Reference in New Issue