[cfe-commits] r108044 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/SemaTemplate/self-comparison.cpp

Chandler Carruth chandlerc at gmail.com
Sat Jul 10 05:30:03 PDT 2010


Author: chandlerc
Date: Sat Jul 10 07:30:03 2010
New Revision: 108044

URL: http://llvm.org/viewvc/llvm-project?rev=108044&view=rev
Log:
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.

Added:
    cfe/trunk/test/SemaTemplate/self-comparison.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=108044&r1=108043&r2=108044&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sat Jul 10 07:30:03 2010
@@ -5292,6 +5292,16 @@
   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 @@
     // 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 @@
                                 << always_evals_to);
         }
       }
+    }
 
     if (isa<CastExpr>(LHSStripped))
       LHSStripped = LHSStripped->IgnoreParenCasts();

Added: cfe/trunk/test/SemaTemplate/self-comparison.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/self-comparison.cpp?rev=108044&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/self-comparison.cpp (added)
+++ cfe/trunk/test/SemaTemplate/self-comparison.cpp Sat Jul 10 07:30:03 2010
@@ -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>();
+}





More information about the cfe-commits mailing list