[clang] [Clang] Fix infinite loop on '::' inside parens in C mode (PR #195377)

Petr Beneš via cfe-commits cfe-commits at lists.llvm.org
Sun May 3 09:27:43 PDT 2026


https://github.com/wbenny updated https://github.com/llvm/llvm-project/pull/195377

>From 4a6225dbca4b6d91bb1d7f2f0c7ec58437f48f4e Mon Sep 17 00:00:00 2001
From: root <w.benny at outlook.com>
Date: Sat, 2 May 2026 01:06:25 +0200
Subject: [PATCH] [Clang] Fix infinite loop on '::' inside parens in C mode

`Parser::isTypeSpecifierQualifier` was recursing on the same `::` token
forever when called from `isTypeIdInParens` while parsing a parenthesized
expression in C mode.

Fixes: #195367
---
 clang/docs/ReleaseNotes.rst                   | 1 +
 clang/lib/Parse/ParseDecl.cpp                 | 2 ++
 clang/test/Parser/c-global-scope-coloncolon.c | 5 +++++
 3 files changed, 8 insertions(+)
 create mode 100644 clang/test/Parser/c-global-scope-coloncolon.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6b66a4fa1a261..400824a24a489 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -511,6 +511,7 @@ Bug Fixes in This Version
 - Clang now emits an error for friend declarations of lambda members. (#GH26540)
 - Fixed a crash caused by lambda capture handling in delayed default arguments. (#GH176534)
 - Fixed a crash when parsing invalid ``static_assert`` declarations with string-literal messages (#GH187690).
+- Fixed an infinite loop in the parser when a ``::`` token appears inside a parenthesized expression in C mode (e.g. ``int x = (::h);``). (#GH195367)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 434a1a8fcb223..b5f06c9e01077 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5632,6 +5632,8 @@ bool Parser::isTypeSpecifierQualifier(const Token &Tok) {
     return isTypeSpecifierQualifier(getCurToken());
 
   case tok::coloncolon:   // ::foo::bar
+    if (!getLangOpts().CPlusPlus && !getLangOpts().ObjC)
+      return false;
     if (NextToken().is(tok::kw_new) ||    // ::new
         NextToken().is(tok::kw_delete))   // ::delete
       return false;
diff --git a/clang/test/Parser/c-global-scope-coloncolon.c b/clang/test/Parser/c-global-scope-coloncolon.c
new file mode 100644
index 0000000000000..d0336aaccc71a
--- /dev/null
+++ b/clang/test/Parser/c-global-scope-coloncolon.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=c   -x c   %s
+// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s
+
+int x = (::h); // c-error {{expected expression}} \
+                  cxx-error {{no member named 'h' in the global namespace}}



More information about the cfe-commits mailing list