From 999194739e3a2d35b5a1e563ba514cba8b4ab252 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 10 Jul 2010 12:30:03 +0000 Subject: [PATCH] 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 --- lib/Sema/SemaExpr.cpp | 21 ++++++++++-- test/SemaTemplate/self-comparison.cpp | 48 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 test/SemaTemplate/self-comparison.cpp diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a9a3b2c8ce..b907675b96 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(DC)) + return true; + if (FunctionDecl *FD = dyn_cast(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(LHSStripped)) + if (DeclRefExpr* DRL = dyn_cast(LHSStripped)) { if (DeclRefExpr* DRR = dyn_cast(RHSStripped)) { if (DRL->getDecl() == DRR->getDecl() && - !isa(DRL->getDecl())) { + !isa(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(LHSStripped)) LHSStripped = LHSStripped->IgnoreParenCasts(); diff --git a/test/SemaTemplate/self-comparison.cpp b/test/SemaTemplate/self-comparison.cpp new file mode 100644 index 0000000000..50ab660e65 --- /dev/null +++ b/test/SemaTemplate/self-comparison.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); +} +template struct S1 { + void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +template struct S2 { + template T foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +struct S3 { + template void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +template struct S4 { + template void foo() { + (void)(A == A); // expected-warning {{self-comparison always evaluates to true}} + (void)(A == B); + } +}; + +const int N = 42; +template 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(); + S3 s3; s3.foo<1, 1>(); + S4<1> s4; s4.foo<1>(); + foo2(); +} -- 2.40.0