]> granicus.if.org Git - re2c/commitdiff
Don't bother with reachability when reporting nullable rules.
authorUlya Trofimovich <skvadrik@gmail.com>
Thu, 19 May 2016 10:37:11 +0000 (11:37 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Thu, 19 May 2016 10:37:11 +0000 (11:37 +0100)
We couldn't trace all unreachable nullable rules anyway, e.g.:
    [^]?
Nullable part of this rule is unreachable, but it was reported.
Besides, there's nothing bad in reporting all probles at once.

31 files changed:
re2c/Makefile.am
re2c/src/codegen/emit_dfa.cc
re2c/src/conf/warn.cc
re2c/src/conf/warn.h
re2c/src/ir/compile.cc
re2c/src/ir/nfa/init_rules.cc
re2c/src/ir/nfa/nullable.cc [deleted file]
re2c/src/ir/regexp/nullable.cc [new file with mode: 0644]
re2c/src/ir/regexp/regexp.h
re2c/src/ir/rule.h
re2c/src/ir/skeleton/skeleton.h
re2c/src/ir/skeleton/unreachable.cc [moved from re2c/src/ir/skeleton/unreachable_nullable.cc with 82% similarity]
re2c/test/bug116.c
re2c/test/bug2462777.ci.c
re2c/test/condition_02.c.c
re2c/test/condition_02.cg.c
re2c/test/condition_03.cg.c
re2c/test/condition_11.cg.c
re2c/test/condition_13.cg.c
re2c/test/default_dup_star_1.ic.c
re2c/test/input4.--empty-class(match-empty).c
re2c/test/input4.c
re2c/test/input6.--empty-class(match-empty).c
re2c/test/input6.c
re2c/test/segfault_full_range_star.bi.c
re2c/test/segfault_full_range_star_startlabel.ci.c
re2c/test/segfault_full_range_star_startlabel.i.c
re2c/test/segfault_full_range_star_startlabel2.ci.c
re2c/test/segfault_full_range_star_startlabel2.i.c
re2c/test/tags/nondet_iter.--tags.c
re2c/test/yyaccept_missing.bci.c

index 3c1597a0bbed11536552f0102953b3aac6ee8ec1..408e3bfaa644ebf8607e93367cda6ca300bd9da0 100644 (file)
@@ -86,7 +86,6 @@ SRC = \
        src/ir/nfa/init_rules.cc \
        src/ir/nfa/make_tags.cc \
        src/ir/nfa/nfa.cc \
-       src/ir/nfa/nullable.cc \
        src/ir/nfa/regexps2nfa.cc \
        src/ir/adfa/adfa.cc \
        src/ir/adfa/prepare.cc \
@@ -103,6 +102,7 @@ SRC = \
        src/ir/regexp/encoding/utf16/utf16_regexp.cc \
        src/ir/regexp/encoding/utf16/utf16.cc \
        src/ir/regexp/encoding/utf16/utf16_range.cc \
+       src/ir/regexp/nullable.cc \
        src/ir/regexp/regexp.cc \
        src/ir/regexp/split_charset.cc \
        src/ir/compile.cc \
@@ -112,7 +112,7 @@ SRC = \
        src/ir/skeleton/generate_data.cc \
        src/ir/skeleton/maxpath.cc \
        src/ir/skeleton/skeleton.cc \
-       src/ir/skeleton/unreachable_nullable.cc \
+       src/ir/skeleton/unreachable.cc \
        src/ir/tag.cc \
        src/ir/tagpool.cc \
        src/main.cc \
index 84ef2af2a6af91c040b996b50be51dc7496afbdc..0800f6c7b4cd8eb8eb778da8c4fcc48a8e0b4a84 100644 (file)
@@ -175,7 +175,7 @@ void DFA::emit(Output & output, uint32_t& ind, bool isLastCond, bool& bPrologBra
        head->action.set_initial (initial_label, head->action.type == Action::SAVE);
 
        warn_undefined_control_flow(*skeleton);
-       warn_unreachable_nullable_rules(*skeleton);
+       warn_unreachable(*skeleton);
 
        if (opts->target == opt_t::SKELETON) {
                if (output.skeletons.insert (name).second)
index 5810f129a82a503c7cddd02a6cc8ee4a9f93ae03..8c75420b8cda29155da045f69512088018b8ac49 100644 (file)
@@ -109,13 +109,14 @@ void Warn::empty_class (uint32_t line)
        }
 }
 
-void Warn::match_empty_string (uint32_t line)
+void Warn::match_empty_string (uint32_t line, const std::string &cond)
 {
        if (mask[MATCH_EMPTY_STRING] & WARNING)
        {
                const bool e = mask[MATCH_EMPTY_STRING] & ERROR;
                error_accuml |= e;
-               warning (names[MATCH_EMPTY_STRING], line, e, "rule matches empty string");
+               warning (names[MATCH_EMPTY_STRING], line, e,
+                       "rule %smatches empty string", incond(cond).c_str());
        }
 }
 
index 58501c2f923047d0fea5dc785b8e1ee1882bd8ce..419ddbfa5b26aba26370fd29f9664a8b1e021133 100644 (file)
@@ -58,7 +58,7 @@ public:
 
        void condition_order (uint32_t line);
        void empty_class (uint32_t line);
-       void match_empty_string (uint32_t line);
+       void match_empty_string (uint32_t line, const std::string &cond);
        void nondeterministic_tags(uint32_t line, const std::string &cond, const std::string *tagname);
        void swapped_range (uint32_t line, uint32_t l, uint32_t u);
        void undefined_control_flow (const Skeleton &skel, std::vector<path_t> & paths, bool overflow);
index 73369ad70a782dd417af756266f1c4ec2409609e..c380f8892c8c910ce21a7951fd584c8e82f921ea 100644 (file)
@@ -38,6 +38,8 @@ static smart_ptr<DFA> compile_rules(
        const uint32_t line = output.source.block().line;
        const std::string name = make_name(cond, line);
 
+       warn_nullable(rules, cond);
+
        // The original set of code units (charset) might be very large.
        // A common trick it is to split charset into disjoint character ranges
        // and choose a representative of each range (we choose lower bound).
index dc3dc51247f672d5d4a542886cd4b2c97afc1416..7e43a2f493411281525815ba4409b00fc99cfccc 100644 (file)
@@ -44,7 +44,6 @@ void init_rules(const std::vector<const RegExpRule*> &regexps,
        for (size_t r = 0, t = 0; r < nr; ++r) {
                Rule &rule = rules[r];
                rule.info = regexps[r]->info;
-               rule.nullable = nullable_rule(regexps[r]);
 
                rule.ltag = t;
                for (; t < nt && tags[t].rule == r; ++t);
diff --git a/re2c/src/ir/nfa/nullable.cc b/re2c/src/ir/nfa/nullable.cc
deleted file mode 100644 (file)
index a2fbf82..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "src/ir/nfa/nfa.h"
-
-namespace re2c {
-
-static bool nullable(const RegExp *re, bool &trail)
-{
-       if (trail) {
-               return true;
-       }
-       switch (re->type) {
-               case RegExp::NIL:
-               case RegExp::ITER:
-                       return true;
-               case RegExp::TAG:
-                       if (re->tag == NULL) {
-                               trail = true;
-                       }
-                       return true;
-               case RegExp::SYM:
-                       return false;
-               case RegExp::ALT:
-                       return nullable(re->alt.re1, trail)
-                               || nullable(re->alt.re2, trail);
-               case RegExp::CAT:
-                       return nullable(re->cat.re1, trail)
-                               && nullable(re->cat.re2, trail);
-               default:
-                       assert(false);
-       }
-}
-
-bool nullable_rule(const RegExpRule *rule)
-{
-       bool trail = false;
-       return nullable(rule->re, trail);
-}
-
-} // namespace re2c
diff --git a/re2c/src/ir/regexp/nullable.cc b/re2c/src/ir/regexp/nullable.cc
new file mode 100644 (file)
index 0000000..3abef05
--- /dev/null
@@ -0,0 +1,52 @@
+#include "src/conf/opt.h"
+#include "src/ir/regexp/regexp.h"
+#include "src/globals.h"
+
+namespace re2c {
+
+static bool nullable(const RegExp *re, bool &trail)
+{
+       if (trail) {
+               return true;
+       }
+       switch (re->type) {
+               case RegExp::NIL:
+               case RegExp::ITER:
+                       return true;
+               case RegExp::TAG:
+                       if (re->tag == NULL) {
+                               trail = true;
+                       }
+                       return true;
+               case RegExp::SYM:
+                       return false;
+               case RegExp::ALT:
+                       return nullable(re->alt.re1, trail)
+                               || nullable(re->alt.re2, trail);
+               case RegExp::CAT:
+                       return nullable(re->cat.re1, trail)
+                               && nullable(re->cat.re2, trail);
+               default:
+                       assert(false);
+       }
+}
+
+/*
+ * warn about rules that match empty string
+ * (including rules with nonempty trailing context)
+ * false positives on partially self-shadowed rules like [^]?
+ */
+void warn_nullable(const std::vector<const RegExpRule*> &regexps,
+       const std::string &cond)
+{
+       const size_t nregexps = regexps.size();
+       for (size_t i = 0; i < nregexps; ++i) {
+               const RegExpRule *r = regexps[i];
+               bool trail = false;
+               if (nullable(r->re, trail)) {
+                       warn.match_empty_string(r->info->loc.line, cond);
+               }
+       }
+}
+
+} // namespace re2c
index 1244a4d91d295e70c35d865902624bffb8bb238a..2d216753ad2bb0b81cb33a92c66b3ecd3d7d1965 100644 (file)
@@ -118,6 +118,8 @@ const RegExp *doCat(const RegExp *re1, const RegExp *re2);
 const RegExp *repeat(const RegExp *re, uint32_t n);
 const RegExp *repeat_from_to(const RegExp *re, uint32_t n, uint32_t m);
 const RegExp *repeat_from(const RegExp *re, uint32_t n);
+void warn_nullable(const std::vector<const RegExpRule*> &regexps,
+       const std::string &cond);
 
 } // end namespace re2c
 
index 0cfc6bdb915bc8499eeee6556228434587c44761..1824c8d64219c69f4f01b7684a077d2c520f9b11 100644 (file)
@@ -39,7 +39,6 @@ struct Rule
        size_t htag;
        size_t trail;
        size_t tags;
-       bool nullable;
        std::set<uint32_t> shadow;
        bool reachable;
 
@@ -49,7 +48,6 @@ struct Rule
                , htag(0)
                , trail(Tag::NONE)
                , tags(0)
-               , nullable(false)
                , shadow()
                , reachable(false)
        {}
index 7e54d372b261805dd6259c484e625cf7c8720fd1..255f0974d3c5e505615f45e20eb4416bab4e042e 100644 (file)
@@ -85,7 +85,7 @@ template<typename key_t> key_t Skeleton::rule2key(size_t r, size_t def) const
 uint32_t maxpath(const Skeleton &skel);
 void warn_undefined_control_flow(const Skeleton &skel);
 void fprint_default_path(FILE *f, const Skeleton &skel, const path_t &p);
-void warn_unreachable_nullable_rules(const Skeleton &skel);
+void warn_unreachable(const Skeleton &skel);
 void emit_data(const Skeleton &skel);
 void emit_prolog(OutputFile & o);
 void emit_start(const Skeleton &skel, OutputFile &o, size_t maxfill,
similarity index 82%
rename from re2c/src/ir/skeleton/unreachable_nullable.cc
rename to re2c/src/ir/skeleton/unreachable.cc
index 5bbb49513ba36ae9ed1f9953e6f01339f756aaaa..3c0dc8e581004b8a79a83dcd9d110bd012c8b0cb 100644 (file)
@@ -36,7 +36,7 @@ static void calc_reachable(
        }
 }
 
-void warn_unreachable_nullable_rules(const Skeleton &skel)
+void warn_unreachable(const Skeleton &skel)
 {
        // calculate reachable rules
        const size_t nnodes = skel.nodes_count;
@@ -76,18 +76,6 @@ void warn_unreachable_nullable_rules(const Skeleton &skel)
                        warn.unreachable_rule(skel.cond, rule);
                }
        }
-
-       // warn about nullable rules:
-       //    - rules that match empty string
-       //    - rules that match empty strins with nonempty trailing context
-       // false positives on partially shadowed (yet reachable) rules, e.g.:
-       //     [^]?
-       for (size_t i = 0; i < nrules; ++i) {
-               const Rule &rule = rules[i];
-               if (rule.nullable && rule.reachable) {
-                       warn.match_empty_string(rule.info->loc.line);
-               }
-       }
 }
 
 } // namespace re2c
