[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