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; + +def note_drv_verify_prefix_spelling : Note<"-verify prefixes must start with a letter and contain only alphanumeric characters, hyphens, and underscores">; } Index: include/clang/Basic/DiagnosticOptions.h =================================================================== --- include/clang/Basic/DiagnosticOptions.h +++ include/clang/Basic/DiagnosticOptions.h @@ -100,6 +100,10 @@ /// prefixes removed. std::vector Remarks; + /// The prefixes for comment directives sought by -verify ("expected" by + /// default). + std::vector VerifyPrefixes; + public: // Define accessors/mutators for diagnostic options of enumeration type. #define DIAGOPT(Name, Bits, Default) 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<"">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; +def verify_EQ : CommaJoined<["-"], "verify=">, + MetaVarName<"">, + HelpText<"Verify diagnostic output using comment directives that start with prefixes in the comma-separated sequence ">; 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: 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: 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: 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: 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/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-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-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-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;