index f89a356a36e0185302747b0ed2c7c069df26d3e4..454029412452361c1822f8e706b7033375da7371 100644 (file)
@@ -20,5 +20,5 @@ yy3:
 }
 #line 3 "bug116.re"
 
-re2c: warning: line 3: control flow is undefined for strings that match '[\x0-\x60\x62-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: control flow is undefined for strings that match '[\x0-\x60\x62-\xFF]', use default rule '*' [-Wundefined-control-flow]
index 77c241d5523c80007ca485ce39876bffd5da2941..345fcb73d7ceeb3da4ea8c67cb18ca56fbb6b731 100644 (file)
@@ -21,4 +21,4 @@ yy4:
        {x;}
 }
 
-re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 2: rule in condition 'X' matches empty string [-Wmatch-empty-string]
index 36d36a04a748d11828793782bfc01a51c21c040d..0fb4afc9e2a57d2cb7245890b14ecca8578d6c55 100644 (file)
@@ -51,6 +51,6 @@ yy14:
 }
 #line 7 "condition_02.c.re"
 
-re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule in condition '0' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 7: control flow in condition 'r1' is undefined for strings that match '[\x0-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 7: control flow in condition 'r2' is undefined for strings that match '[\x0-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
index cf693a6b765371161cda3db92725a3899714fc35..7a18c466f1004a506da8a23dcf72c08aa0346908 100644 (file)
@@ -46,7 +46,7 @@ yy14:
 }
 #line 7 "condition_02.cg.re"
 
-re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule in condition '0' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 7: control flow in condition 'r1' is undefined for strings that match '[\x0-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 7: control flow in condition 'r2' is undefined for strings that match '[\x0-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 7: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order]
index aad5c09bb395f50882f7a40d227364fdc6139810..7f5c76e129a51c7e3778fd5372e38a05449dcabc 100644 (file)
@@ -79,7 +79,7 @@ yy22:
 }
 #line 9 "condition_03.cg.re"
 
-re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule in condition '0' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 9: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order]
index 7bbf213bb5f871e8b2174932417303dc0fcca7cd..7941d6d36a73b71ea03e3cbd2bff1d633b13afe1 100644 (file)
@@ -84,7 +84,7 @@ yy22:
 }
 #line 9 "condition_11.cg.re"
 
-re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule in condition '0' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 9: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order]
index 998e9084a38e6fcdabca976e74daf9319145f454..084ff3a702b25b0ab659dc40cd106b3a52d05a47 100644 (file)
@@ -68,7 +68,7 @@ yy22:
 }
 #line 9 "condition_13.cg.re"
 
-re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 3: rule in condition '0' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 9: control flow in condition 'r1' is undefined for strings that match '[\x0-\x30\x33-\x60\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: control flow in condition 'r2' is undefined for strings that match '[\x0-\x30\x33-\x61\x63-\xFF]', use default rule '*' [-Wundefined-control-flow]
 re2c: warning: line 9: looks like you use hardcoded numbers instead of autogenerated condition names: better add '/*!types:re2c*/' directive or '-t, --type-header' option and don't rely on fixed condition order. [-Wcondition-order]
