jdenny updated this revision to Diff 125640.
jdenny edited the summary of this revision.
jdenny added a comment.
This update includes all of Hal's suggestions.
I'm also thinking of converting prefix storage from a std::vector to a std::map
so that lookup should be faster during parsing.
https://reviews.llvm.org/D39694
Files:
include/clang/Basic/DiagnosticDriverKinds.td
include/clang/Basic/DiagnosticOptions.h
include/clang/Driver/CC1Options.td
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/VerifyDiagnosticConsumer.cpp
test/Frontend/verify-prefixes.c
test/Sema/tautological-constant-compare.c
test/Sema/tautological-constant-enum-compare.c
test/Sema/tautological-unsigned-enum-zero-compare.c
test/Sema/tautological-unsigned-enum-zero-compare.cpp
test/Sema/tautological-unsigned-zero-compare.c
Index: test/Sema/tautological-unsigned-zero-compare.c
===================================================================
--- test/Sema/tautological-unsigned-zero-compare.c
+++ test/Sema/tautological-unsigned-zero-compare.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -fsyntax-only -DTEST -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify %s
-// RUN: %clang_cc1 -fsyntax-only -DTEST -verify -x c++ %s
-// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify=silence %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-unsigned-zero-compare -verify=silence -x c++ %s
unsigned uvalue(void);
signed int svalue(void);
@@ -13,13 +13,8 @@
void TFunc() {
// Make sure that we do warn for normal variables in template functions !
unsigned char c = svalue();
-#ifdef TEST
if (c < 0) // expected-warning {{comparison of unsigned expression < 0 is always false}}
return;
-#else
- if (c < 0)
- return;
-#endif
if (c < macro(0))
return;
@@ -39,7 +34,8 @@
unsigned un = uvalue();
-#ifdef TEST
+ // silence-no-diagnostics
+
if (un == 0)
return 0;
if (un != 0)
@@ -91,65 +87,10 @@
return 0;
if (0UL >= un)
return 0;
-#else
-// expected-no-diagnostics
- if (un == 0)
- return 0;
- if (un != 0)
- return 0;
- if (un < 0)
- return 0;
- if (un <= 0)
- return 0;
- if (un > 0)
- return 0;
- if (un >= 0)
- return 0;
-
- if (0 == un)
- return 0;
- if (0 != un)
- return 0;
- if (0 < un)
- return 0;
- if (0 <= un)
- return 0;
- if (0 > un)
- return 0;
- if (0 >= un)
- return 0;
-
- if (un == 0UL)
- return 0;
- if (un != 0UL)
- return 0;
- if (un < 0UL)
- return 0;
- if (un <= 0UL)
- return 0;
- if (un > 0UL)
- return 0;
- if (un >= 0UL)
- return 0;
-
- if (0UL == un)
- return 0;
- if (0UL != un)
- return 0;
- if (0UL < un)
- return 0;
- if (0UL <= un)
- return 0;
- if (0UL > un)
- return 0;
- if (0UL >= un)
- return 0;
-#endif
signed int a = svalue();
-#ifdef TEST
if (a == 0)
return 0;
if (a != 0)
@@ -201,60 +142,6 @@
return 0;
if (0UL >= a)
return 0;
-#else
-// expected-no-diagnostics
- if (a == 0)
- return 0;
- if (a != 0)
- return 0;
- if (a < 0)
- return 0;
- if (a <= 0)
- return 0;
- if (a > 0)
- return 0;
- if (a >= 0)
- return 0;
-
- if (0 == a)
- return 0;
- if (0 != a)
- return 0;
- if (0 < a)
- return 0;
- if (0 <= a)
- return 0;
- if (0 > a)
- return 0;
- if (0 >= a)
- return 0;
-
- if (a == 0UL)
- return 0;
- if (a != 0UL)
- return 0;
- if (a < 0UL)
- return 0;
- if (a <= 0UL)
- return 0;
- if (a > 0UL)
- return 0;
- if (a >= 0UL)
- return 0;
-
- if (0UL == a)
- return 0;
- if (0UL != a)
- return 0;
- if (0UL < a)
- return 0;
- if (0UL <= a)
- return 0;
- if (0UL > a)
- return 0;
- if (0UL >= a)
- return 0;
-#endif
float fl = 0;
Index: test/Sema/tautological-unsigned-enum-zero-compare.cpp
===================================================================
--- test/Sema/tautological-unsigned-enum-zero-compare.cpp
+++ test/Sema/tautological-unsigned-enum-zero-compare.cpp
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
-// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
-// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only -DSILENCE -Wno-tautological-unsigned-enum-zero-compare -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-linux-gnu -fsyntax-only \
+// RUN: -verify=unsigned,unsigned-signed,expected %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -verify=unsigned-signed,signed-silence,expected %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -Wno-tautological-unsigned-enum-zero-compare \
+// RUN: -verify=signed-silence,expected %s
// Okay, this is where it gets complicated.
// Then default enum sigdness is target-specific.
@@ -16,71 +20,70 @@
enum C : signed { C_foo = 0, C_bar, };
enum C c;
-#ifdef UNSIGNED
- if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (a < 0) // unsigned-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
- if (0 >= a)
+ if (0 >= a) // signed-silence-warning {{comparison 0 >= 'enum A' is always true}}
return 0;
- if (a > 0)
+ if (a > 0) // signed-silence-warning {{comparison 'enum A' > 0 is always false}}
return 0;
- if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (0 <= a) // unsigned-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
- if (a <= 0)
+ if (a <= 0) // signed-silence-warning {{comparison 'enum A' <= 0 is always true}}
return 0;
- if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (0 > a) // unsigned-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (a >= 0) // unsigned-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
- if (0 < a)
+ if (0 < a) // signed-silence-warning {{comparison 0 < 'enum A' is always false}}
return 0;
- if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (a < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= a)
return 0;
if (a > 0U)
return 0;
- if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (0U <= a) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (a <= 0U)
return 0;
- if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (0U > a) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (a >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < a)
return 0;
- if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (b < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0 >= b)
return 0;
if (b > 0)
return 0;
- if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (0 <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (b <= 0)
return 0;
- if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (0 > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (b >= 0) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0 < b)
return 0;
- if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (b < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= b)
return 0;
if (b > 0U)
return 0;
- if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (0U <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (b <= 0U)
return 0;
- if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (0U > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (b >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < b)
return 0;
@@ -102,227 +105,22 @@
if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
return 0;
- if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
+ if (c < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= c)
return 0;
if (c > 0U)
return 0;
- if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
+ if (0U <= c) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (c <= 0U)
return 0;
- if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
+ if (0U > c) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
+ if (c >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < c)
return 0;
-#elif defined(SIGNED)
- if (a < 0)
- return 0;
- if (0 >= a) // expected-warning {{comparison 0 >= 'enum A' is always true}}
- return 0;
- if (a > 0) // expected-warning {{comparison 'enum A' > 0 is always false}}
- return 0;
- if (0 <= a)
- return 0;
- if (a <= 0) // expected-warning {{comparison 'enum A' <= 0 is always true}}
- return 0;
- if (0 > a)
- return 0;
- if (a >= 0)
- return 0;
- if (0 < a) // expected-warning {{comparison 0 < 'enum A' is always false}}
- return 0;
-
- if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= a)
- return 0;
- if (a > 0U)
- return 0;
- if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (a <= 0U)
- return 0;
- if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < a)
- return 0;
-
- if (b < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0 >= b)
- return 0;
- if (b > 0)
- return 0;
- if (0 <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (b <= 0)
- return 0;
- if (0 > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (b >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0 < b)
- return 0;
-
- if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= b)
- return 0;
- if (b > 0U)
- return 0;
- if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (b <= 0U)
- return 0;
- if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < b)
- return 0;
-
- if (c < 0)
- return 0;
- if (0 >= c) // expected-warning {{comparison 0 >= 'enum C' is always true}}
- return 0;
- if (c > 0) // expected-warning {{comparison 'enum C' > 0 is always false}}
- return 0;
- if (0 <= c)
- return 0;
- if (c <= 0) // expected-warning {{comparison 'enum C' <= 0 is always true}}
- return 0;
- if (0 > c)
- return 0;
- if (c >= 0)
- return 0;
- if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
- return 0;
-
- if (c < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= c)
- return 0;
- if (c > 0U)
- return 0;
- if (0U <= c) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (c <= 0U)
- return 0;
- if (0U > c) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (c >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < c)
- return 0;
-#else
- if (a < 0)
- return 0;
- if (0 >= a) // expected-warning {{comparison 0 >= 'enum A' is always true}}
- return 0;
- if (a > 0) // expected-warning {{comparison 'enum A' > 0 is always false}}
- return 0;
- if (0 <= a)
- return 0;
- if (a <= 0) // expected-warning {{comparison 'enum A' <= 0 is always true}}
- return 0;
- if (0 > a)
- return 0;
- if (a >= 0)
- return 0;
- if (0 < a) // expected-warning {{comparison 0 < 'enum A' is always false}}
- return 0;
-
- if (a < 0U)
- return 0;
- if (0U >= a)
- return 0;
- if (a > 0U)
- return 0;
- if (0U <= a)
- return 0;
- if (a <= 0U)
- return 0;
- if (0U > a)
- return 0;
- if (a >= 0U)
- return 0;
- if (0U < a)
- return 0;
-
- if (b < 0)
- return 0;
- if (0 >= b)
- return 0;
- if (b > 0)
- return 0;
- if (0 <= b)
- return 0;
- if (b <= 0)
- return 0;
- if (0 > b)
- return 0;
- if (b >= 0)
- return 0;
- if (0 < b)
- return 0;
-
- if (b < 0U)
- return 0;
- if (0U >= b)
- return 0;
- if (b > 0U)
- return 0;
- if (0U <= b)
- return 0;
- if (b <= 0U)
- return 0;
- if (0U > b)
- return 0;
- if (b >= 0U)
- return 0;
- if (0U < b)
- return 0;
-
- if (c < 0)
- return 0;
- if (0 >= c) // expected-warning {{comparison 0 >= 'enum C' is always true}}
- return 0;
- if (c > 0) // expected-warning {{comparison 'enum C' > 0 is always false}}
- return 0;
- if (0 <= c)
- return 0;
- if (c <= 0) // expected-warning {{comparison 'enum C' <= 0 is always true}}
- return 0;
- if (0 > c)
- return 0;
- if (c >= 0)
- return 0;
- if (0 < c) // expected-warning {{0 < 'enum C' is always false}}
- return 0;
-
- if (c < 0U)
- return 0;
- if (0U >= c)
- return 0;
- if (c > 0U)
- return 0;
- if (0U <= c)
- return 0;
- if (c <= 0U)
- return 0;
- if (0U > c)
- return 0;
- if (c >= 0U)
- return 0;
- if (0U < c)
- return 0;
-#endif
return 1;
}
@@ -335,11 +133,7 @@
enum A a;
// used to crash in llvm::APSInt::getMaxValue()
-#ifndef SILENCE
- if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
-#else
- if (a > 0)
-#endif
+ if (a < 0) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
return 1;
Index: test/Sema/tautological-unsigned-enum-zero-compare.c
===================================================================
--- test/Sema/tautological-unsigned-enum-zero-compare.c
+++ test/Sema/tautological-unsigned-enum-zero-compare.c
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -Wno-tautological-unsigned-enum-zero-compare -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only \
+// RUN: -verify=unsigned,unsigned-signed %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -verify=unsigned-signed %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only \
+// RUN: -Wno-tautological-unsigned-enum-zero-compare \
+// RUN: -verify=silence %s
// Okay, this is where it gets complicated.
// Then default enum sigdness is target-specific.
@@ -12,175 +16,38 @@
enum B { B_a = -1 };
enum B b;
-#ifdef UNSIGNED
- if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0 >= a)
- return 0;
- if (a > 0)
- return 0;
- if (0 <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (a <= 0)
- return 0;
- if (0 > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (a >= 0) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0 < a)
- return 0;
-
- if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= a)
- return 0;
- if (a > 0U)
- return 0;
- if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (a <= 0U)
- return 0;
- if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < a)
- return 0;
-
- if (b < 0)
- return 0;
- if (0 >= b)
- return 0;
- if (b > 0)
- return 0;
- if (0 <= b)
- return 0;
- if (b <= 0)
- return 0;
- if (0 > b)
- return 0;
- if (b >= 0)
- return 0;
- if (0 < b)
- return 0;
-
- if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= b)
- return 0;
- if (b > 0U)
- return 0;
- if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (b <= 0U)
- return 0;
- if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < b)
- return 0;
-#elif defined(SIGNED)
- if (a < 0)
- return 0;
- if (0 >= a)
- return 0;
- if (a > 0)
- return 0;
- if (0 <= a)
- return 0;
- if (a <= 0)
- return 0;
- if (0 > a)
- return 0;
- if (a >= 0)
- return 0;
- if (0 < a)
- return 0;
-
- if (a < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= a)
- return 0;
- if (a > 0U)
- return 0;
- if (0U <= a) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (a <= 0U)
- return 0;
- if (0U > a) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (a >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < a)
- return 0;
-
- if (b < 0)
- return 0;
- if (0 >= b)
- return 0;
- if (b > 0)
- return 0;
- if (0 <= b)
- return 0;
- if (b <= 0)
- return 0;
- if (0 > b)
- return 0;
- if (b >= 0)
- return 0;
- if (0 < b)
- return 0;
-
- if (b < 0U) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
- return 0;
- if (0U >= b)
- return 0;
- if (b > 0U)
- return 0;
- if (0U <= b) // expected-warning {{comparison of 0 <= unsigned enum expression is always true}}
- return 0;
- if (b <= 0U)
- return 0;
- if (0U > b) // expected-warning {{comparison of 0 > unsigned enum expression is always false}}
- return 0;
- if (b >= 0U) // expected-warning {{comparison of unsigned enum expression >= 0 is always true}}
- return 0;
- if (0U < b)
- return 0;
-#else
- // expected-no-diagnostics
+ // silence-no-diagnostics
- if (a < 0)
+ if (a < 0) // unsigned-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0 >= a)
return 0;
if (a > 0)
return 0;
- if (0 <= a)
+ if (0 <= a) // unsigned-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (a <= 0)
return 0;
- if (0 > a)
+ if (0 > a) // unsigned-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (a >= 0)
+ if (a >= 0) // unsigned-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0 < a)
return 0;
- if (a < 0U)
+ if (a < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= a)
return 0;
if (a > 0U)
return 0;
- if (0U <= a)
+ if (0U <= a) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (a <= 0U)
return 0;
- if (0U > a)
+ if (0U > a) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (a >= 0U)
+ if (a >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < a)
return 0;
@@ -202,23 +69,22 @@
if (0 < b)
return 0;
- if (b < 0U)
+ if (b < 0U) // unsigned-signed-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0U >= b)
return 0;
if (b > 0U)
return 0;
- if (0U <= b)
+ if (0U <= b) // unsigned-signed-warning {{comparison of 0 <= unsigned enum expression is always true}}
return 0;
if (b <= 0U)
return 0;
- if (0U > b)
+ if (0U > b) // unsigned-signed-warning {{comparison of 0 > unsigned enum expression is always false}}
return 0;
- if (b >= 0U)
+ if (b >= 0U) // unsigned-signed-warning {{comparison of unsigned enum expression >= 0 is always true}}
return 0;
if (0U < b)
return 0;
-#endif
if (a == 0)
return 0;
Index: test/Sema/tautological-constant-enum-compare.c
===================================================================
--- test/Sema/tautological-constant-enum-compare.c
+++ test/Sema/tautological-constant-enum-compare.c
@@ -1,18 +1,15 @@
// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -verify %s
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
-// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -DSILENCE -Wno-tautological-constant-compare -verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED -Wno-tautological-constant-compare -verify=silence %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -Wno-tautological-constant-compare -verify=silence %s
int main() {
enum A { A_a = 2 };
enum A a;
-#ifdef SILENCE
- // expected-no-diagnostics
-#endif
+// silence-no-diagnostics
#ifdef UNSIGNED
-#ifndef SILENCE
if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;
if (0 >= a)
@@ -80,77 +77,7 @@
return 0;
if (4294967295U < a) // expected-warning {{comparison 4294967295 < 'enum A' is always false}}
return 0;
-#else // SILENCE
- if (a < 0)
- return 0;
- if (0 >= a)
- return 0;
- if (a > 0)
- return 0;
- if (0 <= a)
- return 0;
- if (a <= 0)
- return 0;
- if (0 > a)
- return 0;
- if (a >= 0)
- return 0;
- if (0 < a)
- return 0;
-
- if (a < 0U)
- return 0;
- if (0U >= a)
- return 0;
- if (a > 0U)
- return 0;
- if (0U <= a)
- return 0;
- if (a <= 0U)
- return 0;
- if (0U > a)
- return 0;
- if (a >= 0U)
- return 0;
- if (0U < a)
- return 0;
-
- if (a < 4294967295)
- return 0;
- if (4294967295 >= a)
- return 0;
- if (a > 4294967295)
- return 0;
- if (4294967295 <= a)
- return 0;
- if (a <= 4294967295)
- return 0;
- if (4294967295 > a)
- return 0;
- if (a >= 4294967295)
- return 0;
- if (4294967295 < a)
- return 0;
-
- if (a < 4294967295U)
- return 0;
- if (4294967295U >= a)
- return 0;
- if (a > 4294967295U)
- return 0;
- if (4294967295U <= a)
- return 0;
- if (a <= 4294967295U)
- return 0;
- if (4294967295U > a)
- return 0;
- if (a >= 4294967295U)
- return 0;
- if (4294967295U < a)
- return 0;
-#endif
#elif defined(SIGNED)
-#ifndef SILENCE
if (a < -2147483648) // expected-warning {{comparison 'enum A' < -2147483648 is always false}}
return 0;
if (-2147483648 >= a)
@@ -201,58 +128,6 @@
return 0;
if (2147483647U < a) // expected-warning {{comparison 2147483647 < 'enum A' is always false}}
return 0;
-#else // SILENCE
- if (a < -2147483648)
- return 0;
- if (-2147483648 >= a)
- return 0;
- if (a > -2147483648)
- return 0;
- if (-2147483648 <= a)
- return 0;
- if (a <= -2147483648)
- return 0;
- if (-2147483648 > a)
- return 0;
- if (a >= -2147483648)
- return 0;
- if (-2147483648 < a)
- return 0;
-
- if (a < 2147483647)
- return 0;
- if (2147483647 >= a)
- return 0;
- if (a > 2147483647)
- return 0;
- if (2147483647 <= a)
- return 0;
- if (a <= 2147483647)
- return 0;
- if (2147483647 > a)
- return 0;
- if (a >= 2147483647)
- return 0;
- if (2147483647 < a)
- return 0;
-
- if (a < 2147483647U)
- return 0;
- if (2147483647U >= a)
- return 0;
- if (a > 2147483647U)
- return 0;
- if (2147483647U <= a)
- return 0;
- if (a <= 2147483647U)
- return 0;
- if (2147483647U > a)
- return 0;
- if (a >= 2147483647U)
- return 0;
- if (2147483647U < a)
- return 0;
-#endif
#endif
return 1;
Index: test/Sema/tautological-constant-compare.c
===================================================================
--- test/Sema/tautological-constant-compare.c
+++ test/Sema/tautological-constant-compare.c
@@ -1,7 +1,7 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -DTEST -verify -x c++ %s
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify=silence %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -x c++ %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -Wno-tautological-constant-compare -verify=silence -x c++ %s
int value(void);
@@ -12,13 +12,8 @@
void TFunc() {
// Make sure that we do warn for normal variables in template functions !
unsigned char c = value();
-#ifdef TEST
if (c > 255) // expected-warning {{comparison 'unsigned char' > 255 is always false}}
return;
-#else
- if (c > 255)
- return;
-#endif
if (c > macro(255))
return;
@@ -40,7 +35,8 @@
short s = value();
-#ifdef TEST
+ // silence-no-diagnostics
+
if (s == 32767)
return 0;
if (s != 32767)
@@ -146,114 +142,6 @@
return 0;
if (-32768L >= s)
return 0;
-#else
- // expected-no-diagnostics
- if (s == 32767)
- return 0;
- if (s != 32767)
- return 0;
- if (s < 32767)
- return 0;
- if (s <= 32767)
- return 0;
- if (s > 32767)
- return 0;
- if (s >= 32767)
- return 0;
-
- if (32767 == s)
- return 0;
- if (32767 != s)
- return 0;
- if (32767 < s)
- return 0;
- if (32767 <= s)
- return 0;
- if (32767 > s)
- return 0;
- if (32767 >= s)
- return 0;
-
- // FIXME: assumes two's complement
- if (s == -32768)
- return 0;
- if (s != -32768)
- return 0;
- if (s < -32768)
- return 0;
- if (s <= -32768)
- return 0;
- if (s > -32768)
- return 0;
- if (s >= -32768)
- return 0;
-
- if (-32768 == s)
- return 0;
- if (-32768 != s)
- return 0;
- if (-32768 < s)
- return 0;
- if (-32768 <= s)
- return 0;
- if (-32768 > s)
- return 0;
- if (-32768 >= s)
- return 0;
-
- if (s == 32767UL)
- return 0;
- if (s != 32767UL)
- return 0;
- if (s < 32767UL)
- return 0;
- if (s <= 32767UL)
- return 0;
- if (s > 32767UL)
- return 0;
- if (s >= 32767UL)
- return 0;
-
- if (32767UL == s)
- return 0;
- if (32767UL != s)
- return 0;
- if (32767UL < s)
- return 0;
- if (32767UL <= s)
- return 0;
- if (32767UL > s)
- return 0;
- if (32767UL >= s)
- return 0;
-
- // FIXME: assumes two's complement
- if (s == -32768L)
- return 0;
- if (s != -32768L)
- return 0;
- if (s < -32768L)
- return 0;
- if (s <= -32768L)
- return 0;
- if (s > -32768L)
- return 0;
- if (s >= -32768L)
- return 0;
-
- if (-32768L == s)
- return 0;
- if (-32768L != s)
- return 0;
- if (-32768L < s)
- return 0;
- if (-32768L <= s)
- return 0;
- if (-32768L > s)
- return 0;
- if (-32768L >= s)
- return 0;
-#endif
if (s == 0)
return 0;
@@ -285,7 +173,6 @@
unsigned short us = value();
-#ifdef TEST
if (us == 65535)
return 0;
if (us != 65535)
@@ -337,60 +224,6 @@
return 0;
if (65535UL >= us) // expected-warning {{comparison 65535 >= 'unsigned short' is always true}}
return 0;
-#else
- // expected-no-diagnostics
- if (us == 65535)
- return 0;
- if (us != 65535)
- return 0;
- if (us < 65535)
- return 0;
- if (us <= 65535)
- return 0;
- if (us > 65535)
- return 0;
- if (us >= 65535)
- return 0;
-
- if (65535 == us)
- return 0;
- if (65535 != us)
- return 0;
- if (65535 < us)
- return 0;
- if (65535 <= us)
- return 0;
- if (65535 > us)
- return 0;
- if (65535 >= us)
- return 0;
-
- if (us == 65535UL)
- return 0;
- if (us != 65535UL)
- return 0;
- if (us < 65535UL)
- return 0;
- if (us <= 65535UL)
- return 0;
- if (us > 65535UL)
- return 0;
- if (us >= 65535UL)
- return 0;
-
- if (65535UL == us)
- return 0;
- if (65535UL != us)
- return 0;
- if (65535UL < us)
- return 0;
- if (65535UL <= us)
- return 0;
- if (65535UL > us)
- return 0;
- if (65535UL >= us)
- return 0;
-#endif
if (us == 32767)
return 0;
Index: test/Frontend/verify-prefixes.c
===================================================================
--- /dev/null
+++ test/Frontend/verify-prefixes.c
@@ -0,0 +1,125 @@
+#if GC
+# define GCONST const
+#else
+# define GCONST
+#endif
+
+// gconst-note@8 {{variable 'glb' declared const here}}
+GCONST int glb = 5;
+
+
+// Check various correct prefix spellings and combinations.
+//
+// RUN: %clang_cc1 -DGC -verify=gconst %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -verify=lconst %s
+// RUN: %clang_cc1 -DSC -verify=expected %s
+// RUN: %clang_cc1 -DSC -verify %s
+// RUN: %clang_cc1 -DSC -verify -verify %s
+// RUN: %clang_cc1 -verify=nconst %s
+// RUN: %clang_cc1 -verify=n-const %s
+// RUN: %clang_cc1 -verify=n_const %s
+// RUN: %clang_cc1 -verify=NConst %s
+// RUN: %clang_cc1 -verify=NConst2 %s
+// RUN: %clang_cc1 -Wcast-qual -DGC -DLC -verify=gconst,lconst %s
+// RUN: %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify=gconst,lconst,expected %s
+// RUN: %clang_cc1 -Wcast-qual -DGC -DLC -verify=gconst -verify=lconst %s
+// RUN: %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify=gconst,lconst -verify %s
+// RUN: %clang_cc1 -DGC -DSC -verify -verify=gconst -verify %s
+//
+// Duplicate prefixes.
+// RUN: %clang_cc1 -Wcast-qual -DGC -DLC -verify=gconst,lconst,gconst %s
+// RUN: %clang_cc1 -DGC -verify=gconst -verify=gconst,gconst %s
+// RUN: %clang_cc1 -DSC -verify=expected -verify=expected %s
+// RUN: %clang_cc1 -DSC -verify -verify=expected %s
+//
+// Various tortured cases: multiple directives with different prefixes per
+// line, prefixes used as comments, prefixes prefixing prefixes, and prefixes
+// with special suffixes.
+// RUN: %clang_cc1 -Wcast-qual -DLC -verify=foo %s
+// RUN: %clang_cc1 -DSC -verify=bar %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo,bar %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=bar,foo %s
+// RUN: %clang_cc1 -DSC -verify=foo-bar %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -verify=bar-foo %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo,foo-bar %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo-bar,foo %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=bar,bar-foo %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=bar-foo,bar %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo-bar,bar-foo %s
+// RUN: %clang_cc1 -DSC -verify=foo-warning %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -verify=bar-warning-re %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo,foo-warning %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=foo-warning,foo %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=bar,bar-warning-re %s
+// RUN: %clang_cc1 -Wcast-qual -DLC -DSC -verify=bar-warning-re,bar %s
+
+
+// Check invalid prefixes. Make sure there's no additional output, which
+// might indicate that diagnostic verification became enabled even though it
+// was requested incorrectly.
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify=5abc %s 2> %t
+// RUN: FileCheck --check-prefixes=ERR,ERR-HEAD-NUM %s < %t
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify='-xy' %s 2> %t
+// RUN: FileCheck --check-prefixes=ERR,ERR-HEAD-HYPHEN %s < %t
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify='_k' %s 2> %t
+// RUN: FileCheck --check-prefixes=ERR,ERR-HEAD-UNDER %s < %t
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify='#a' %s 2> %t
+// RUN: FileCheck --check-prefixes=ERR,ERR-HEAD-OTHER %s < %t
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC -verify='b$' %s 2> %t
+// RUN: FileCheck --check-prefixes=ERR,ERR-BODY-OTHER %s < %t
+//
+// ERR-NOT: {{.}}
+// ERR-HEAD-NUM: error: invalid value '5abc' in '-verify='
+// ERR-HEAD-HYPHEN: error: invalid value '-xy' in '-verify='
+// ERR-HEAD-UNDER: error: invalid value '_k' in '-verify='
+// ERR-HEAD-OTHER: error: invalid value '#a' in '-verify='
+// ERR-BODY-OTHER: error: invalid value 'b$' in '-verify='
+// ERR-NEXT: note: -verify prefixes must start with a letter and contain only alphanumeric characters, hyphens, and underscores
+// ERR-NOT: {{.}}
+
+
+// Check that our test code actually has expected diagnostics when there's no
+// -verify.
+//
+// RUN: not %clang_cc1 -Wcast-qual -DGC -DLC -DSC %s 2> %t
+// RUN: FileCheck --check-prefix=ALL %s < %t
+//
+// ALL: cannot assign to variable 'glb' with const-qualified type 'const int'
+// ALL: variable 'glb' declared const here
+// ALL: cast from 'const int *' to 'int *' drops const qualifier
+// ALL: initializing 'int *' with an expression of type 'const int *' discards qualifiers
+
+
+#if LC
+# define LCONST const
+#else
+# define LCONST
+#endif
+
+#if SC
+# define SCONST const
+#else
+# define SCONST
+#endif
+
+void foo() {
+ LCONST int loc = 5;
+ SCONST static int sta = 5;
+ // We don't actually expect 1-2 occurrences of this error. We're just
+ // checking the parsing.
+ glb = 6; // gconst-error1-2 {{cannot assign to variable 'glb' with const-qualified type 'const int'}}
+ *(int*)(&loc) = 6; // lconst-warning {{cast from 'const int *' to 'int *' drops const qualifier}}
+ ; // Code, comments, and many directives with different prefixes per line, including cases where some prefixes (foo and bar) prefix others (such as foo-bar and bar-foo), such that some prefixes appear as normal comments and some have special suffixes (-warning and -re): foo-warning@-1 {{cast from 'const int *' to 'int *' drops const qualifier}} foo-bar-warning@+1 {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}} foo-warning-warning@+1 {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}} bar-warning-re-warning@-1 {{cast from 'const int *' to 'int *' drops const qualifier}} bar-foo-warning@-1 {{cast from 'const int *' to 'int *' drops const qualifier}} bar-warning@+1 {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}}
+ int *p = &sta; // expected-warning {{initializing 'int *' with an expression of type 'const int *' discards qualifiers}}
+}
+
+// nconst-no-diagnostics
+// n-const-no-diagnostics
+// n_const-no-diagnostics
+// NConst-no-diagnostics
+// NConst2-no-diagnostics
Index: lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -229,22 +229,52 @@
return true;
}
- // Return true if string literal is found.
- // When true, P marks begin-position of S in content.
- bool Search(StringRef S, bool EnsureStartOfWord = false) {
+ // Return true if string literal S is matched in content.
+ // When true, P marks begin-position of the match, and calling Advance sets C
+ // to end-position of the match.
+ // If S is the empty string, then search for any letter instead (makes sense
+ // with FinishDirectiveToken=true).
+ // If EnsureStartOfWord, then skip matches that don't start a new word.
+ // If FinishDirectiveToken, then assume the match is the start of a comment
+ // directive for -verify, and extend the match to include the entire first
+ // token of that directive.
+ bool Search(StringRef S, bool EnsureStartOfWord = false,
+ bool FinishDirectiveToken = false) {
do {
- P = std::search(C, End, S.begin(), S.end());
- PEnd = P + S.size();
+ if (!S.empty()) {
+ P = std::search(C, End, S.begin(), S.end());
+ PEnd = P + S.size();
+ }
+ else {
+ P = C;
+ while (P != End && !isLetter(*P))
+ ++P;
+ PEnd = P + 1;
+ }
if (P == End)
break;
- if (!EnsureStartOfWord
- // Check if string literal starts a new word.
- || P == Begin || isWhitespace(P[-1])
- // Or it could be preceded by the start of a comment.
- || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
- && P[-2] == '/'))
- return true;
- // Otherwise, skip and search again.
+ // If not start of word but required, skip and search again.
+ if (EnsureStartOfWord
+ // Check if string literal starts a new word.
+ && !(P == Begin || isWhitespace(P[-1])
+ // Or it could be preceded by the start of a comment.
+ || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*')
+ && P[-2] == '/')))
+ continue;
+ if (FinishDirectiveToken) {
+ while (PEnd != End && (isAlphanumeric(*PEnd)
+ || *PEnd == '-' || *PEnd == '_'))
+ ++PEnd;
+ // Put back trailing digits and hyphens to be parsed later as a count
+ // or count range. Because -verify prefixes must start with letters,
+ // we know the actual directive we found starts with a letter, so
+ // we won't put back the entire directive word and thus record an empty
+ // string.
+ assert(isLetter(*P) && "-verify prefix must start with a letter");
+ while (isDigit(PEnd[-1]) || PEnd[-1] == '-')
+ --PEnd;
+ }
+ return true;
} while (Advance());
return false;
}
@@ -314,37 +344,68 @@
// A single comment may contain multiple directives.
bool FoundDirective = false;
for (ParseHelper PH(S); !PH.Done();) {
- // Search for token: expected
- if (!PH.Search("expected", true))
+ // Search for the initial directive token.
+ // If one prefix, save time by searching only for its directives.
+ // Otherwise, search for any potential directive token and check it later.
+ const auto &Prefixes = Diags.getDiagnosticOptions().VerifyPrefixes;
+ if (!(Prefixes.size() == 1 ? PH.Search(Prefixes[0], true, true)
+ : PH.Search("", true, true)))
break;
PH.Advance();
- // Next token: -
- if (!PH.Next("-"))
- continue;
- PH.Advance();
+ // Default directive kind.
+ bool RegexKind = false;
+ const char* KindStr = "string";
+
+ // Parse the initial directive token in reverse so we can easily determine
+ // its exact actual prefix. If we were to parse it from the front instead,
+ // it would be harder to determine where the prefix ends because there
+ // might be multiple matching -verify prefixes because some might prefix
+ // others.
+ StringRef DToken(PH.P, PH.C - PH.P);
- // Next token: { error | warning | note }
+ // Regex in initial directive token: -re
+ if (DToken.endswith("-re")) {
+ RegexKind = true;
+ KindStr = "regex";
+ DToken = DToken.substr(0, DToken.size()-3);
+ }
+
+ // Type in initial directive token: -{error|warning|note|no-diagnostics}
DirectiveList *DL = nullptr;
- if (PH.Next("error"))
+ bool NoDiag = false;
+ StringRef DType;
+ if (DToken.endswith(DType="-error"))
DL = ED ? &ED->Errors : nullptr;
- else if (PH.Next("warning"))
+ else if (DToken.endswith(DType="-warning"))
DL = ED ? &ED->Warnings : nullptr;
- else if (PH.Next("remark"))
+ else if (DToken.endswith(DType="-remark"))
DL = ED ? &ED->Remarks : nullptr;
- else if (PH.Next("note"))
+ else if (DToken.endswith(DType="-note"))
DL = ED ? &ED->Notes : nullptr;
- else if (PH.Next("no-diagnostics")) {
+ else if (DToken.endswith(DType="-no-diagnostics")) {
+ NoDiag = true;
+ if (RegexKind)
+ continue;
+ }
+ else
+ continue;
+ DToken = DToken.substr(0, DToken.size()-DType.size());
+
+ // What's left in DToken is the actual prefix. That might not be a -verify
+ // prefix even if there is only one -verify prefix (for example, the full
+ // DToken is foo-bar-warning, but foo is the only -verify prefix).
+ if (Prefixes.end() == std::find(Prefixes.begin(), Prefixes.end(), DToken))
+ continue;
+
+ if (NoDiag) {
if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives)
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/true;
else
Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics;
continue;
- } else
- continue;
- PH.Advance();
-
+ }
if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) {
Diags.Report(Pos, diag::err_verify_invalid_no_diags)
<< /*IsExpectedNoDiagnostics=*/false;
@@ -357,17 +418,6 @@
if (!DL)
return true;
- // Default directive kind.
- bool RegexKind = false;
- const char* KindStr = "string";
-
- // Next optional token: -
- if (PH.Next("-re")) {
- PH.Advance();
- RegexKind = true;
- KindStr = "regex";
- }
-
// Next optional token: @
SourceLocation ExpectedLoc;
bool MatchAnyLine = false;
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1069,6 +1069,28 @@
llvm::sys::Process::StandardErrHasColors());
}
+static bool checkVerifyPrefixes(DiagnosticOptions &Opts,
+ DiagnosticsEngine *Diags) {
+ bool Success = true;
+ for (const auto &Prefix : Opts.VerifyPrefixes) {
+ // Every prefix must start with a letter and contain only alphanumeric
+ // characters, hyphens, and underscores.
+ auto BadChar = std::find_if(Prefix.begin(), Prefix.end(),
+ [](char C){return !isAlphanumeric(C)
+ && C != '-' && C != '_';});
+ if (BadChar != Prefix.end() || !isLetter(Prefix[0])) {
+ Success = false;
+ if (Diags) {
+ Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix;
+ Diags->Report(diag::note_drv_verify_prefix_spelling);
+ }
+ }
+ }
+ if (!Success)
+ Opts.VerifyDiagnostics = false;
+ return Success;
+}
+
bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
DiagnosticsEngine *Diags,
bool DefaultDiagColor, bool DefaultShowOpt) {
@@ -1156,7 +1178,11 @@
Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location);
- Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
+ Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ);
+ Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ);
+ if (Args.hasArg(OPT_verify))
+ Opts.VerifyPrefixes.push_back("expected");
+ Success &= checkVerifyPrefixes(Opts, Diags);
DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None;
Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=",
Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ),
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -400,8 +400,11 @@
HelpText<"Set the maximum number of source lines to show in a caret diagnostic">;
def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
+def verify_EQ : CommaJoined<["-"], "verify=">,
+ MetaVarName<"<prefixes>">,
+ HelpText<"Verify diagnostic output using comment directives that start with prefixes in the comma-separated sequence <prefixes>">;
def verify : Flag<["-"], "verify">,
- HelpText<"Verify diagnostic output using comment directives">;
+ HelpText<"Equivalent to -verify=expected">;
def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
HelpText<"Ignore unexpected diagnostic messages">;
def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
Index: include/clang/Basic/DiagnosticOptions.h
===================================================================
--- include/clang/Basic/DiagnosticOptions.h
+++ include/clang/Basic/DiagnosticOptions.h
@@ -100,6 +100,10 @@
/// prefixes removed.
std::vector<std::string> Remarks;
+ /// The prefixes for comment directives sought by -verify ("expected" by
+ /// default).
+ std::vector<std::string> VerifyPrefixes;
+
public:
// Define accessors/mutators for diagnostic options of enumeration type.
#define DIAGOPT(Name, Bits, Default)
Index: include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- include/clang/Basic/DiagnosticDriverKinds.td
+++ include/clang/Basic/DiagnosticDriverKinds.td
@@ -338,4 +338,6 @@
def warn_drv_fine_grained_bitfield_accesses_ignored : Warning<
"option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored">,
InGroup<OptionIgnored>;
+
+def note_drv_verify_prefix_spelling : Note<"-verify prefixes must start with a letter and contain only alphanumeric characters, hyphens, and underscores">;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits