+2017-10-12 David Malcolm <dmalcolm@redhat.com>
+
+ * c-common.c (enum missing_token_insertion_kind): New enum.
+ (get_missing_token_insertion_kind): New function.
+ (maybe_suggest_missing_token_insertion): New function.
+ * c-common.h (maybe_suggest_missing_token_insertion): New decl.
+
2017-10-11 Nathan Sidwell <nathan@acm.org>
* c-opts.c (add_prefixed_path): Change chain to incpath_kind.
return c_ts18661_flt_eval_method ();
}
+/* An enum for get_missing_token_insertion_kind for describing the best
+ place to insert a missing token, if there is one. */
+
+enum missing_token_insertion_kind
+{
+ MTIK_IMPOSSIBLE,
+ MTIK_INSERT_BEFORE_NEXT,
+ MTIK_INSERT_AFTER_PREV
+};
+
+/* Given a missing token of TYPE, determine if it is reasonable to
+ emit a fix-it hint suggesting the insertion of the token, and,
+ if so, where the token should be inserted relative to other tokens.
+
+ It only makes sense to do this for values of TYPE that are symbols.
+
+ Some symbols should go before the next token, e.g. in:
+ if flag)
+ we want to insert the missing '(' immediately before "flag",
+ giving:
+ if (flag)
+ rather than:
+ if( flag)
+ These use MTIK_INSERT_BEFORE_NEXT.
+
+ Other symbols should go after the previous token, e.g. in:
+ if (flag
+ do_something ();
+ we want to insert the missing ')' immediately after the "flag",
+ giving:
+ if (flag)
+ do_something ();
+ rather than:
+ if (flag
+ )do_something ();
+ These use MTIK_INSERT_AFTER_PREV. */
+
+static enum missing_token_insertion_kind
+get_missing_token_insertion_kind (enum cpp_ttype type)
+{
+ switch (type)
+ {
+ /* Insert missing "opening" brackets immediately
+ before the next token. */
+ case CPP_OPEN_SQUARE:
+ case CPP_OPEN_PAREN:
+ return MTIK_INSERT_BEFORE_NEXT;
+
+ /* Insert other missing symbols immediately after
+ the previous token. */
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_SQUARE:
+ case CPP_SEMICOLON:
+ case CPP_COMMA:
+ case CPP_COLON:
+ return MTIK_INSERT_AFTER_PREV;
+
+ /* Other kinds of token don't get fix-it hints. */
+ default:
+ return MTIK_IMPOSSIBLE;
+ }
+}
+
+/* Given RICHLOC, a location for a diagnostic describing a missing token
+ of kind TOKEN_TYPE, potentially add a fix-it hint suggesting the
+ insertion of the token.
+
+ The location of the attempted fix-it hint depends on TOKEN_TYPE:
+ it will either be:
+ (a) immediately after PREV_TOKEN_LOC, or
+
+ (b) immediately before the primary location within RICHLOC (taken to
+ be that of the token following where the token was expected).
+
+ If we manage to add a fix-it hint, then the location of the
+ fix-it hint is likely to be more useful as the primary location
+ of the diagnostic than that of the following token, so we swap
+ these locations.
+
+ For example, given this bogus code:
+ 123456789012345678901234567890
+ 1 | int missing_semicolon (void)
+ 2 | {
+ 3 | return 42
+ 4 | }
+
+ we will emit:
+
+ "expected ';' before '}'"
+
+ RICHLOC's primary location is at the closing brace, so before "swapping"
+ we would emit the error at line 4 column 1:
+
+ 123456789012345678901234567890
+ 3 | return 42 |< fix-it hint emitted for this line
+ | ; |
+ 4 | } |< "expected ';' before '}'" emitted at this line
+ | ^ |
+
+ It's more useful for the location of the diagnostic to be at the
+ fix-it hint, so we swap the locations, so the primary location
+ is at the fix-it hint, with the old primary location inserted
+ as a secondary location, giving this, with the error at line 3
+ column 12:
+
+ 123456789012345678901234567890
+ 3 | return 42 |< "expected ';' before '}'" emitted at this line,
+ | ^ | with fix-it hint
+ 4 | ; |
+ | } |< secondary range emitted here
+ | ~ |. */
+
+void
+maybe_suggest_missing_token_insertion (rich_location *richloc,
+ enum cpp_ttype token_type,
+ location_t prev_token_loc)
+{
+ gcc_assert (richloc);
+
+ enum missing_token_insertion_kind mtik
+ = get_missing_token_insertion_kind (token_type);
+
+ switch (mtik)
+ {
+ default:
+ gcc_unreachable ();
+ break;
+
+ case MTIK_IMPOSSIBLE:
+ return;
+
+ case MTIK_INSERT_BEFORE_NEXT:
+ /* Attempt to add the fix-it hint before the primary location
+ of RICHLOC. */
+ richloc->add_fixit_insert_before (cpp_type2name (token_type, 0));
+ break;
+
+ case MTIK_INSERT_AFTER_PREV:
+ /* Attempt to add the fix-it hint after PREV_TOKEN_LOC. */
+ richloc->add_fixit_insert_after (prev_token_loc,
+ cpp_type2name (token_type, 0));
+ break;
+ }
+
+ /* If we were successful, use the fix-it hint's location as the
+ primary location within RICHLOC, adding the old primary location
+ back as a secondary location. */
+ if (!richloc->seen_impossible_fixit_p ())
+ {
+ fixit_hint *hint = richloc->get_last_fixit_hint ();
+ location_t hint_loc = hint->get_start_loc ();
+ location_t old_loc = richloc->get_loc ();
+
+ richloc->set_range (line_table, 0, hint_loc, true);
+ richloc->add_range (old_loc, false);
+ }
+}
+
#if CHECKING_P
namespace selftest {
extern void add_no_sanitize_value (tree node, unsigned int flags);
extern void maybe_add_include_fixit (rich_location *, const char *);
+extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
+ enum cpp_ttype token_type,
+ location_t prev_token_loc);
#if CHECKING_P
namespace selftest {
+2017-10-12 David Malcolm <dmalcolm@redhat.com>
+
+ * c-parser.c (c_parser_require): Add "type_is_unique" param and
+ use it to guard calls to maybe_suggest_missing_token_insertion.
+ (c_parser_parms_list_declarator): Override default value of new
+ "type_is_unique" param to c_parser_require.
+ (c_parser_asm_statement): Likewise.
+ * c-parser.h (c_parser_require): Add "type_is_unique" param,
+ defaulting to true.
+
2017-10-11 Nathan Sidwell <nathan@acm.org>
* c-decl.c (grokdeclarator): Check HAS_DECL_ASSEMBLER_NAME_P too.
If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
within any error as the location of an "opening" token matching
the close token TYPE (e.g. the location of the '(' when TYPE is
- CPP_CLOSE_PAREN). */
+ CPP_CLOSE_PAREN).
+
+ If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
+ one type (e.g. "expected %<)%>") and thus it may be reasonable to
+ attempt to generate a fix-it hint for the problem.
+ Otherwise msgid describes multiple token types (e.g.
+ "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
+ generate a fix-it hint. */
bool
c_parser_require (c_parser *parser,
enum cpp_ttype type,
const char *msgid,
- location_t matching_location)
+ location_t matching_location,
+ bool type_is_unique)
{
if (c_parser_next_token_is (parser, type))
{
location_t next_token_loc = c_parser_peek_token (parser)->location;
gcc_rich_location richloc (next_token_loc);
+ /* Potentially supply a fix-it hint, suggesting to add the
+ missing token immediately after the *previous* token.
+ This may move the primary location within richloc. */
+ if (!parser->error && type_is_unique)
+ maybe_suggest_missing_token_insertion (&richloc, type,
+ parser->last_token_location);
+
/* If matching_location != UNKNOWN_LOCATION, highlight it.
Attempt to consolidate diagnostics by printing it as a
secondary range within the main diagnostic. */
return get_parm_info (false, expr);
}
if (!c_parser_require (parser, CPP_COMMA,
- "expected %<;%>, %<,%> or %<)%>"))
+ "expected %<;%>, %<,%> or %<)%>",
+ UNKNOWN_LOCATION, false))
{
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
return NULL;
if (!c_parser_require (parser, CPP_COLON,
is_goto
? G_("expected %<:%>")
- : G_("expected %<:%> or %<)%>")))
+ : G_("expected %<:%> or %<)%>"),
+ UNKNOWN_LOCATION, is_goto))
goto error_close_paren;
/* Once past any colon, we're no longer a simple asm. */
extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned int n);
extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
const char *msgid,
- location_t matching_location = UNKNOWN_LOCATION);
+ location_t matching_location = UNKNOWN_LOCATION,
+ bool type_is_unique=true);
extern bool c_parser_error (c_parser *parser, const char *gmsgid);
extern void c_parser_consume_token (c_parser *parser);
extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
+2017-10-12 David Malcolm <dmalcolm@redhat.com>
+
+ * parser.c (get_required_cpp_ttype): New function.
+ (cp_parser_error_1): Call it, using the result to call
+ maybe_suggest_missing_token_insertion.
+
2017-10-12 David Malcolm <dmalcolm@redhat.com>
* parser.c (get_matching_symbol): Move to before...
}
}
+/* Attempt to convert TOKEN_DESC from a required_token to an
+ enum cpp_ttype, returning CPP_EOF if there is no good conversion. */
+
+static enum cpp_ttype
+get_required_cpp_ttype (required_token token_desc)
+{
+ switch (token_desc)
+ {
+ case RT_SEMICOLON:
+ return CPP_SEMICOLON;
+ case RT_OPEN_PAREN:
+ return CPP_OPEN_PAREN;
+ case RT_CLOSE_BRACE:
+ return CPP_CLOSE_BRACE;
+ case RT_OPEN_BRACE:
+ return CPP_OPEN_BRACE;
+ case RT_CLOSE_SQUARE:
+ return CPP_CLOSE_SQUARE;
+ case RT_OPEN_SQUARE:
+ return CPP_OPEN_SQUARE;
+ case RT_COMMA:
+ return CPP_COMMA;
+ case RT_COLON:
+ return CPP_COLON;
+ case RT_CLOSE_PAREN:
+ return CPP_CLOSE_PAREN;
+
+ default:
+ /* Use CPP_EOF as a "no completions possible" code. */
+ return CPP_EOF;
+ }
+}
+
+
/* Subroutine of cp_parser_error and cp_parser_required_error.
Issue a diagnostic of the form
This bypasses the check for tentative passing, and potentially
adds material needed by cp_parser_required_error.
- If MISSING_TOKEN_DESC is not RT_NONE, and MATCHING_LOCATION is not
- UNKNOWN_LOCATION, then we have an unmatched symbol at
- MATCHING_LOCATION; highlight this secondary location. */
+ If MISSING_TOKEN_DESC is not RT_NONE, then potentially add fix-it hints
+ suggesting insertion of the missing token.
+
+ Additionally, if MATCHING_LOCATION is not UNKNOWN_LOCATION, then we
+ have an unmatched symbol at MATCHING_LOCATION; highlight this secondary
+ location. */
static void
cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
if (missing_token_desc != RT_NONE)
{
+ /* Potentially supply a fix-it hint, suggesting to add the
+ missing token immediately after the *previous* token.
+ This may move the primary location within richloc. */
+ enum cpp_ttype ttype = get_required_cpp_ttype (missing_token_desc);
+ location_t prev_token_loc
+ = cp_lexer_previous_token (parser->lexer)->location;
+ maybe_suggest_missing_token_insertion (&richloc, ttype, prev_token_loc);
+
/* If matching_location != UNKNOWN_LOCATION, highlight it.
Attempt to consolidate diagnostics by printing it as a
secondary range within the main diagnostic. */
+2017-10-12 David Malcolm <dmalcolm@redhat.com>
+
+ * c-c++-common/cilk-plus/AN/parser_errors.c: Update expected
+ output to reflect changes to reported locations of missing
+ symbols.
+ * c-c++-common/cilk-plus/AN/parser_errors2.c: Likewise.
+ * c-c++-common/cilk-plus/AN/parser_errors3.c: Likewise.
+ * c-c++-common/cilk-plus/AN/pr61191.c: Likewise.
+ * c-c++-common/gomp/pr63326.c: Likewise.
+ * c-c++-common/missing-close-symbol.c: Likewise, also update for
+ new fix-it hints.
+ * c-c++-common/missing-symbol.c: Likewise, also add test coverage
+ for missing colon in ternary operator.
+ * g++.dg/cpp1y/digit-sep-neg.C: Likewise.
+ * g++.dg/cpp1y/pr65202.C: Likewise.
+ * g++.dg/missing-symbol-2.C: New test case.
+ * g++.dg/other/do1.C: Update expected output to reflect
+ changes to reported locations of missing symbols.
+ * g++.dg/parse/error11.C: Likewise.
+ * g++.dg/template/error11.C: Likewise.
+ * gcc.dg/missing-symbol-2.c: New test case.
+ * gcc.dg/missing-symbol-3.c: New test case.
+ * gcc.dg/noncompile/940112-1.c: Update expected output to reflect
+ changes to reported locations of missing symbols.
+ * gcc.dg/noncompile/971104-1.c: Likewise.
+ * obj-c++.dg/exceptions-6.mm: Likewise.
+ * obj-c++.dg/pr48187.mm: Likewise.
+ * objc.dg/exceptions-6.m: Likewise.
+
2017-10-12 Martin Sebor <msebor@redhat.com>
PR other/82301
array2[:] = array2[: ; /* { dg-error "expected ']'" } */
- return 0;
-} /* { dg-error "expected ';' before" "" { target c } } */
+ return 0; /* { dg-error "expected ';' before" "" { target c } } */
+}
array2[:] = array2[1:2:] ; /* { dg-error "expected expression before" "" { target c } } */
/* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */
+ /* { dg-error "expected ';' before" "" { target c } .-2 } */
- return 0; /* { dg-error "expected ';' before" "" { target c } } */
+ return 0;
}
array2[:] = array2[1: :] ; /* { dg-error "expected expression before" "" { target c } } */
/* { dg-error "expected primary-expression before" "" { target c++ } .-1 } */
+ /* { dg-error "expected ';' before" "" { target c } .-2 } */
- return 0; /* { dg-error "expected ';' before" "" { target c } } */
+ return 0;
}
return __sec_reduce_add((B[0:500])(; /* { dg-error "called object" "" { target c } } */
/* { dg-error "expected expression before ';' token" "" { target c } .-1 } */
/* { dg-error "expected primary-expression before ';' token" "" { target c++ } .-2 } */
-} /* { dg-error "expected" "" { target c } } */
+/* { dg-error "expected" "" { target c } .-3 } */
+}
{
do
#pragma omp barrier /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp flush /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp taskwait /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp taskyield /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
#pragma omp parallel
{
do
#pragma omp cancel parallel /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
#pragma omp parallel
{
do
#pragma omp cancellation point parallel /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
#pragma omp for ordered(1)
for (i = 0; i < 16; i++)
{
do
#pragma omp ordered depend(source) /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp ordered depend(sink: i-1) /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
}
{
do
#pragma omp target enter data map(to:i) /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp target update to(i) /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
{
do
#pragma omp target exit data map(from:i) /* { dg-error "may only be used in compound statements" } */
- while (0);
+ while (0); /* { dg-error "before" "" { target c++ } } */
} /* { dg-error "before" "" { target c++ } } */
}
/* { dg-begin-multiline-output "" }
_Static_assert(sizeof(int) >= sizeof(char), "msg";
~ ^
+ )
{ dg-end-multiline-output "" } */
}
/* { dg-begin-multiline-output "" }
"msg";
^
+ )
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
_Static_assert(sizeof(int) >= sizeof(char),
int missing_close_paren_in_switch (int i)
{
- switch (i /* { dg-message "10: to match this '\\('" } */
- { /* { dg-error "5: expected '\\)' before '.' token" } */
- /* { dg-begin-multiline-output "" }
- {
- ^
- { dg-end-multiline-output "" } */
+ switch (i /* { dg-error "12: expected '\\)' before '.' token" } */
+ {
/* { dg-begin-multiline-output "" }
switch (i
- ^
+ ~ ^
+ )
+ {
+ ~
{ dg-end-multiline-output "" } */
case 0:
void missing_close_paren_in_if (void)
{
if (foo () /* { dg-line start_of_if } */
- && bar ()
- { /* { dg-error "5: expected '\\)' before '.' token" } */
+ && bar () /* { dg-error "16: expected '\\)' before '.' token" } */
+ {
/* { dg-begin-multiline-output "" }
+ && bar ()
+ ^
+ )
{
- ^
+ ~
{ dg-end-multiline-output "" } */
/* { dg-message "6: to match this '\\('" "" { target *-*-* } start_of_if } */
/* { dg-begin-multiline-output "" }
if (foo ()
^
- { dg-end-multiline-output "" } */
+ { dg-end-multiline-output "" } */
}
-
} /* { dg-error "1: expected" } */
/* { dg-begin-multiline-output "" }
}
^
{ dg-end-multiline-output "" } */
+
+int missing_colon_in_ternary (int flag)
+{
+ return flag ? 42 0; /* { dg-error "expected ':' before numeric constant" } */
+ /* { dg-begin-multiline-output "" }
+ return flag ? 42 0;
+ ^~
+ :
+ { dg-end-multiline-output "" } */
+}
}
// { dg-error "exponent has no digits" "exponent has no digits" { target *-*-* } 21 }
-// { dg-error "expected ';' before" "expected ';' before" { target *-*-* } 14 }
-// { dg-error "expected ';' before" "expected ';' before" { target *-*-* } 25 }
+// { dg-error "expected ';' before" "expected ';' before" { target *-*-* } 13 }
+// { dg-error "expected ';' before" "expected ';' before" { target *-*-* } 24 }
int main()
{
foo<ns::bar> f;
- adl::swap(f, f)
-} // { dg-error "" }
+ adl::swap(f, f) // { dg-error "expected ';'" }
+} // { dg-error "expected '.'" "expected end of namespace" }
--- /dev/null
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+extern int foo (void);
+
+void missing_open_paren (void)
+{
+ if foo ()) /* { dg-error "expected '\\(' before 'foo'" } */
+ {
+ }
+ /* { dg-begin-multiline-output "" }
+ if foo ())
+ ^~~
+ (
+ { dg-end-multiline-output "" } */
+}
+
+
+void missing_close_square (void)
+{
+ const char test [42; /* { dg-error "22: expected ']' before ';' token" } */
+ /* { dg-begin-multiline-output "" }
+ const char test [42;
+ ^
+ ]
+ { dg-end-multiline-output "" } */
+}
+
+int missing_semicolon (void)
+{
+ return 42 /* { dg-error "expected ';'" } */
+}
+/* { dg-begin-multiline-output "" }
+ return 42
+ ^
+ ;
+ }
+ ~
+ { dg-end-multiline-output "" } */
+
+
+int missing_colon_in_switch (int val)
+{
+ switch (val)
+ {
+ case 42 /* { dg-error "expected ':' before 'return'" } */
+ return 42;
+ /* { dg-begin-multiline-output "" }
+ case 42
+ ^
+ :
+ return 42;
+ ~~~~~~
+ { dg-end-multiline-output "" } */
+
+ default:
+ return val;
+ }
+}
void init ()
{
- do { } while (0)
- obj = 0; // { dg-error "expected|not declared" }
+ do { } while (0) // { dg-error "expected ';'" }
+ obj = 0; // { dg-error "not declared" }
}
Foo[:B> k1; // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" }
// { dg-error "6:missing template arguments before" "template" { target *-*-* } 51 }
// { dg-error "9:expected primary-expression before ':' token" "primary" { target *-*-* } 51 }
-// { dg-error "9:expected '\]' before ':' token" "backslash" { target *-*-* } 51 }
+// { dg-error "8:expected '\]' before ':' token" "backslash" { target *-*-* } 51 }
// { dg-error "6:missing template arguments before" "template" { target *-*-* } 52 }
// { dg-error "7:expected primary-expression before ':' token" "primary" { target *-*-* } 52 }
// { dg-error "7:expected '\]' before ':' token" "backslash" { target *-*-* } 52 }
// PR c++/12132
inline template <int> void foo () {} // { dg-error "<" }
-void abort (); // { dg-error ";" }
+void abort (); // { dg-error ";" "" { target *-*-* } .-1 }
--- /dev/null
+/* { dg-options "-fdiagnostics-show-caret -Wno-switch-unreachable" } */
+
+extern int foo (void);
+
+void missing_open_paren (void)
+{
+ if foo ()) /* { dg-line missing_open_paren } */
+ {
+ }
+ /* { dg-error "expected '\\(' before 'foo'" "" { target c } missing_open_paren } */
+ /* { dg-begin-multiline-output "" }
+ if foo ())
+ ^~~
+ (
+ { dg-end-multiline-output "" } */
+ /* { dg-error "expected statement before '\\)' token" "" { target c } missing_open_paren } */
+ /* { dg-begin-multiline-output "" }
+ if foo ())
+ ^
+ { dg-end-multiline-output "" } */
+}
+
+void missing_close_square (void)
+{
+ const char test [42; /* { dg-error "22: expected ']' before ';' token" } */
+ /* { dg-begin-multiline-output "" }
+ const char test [42;
+ ^
+ ]
+ { dg-end-multiline-output "" } */
+}
+
+int missing_semicolon (void)
+{
+ return 42 /* { dg-error "expected ';'" } */
+}
+/* { dg-begin-multiline-output "" }
+ return 42
+ ^
+ ;
+ }
+ ~
+ { dg-end-multiline-output "" } */
+
+
+/* We don't offer a fix-it hint for this case in C, as it could be
+ colon or ellipsis.
+ TODO: we could be smarter about error-recovery here; given the
+ return perhaps we could assume a missing colon. */
+
+int missing_colon_in_switch (int val)
+{
+ switch (val)
+ {
+ case 42
+ return 42; /* { dg-error "expected ':' or '...' before 'return'" } */
+ /* { dg-begin-multiline-output "" }
+ return 42;
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+
+ default:
+ return val;
+ }
+}
+
+/* { dg-begin-multiline-output "" }
+ int dummy;
+ ^~~
+ { dg-end-multiline-output "" } */
+int dummy;/* { dg-error "expected declaration or statement at end of input" "" { target c } } */
--- /dev/null
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+/* A sequence of bogus _Static_assert.
+ We can offer fix-it hints for some of these, but not all. */
+
+void test_static_assert_1 (void)
+{
+ _Static_assert sizeof(int) >= sizeof(char); /* { dg-error "expected '\\(' before 'sizeof'" } */
+ /* { dg-begin-multiline-output "" }
+ _Static_assert sizeof(int) >= sizeof(char);
+ ^~~~~~
+ (
+ { dg-end-multiline-output "" } */
+}
+
+void test_static_assert_2 (void)
+{
+ _Static_assert(sizeof(int) >= sizeof(char); /* { dg-error "expected ',' before ';' token" } */
+ /* { dg-begin-multiline-output "" }
+ _Static_assert(sizeof(int) >= sizeof(char);
+ ^
+ ,
+ { dg-end-multiline-output "" } */
+}
+
+void test_static_assert_3 (void)
+{
+ _Static_assert(sizeof(int) >= sizeof(char),; /* { dg-error "expected string literal before ';' token" } */
+ /* { dg-begin-multiline-output "" }
+ _Static_assert(sizeof(int) >= sizeof(char),;
+ ^
+ { dg-end-multiline-output "" } */
+}
+
+void test_static_assert_4 (void)
+{
+ _Static_assert(sizeof(int) >= sizeof(char), "msg"; /* { dg-error "expected '\\)' before ';' token" } */
+ /* { dg-begin-multiline-output "" }
+ _Static_assert(sizeof(int) >= sizeof(char), "msg";
+ ~ ^
+ )
+ { dg-end-multiline-output "" } */
+}
+
+/* The final one is correct. */
+
+void test_static_assert_5 (void)
+{
+ _Static_assert(sizeof(int) >= sizeof(char), "msg");
+}
{
double e = 1;
e = 1;
- return (e)
-} /* { dg-error "parse error|syntax error|expected" } */
+ return (e) /* { dg-error "parse error|syntax error|expected" } */
+}
printf("%s had processes sleeping on it!\n",
({ "MUTEX ", "BARB_SEM 1", "BARB_SEM 2", "CUST_SEM 1",
"CUST_SEM 2", "WAIT_SEM 1", "WAIT_SEM 2", "WAIT_SEM 3",
- "WAIT_SEM 4"} /* { dg-error "parse error|syntax error|expected" } */
- [( sb.sem_num )]) ); /* { dg-error "expected" } */
+ "WAIT_SEM 4"} /* { dg-error "expected" } */
+ [( sb.sem_num )]) );
}
@throw object; /* Ok */
@throw; /* { dg-error ".@throw. .rethrow. used outside of a @catch block" } */
@throw (object); /* Ok. */
- @throw (id)0
-} /* { dg-error "expected" } */
+ @throw (id)0 /* { dg-error "expected" } */
+}
void test2 (id object)
{
@throw object); /* { dg-error "expected" } */
@throw (...); /* { dg-error "expected" } */
@throw (); /* { dg-error "expected" } */
- @throw
+ @throw /* { dg-error "expected" } */
} /* { dg-error "expected" } */
void test3 (id object1, id object2)
/* { dg-do compile } */
@interface A
-{
+{ /* { dg-error "xpected" } */
] /* { dg-error "xpected" } */
}
@end
@interface B
-{
+{ /* { dg-error "xpected" } */
]; /* { dg-error "xpected" } */
}
@end
@interface C
-{
+{ /* { dg-error "xpected" } */
]; /* { dg-error "xpected" } */
int x;
}
@interface D
{
- (
+ ( /* { dg-error "xpected" } */
} /* { dg-error "xpected" } */
@end
@throw object; /* Ok */
@throw; /* { dg-error ".@throw. .rethrow. used outside of a @catch block" } */
@throw (object); /* Ok. */
- @throw (id)0
-} /* { dg-error "expected" } */
+ @throw (id)0 /* { dg-error "expected" } */
+}
void test2 (id object)
{