index 940756bfd245355edec74c73aed6501d93fb9b4f..d62ce0644c009a79f1ae1202e2d90f2f07157372 100644 (file)
@@ -28,4 +28,5 @@ yy12:
        { return DEFAULT-*; }
 }
 
+re2c: warning: line 4: rule in condition 'c3' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 4: unreachable rule in condition 'c3' (shadowed by rule at line 5) [-Wunreachable-rules]
index 1ef8d8072cf7d70e03742635ca5be037040f7ff3..6635a71a9b7cbed420636b2f73e7da8c6bbe2da3 100644 (file)
@@ -19,5 +19,6 @@ yy3:
 #line 7 "input4.--empty-class(match-empty).re"
 
 re2c: warning: line 3: empty character class [-Wempty-character-class]
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
 re2c: warning: line 5: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
index 517b8282a158eadb4e6410bf3a4d003b5af53a72..302c2246e029b103399c403e3757bc483feb07f1 100644 (file)
@@ -19,5 +19,6 @@ yy3:
 #line 7 "input4.re"
 
 re2c: warning: line 3: empty character class [-Wempty-character-class]
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
 re2c: warning: line 5: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
index 238c64a8d70d060200247450940a7b4856566ad4..5652549d3294d923958a10ca03c57f59f4736cc0 100644 (file)
@@ -21,4 +21,5 @@ yy3:
 
 re2c: warning: line 3: empty character class [-Wempty-character-class]
 re2c: warning: line 3: empty character class [-Wempty-character-class]
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
index 410ad5815229a9f5b378d4c1d65c3b38eb424c4e..f0ff023af50b9f36f2245d02798100ec8613e597 100644 (file)
@@ -21,4 +21,5 @@ yy3:
 
 re2c: warning: line 3: empty character class [-Wempty-character-class]
 re2c: warning: line 3: empty character class [-Wempty-character-class]
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule (shadowed by rule at line 4) [-Wunreachable-rules]
index 0f9f7d7bcb872c293669956d3cb9a999bf1868cb..d05aaf195e27733c0a86adc4524b551408b61dcf 100644 (file)
@@ -48,4 +48,5 @@ yy0:
        {}
 }
 
