Skip to content

Commit b147019

Browse files
[clang] Preserve externs following broken declarations (llvm#161641)
Treat them as namespaces: if they are at the beginning of the line, they are likely a good recovery point. For instance, in ```cpp 1.3.0 extern "C" { extern int foo(); extern "C++" { namespace bar { void baz(); }; } } namespace {} ``` Everything until `namespace`... is gone from the AST. Headers (like libc's C++ `math.h`) can be included from an `extern "C"` context, and they do an `extern "C++"` back again before including C++ headers (like `__type_traits`). However, a malformed declaration just before the include (as the orphan `1.3.0` in the example) causes everything from these standard headers to go missing. This patch updates the heuristic to try to recover from the first `extern` keyword seen, pretty much as it is done for `namespace`. CPP-4478
1 parent 706b790 commit b147019

File tree

3 files changed

+13
-0
lines changed

3 files changed

+13
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ Bug Fixes to AST Handling
446446
legal representation. This is fixed because ElaboratedTypes don't exist anymore. (#GH43179) (#GH68670) (#GH92757)
447447
- Fix unrecognized html tag causing undesirable comment lexing (#GH152944)
448448
- Fix comment lexing of special command names (#GH152943)
449+
- Use `extern` as a hint to continue parsing when recovering from a malformed declaration.
449450

450451
Miscellaneous Bug Fixes
451452
^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Parse/ParseDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,9 @@ void Parser::SkipMalformedDecl() {
20832083
return;
20842084
break;
20852085

2086+
case tok::kw_extern:
2087+
// 'extern' at the start of a line is almost certainly a good
2088+
// place to pick back up parsing
20862089
case tok::kw_namespace:
20872090
// 'namespace' at the start of a line is almost certainly a good
20882091
// place to pick back up parsing, except in an Objective-C
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang_cc1 -verify %s
2+
3+
3.2 // expected-error {{expected unqualified-id}}
4+
5+
extern "C" {
6+
typedef int Int;
7+
}
8+
9+
Int foo(); // Ok

0 commit comments

Comments
 (0)