================
@@ -1880,16 +1880,70 @@ Sema::ConditionResult 
Parser::ParseCXXCondition(StmtResult *InitStmt,
     return Sema::ConditionError();
   }
 
+  if (!getLangOpts().CPlusPlus && Tok.is(tok::kw___extension__)) {
+    // In C, the first clause of a condition may be a declaration used as an
+    // init-statement (C2y), and that declaration may be prefixed by one or 
more
+    // __extension__ markers. Consume them up front -- mirroring 
block-statement
+    // parsing -- so the disambiguation below sees the real start of the
+    // declaration. The markers also silence extension diagnostics for the rest
+    // of the condition, including the diagnostic for the init-statement
+    // extension itself.
+    std::optional<ExtensionRAIIObject> ExtensionGuard;
+    ExtensionGuard.emplace(Diags);
+    while (TryConsumeToken(tok::kw___extension__))
+      ;
+  }
+
   ParsedAttributes attrs(AttrFactory);
-  MaybeParseCXX11Attributes(attrs);
+  bool ParsedAttrs = MaybeParseCXX11Attributes(attrs);
+  if (!getLangOpts().CPlusPlus)
+    ParsedAttrs = MaybeParseGNUAttributes(attrs) || ParsedAttrs;
 
   const auto WarnOnInit = [this, &CK] {
-    Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
-                                ? diag::warn_cxx14_compat_init_statement
-                                : diag::ext_init_statement)
-        << (CK == Sema::ConditionKind::Switch);
+    if (getLangOpts().CPlusPlus)
+      Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+                                  ? diag::warn_cxx14_compat_init_statement
+                                  : diag::ext_init_statement)
+          << (CK == Sema::ConditionKind::Switch);
+    else
+      Diag(Tok.getLocation(), getLangOpts().C2y
+                                  ? diag::warn_c2y_compat_decl_statement
+                                  : diag::ext_c2y_decl_statement)
+          << (CK == Sema::ConditionKind::Switch);
   };
 
+  if (!getLangOpts().CPlusPlus) {
+    if (isDeclarationStatement() && !isCXXSimpleDeclaration(false)) {
+      // Accept a C2y declaration, *only* if it's not a simple declaration.
+      WarnOnInit();
+      DeclGroupPtrTy DG;
+      SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
+      ParsedAttributes DeclSpecAttrs(AttrFactory);
+      // C2y replaces the init-statement in C++17 to be a declaration instead.
+      DG = ParseDeclaration(DeclaratorContext::SelectionInit, DeclEnd, attrs,
+                            DeclSpecAttrs);
+      StmtResult DeclStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd);
+      if (InitStmt == nullptr)
+        Diag(DeclStmt.get()->getBeginLoc(), diag::err_expected_expression)
----------------
AaronBallman wrote:

`ActOnDeclStmt` can return unusable results, so this needs to handle the case 
where the decl statement is unusable (I think we're missing test coverage 
because I'd have expected a crash here in that case).

https://github.com/llvm/llvm-project/pull/198244
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to