+re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 2: unreachable rule  [-Wunreachable-rules]
index f99aeeed9495564f758a517e89258bf208f07bba..5a0846d9722d617c9bfe32fb287f58546466cf65 100644 (file)
@@ -18,4 +18,5 @@ yy1:
        {}
 }
 
+re2c: warning: line 3: rule in condition 'c1' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule in condition 'c1'  [-Wunreachable-rules]
index a182f7d8f3b623c948212af93388897b798828dd..29e7c378857f4339b9faac469be424a45635c4e9 100644 (file)
@@ -13,4 +13,5 @@ yy0:
        {}
 }
 
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule  [-Wunreachable-rules]
index bc52884417edaac1ab0fbb994553cf0ac886bc9a..b624a5f16e65bb92a93322f0a46e7d98281be665 100644 (file)
@@ -18,4 +18,5 @@ yy1:
        {}
 }
 
+re2c: warning: line 3: rule in condition 'c1' matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule in condition 'c1'  [-Wunreachable-rules]
index 214ac741e824ea744ebf45812c456ee85bf8b4ed..0e60f8895cd2adc4b17c6ce06f0b2b154e0f9b76 100644 (file)
@@ -12,4 +12,5 @@ yy0:
        {}
 }
 
+re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: unreachable rule  [-Wunreachable-rules]
index 661c10de9f7b76425a4128f40710120b94392f7d..350eb6bbcfd22c467ce90d16349444a9efc11a8a 100644 (file)
@@ -1,10 +1,10 @@
-re2c: error: line 5: tag 'b' is nondeterministic
-re2c: error: line 6: tag 'e' is nondeterministic
-re2c: error: line 8: tag 'c' is nondeterministic
-re2c: error: line 9: tag 'f' is nondeterministic
 re2c: warning: line 2: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 3: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 5: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 6: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 8: rule matches empty string [-Wmatch-empty-string]
 re2c: warning: line 9: rule matches empty string [-Wmatch-empty-string]
+re2c: error: line 5: tag 'b' is nondeterministic
+re2c: error: line 6: tag 'e' is nondeterministic
+re2c: error: line 8: tag 'c' is nondeterministic
+re2c: error: line 9: tag 'f' is nondeterministic
index fe4aa2997ce43490fc57775558d6ea247283da62..71e7ba4576158c673782be921bb81b4aaddd777b 100644 (file)
@@ -165,4 +165,4 @@ int main(int argc, char **argv)
                return 1;
        }
 }
-re2c: warning: line 44: rule matches empty string [-Wmatch-empty-string]
+re2c: warning: line 44: rule in condition 'ST_VALUE' matches empty string [-Wmatch-empty-string]