[PATCH] D132568: [clang][Sema] check default argument promotions for printf

2022-08-27 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 456111.
inclyc added a comment.

Delete extra newline.

Currently this patch has not fully implemented `wchar_t` related support, this
type seems to be even platform dependent in C language, if possible, maybe we
can consider support in subsequent patches?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132568/new/

https://reviews.llvm.org/D132568

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/FormatString.h
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-freebsd.c
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -819,13 +819,7 @@
 
   Unclear type relationship between a format specifier and its argument
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf";>N2562
-  
-Partial
-  Clang supports diagnostics checking format specifier validity, but
-  does not yet account for all of the changes in this paper, especially
-  regarding length modifiers like h and hh.
-
-  
+  Clang 16
 
 
 
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -830,3 +830,57 @@
   printf_arg2("foo", "%s string %i\n", "aaa", 123);
   printf_arg2("%s string\n", "foo", "bar"); // expected-warning{{data argument not used by format string}}
 }
+
+void test_promotion(void) {
+  // Default argument promotions for *printf in N2562
+  // https://github.com/llvm/llvm-project/issues/57102
+  // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf
+  int i;
+  signed char sc;
+  unsigned char uc;
+  char c;
+  short ss;
+  unsigned short us;
+
+  printf("%hhd %hd %d %hhd %hd %d", i, i, i, sc, sc, sc); // no-warning
+  printf("%hhd %hd %d %hhd %hd %d", uc, uc, uc, c, c, c); // no-warning
+
+  // %ld %lld %llx
+  printf("%ld", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+  printf("%lld", i); // expected-warning{{format specifies type 'long long' but the argument has type 'int'}}
+  printf("%ld", sc); // expected-warning{{format specifies type 'long' but the argument has type 'signed char'}}
+  printf("%lld", sc); // expected-warning{{format specifies type 'long long' but the argument has type 'signed char'}}
+  printf("%ld", uc); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned char'}}
+  printf("%lld", uc); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned char'}}
+  printf("%llx", i); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'int'}}
+
+  // ill formed spec for floats
+  printf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}}
+  sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+
+  // for %hhd and `short` they are compatible by promotions but more likely misuse
+  printf("%hd", ss); // no-warning
+  printf("%hhd", ss); // expected-warning{{format specifies type 'char' but the argument has type 'short'}}
+  printf("%hu", us); // no-warning
+  printf("%hhu", ss); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}}
+
+  // floats & integers are not compatible
+  printf("%f", i); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
+  printf("%f", sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+  printf("%f", uc); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}}
+  printf("%f", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
+  printf("%f", ss); // expected-warning{{format specifies type 'double' but the argument has type 'short'}}
+  printf("%f", us); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned short'}}
+
+  // character literals
+  // In C language engineering practice, printing a character literal with %hhd or %d is common, but %hd may be misuse.
+  printf("%hhu", 'a'); // no-warning
+  printf("%hhd", 'a'); // no-warning
+  printf("%hd", 'a'); // expected-warning{{format specifies type 'short' but the argument has type 'char'}}
+  printf("%hu", 'a'); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'char'}}
+  printf("%d", 'a'); // no-warning
+  printf("%u", 'a'); // no-warning
+  
+  // pointers
+  printf("%s", i); // expected-warning{{format specifies type 'char *' but the a

[PATCH] D132952: [Sema] disable -Wvla for function array parameters

2022-08-30 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
inclyc added a reviewer: aaron.ballman.
Herald added a project: All.
inclyc added reviewers: rsmith, clang-language-wg.
inclyc published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Fixes: https://github.com/llvm/llvm-project/issues/57098


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D132952

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaType.cpp
  clang/test/Sema/warn-vla.c


Index: clang/test/Sema/warn-vla.c
===
--- clang/test/Sema/warn-vla.c
+++ clang/test/Sema/warn-vla.c
@@ -5,8 +5,18 @@
   int v[n]; // expected-warning {{variable length array}}
 }
 
-void test2(int n, int v[n]) { // expected-warning {{variable length array}}
+void test2(int n, int v[n]) { // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
 }
 
-void test3(int n, int v[n]); // expected-warning {{variable length array}}
+void test3(int n, int v[n]); // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
 
+void test4(int n, int v[][*]); // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2367,9 +2367,11 @@
 unsigned VLADiag;
 bool VLAIsError;
 bool IsVLA = false;
+bool SuppressNotICEVLA = false;
 
-VLADiagnoser(unsigned VLADiag, bool VLAIsError)
-: VLADiag(VLADiag), VLAIsError(VLAIsError) {}
+VLADiagnoser(unsigned VLADiag, bool VLAIsError, bool SuppressNotICEVLA)
+: VLADiag(VLADiag), VLAIsError(VLAIsError),
+  SuppressNotICEVLA(SuppressNotICEVLA) {}
 
 Sema::SemaDiagnosticBuilder diagnoseNotICEType(Sema &S, SourceLocation Loc,
QualType T) override {
@@ -2379,14 +2381,18 @@
 Sema::SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
SourceLocation Loc) override {
   IsVLA = !VLAIsError;
-  return S.Diag(Loc, VLADiag);
+  if (!SuppressNotICEVLA)
+return S.Diag(Loc, VLADiag);
+  return Sema::SemaDiagnosticBuilder(S);
 }
 
 Sema::SemaDiagnosticBuilder diagnoseFold(Sema &S,
  SourceLocation Loc) override {
   return S.Diag(Loc, diag::ext_vla_folded_to_constant);
 }
-  } Diagnoser(VLADiag, VLAIsError);
+  } Diagnoser(VLADiag, VLAIsError,
+  S.getCurScope()->isFunctionPrototypeScope() &&
+  VLADiag == diag::warn_vla_used);
 
   ExprResult R =
   S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser);
@@ -2528,7 +2534,9 @@
   llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
   if (!ArraySize) {
 if (ASM == ArrayType::Star) {
-  Diag(Loc, VLADiag);
+  if (!(getCurScope()->isFunctionPrototypeScope() &&
+VLADiag == diag::warn_vla_used))
+Diag(Loc, VLADiag);
   if (VLAIsError)
 return QualType();
 
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -1756,6 +1756,8 @@
   K_Deferred
 };
 
+// Special builder emitting no diagnostics
+SemaDiagnosticBuilder(Sema &S) : S(S) {}
 SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
   FunctionDecl *Fn, Sema &S);
 SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);


Index: clang/test/Sema/warn-vla.c
===
--- clang/test/Sema/warn-vla.c
+++ clang/test/Sema/warn-vla.c
@@ -5,8 +5,18 @@
   int v[n]; // expected-warning {{variable length array}}
 }
 
-void test2(int n, int v[n]) { // expected-warning {{variable length array}}
+void test2(int n, int v[n]) { // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
 }
 
-void test3(int n, int v[n]); // expected-warning {{variable length array}}
+void test3(int n, int v[n]); // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
 
+void test4(int n, int v[][*]); // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2367,9 +2367,11 @@
 unsigned VLADiag;
 bool VLAIsError;
 bool IsVLA = false;
+bool SuppressNotICEVLA = false;
 
-V

[PATCH] D132952: [Sema] disable -Wvla for function array parameters

2022-08-30 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/include/clang/Sema/Sema.h:1760
+// Special builder emitting no diagnostics
+SemaDiagnosticBuilder(Sema &S) : S(S) {}
 SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,

erichkeane wrote:
> I haven't looked particularly closely, but this doesn't seem right to me.  
> There is already the 'K_Nop' diagnostic Kind (see the line below), that we 
> should look at the uses of.
I've tried using the following constructor, I have to to pass in a series of 
redundant parameters (such as `DiagID` and `Loc`), which makes it strange to 
construct a Builder emitting no error message at all?

e.g.

```
Sema::SemaDiagnosticBuilder(Sema::SemaDiagnosticBuilder::Kind::K_Nop, Loc, 0,
  nullptr, S);
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132952/new/

https://reviews.llvm.org/D132952

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132568: [clang][Sema] check default argument promotions for printf

2022-08-31 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 457153.
inclyc added a comment.

Update comments according to review feedback


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132568/new/

https://reviews.llvm.org/D132568

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/FormatString.h
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-freebsd.c
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -819,13 +819,7 @@
 
   Unclear type relationship between a format specifier and its argument
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf";>N2562
-  
-Partial
-  Clang supports diagnostics checking format specifier validity, but
-  does not yet account for all of the changes in this paper, especially
-  regarding length modifiers like h and hh.
-
-  
+  Clang 16
 
 
 
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -830,3 +830,57 @@
   printf_arg2("foo", "%s string %i\n", "aaa", 123);
   printf_arg2("%s string\n", "foo", "bar"); // expected-warning{{data argument not used by format string}}
 }
+
+void test_promotion(void) {
+  // Default argument promotions for *printf in N2562
+  // https://github.com/llvm/llvm-project/issues/57102
+  // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf
+  int i;
+  signed char sc;
+  unsigned char uc;
+  char c;
+  short ss;
+  unsigned short us;
+
+  printf("%hhd %hd %d %hhd %hd %d", i, i, i, sc, sc, sc); // no-warning
+  printf("%hhd %hd %d %hhd %hd %d", uc, uc, uc, c, c, c); // no-warning
+
+  // %ld %lld %llx
+  printf("%ld", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+  printf("%lld", i); // expected-warning{{format specifies type 'long long' but the argument has type 'int'}}
+  printf("%ld", sc); // expected-warning{{format specifies type 'long' but the argument has type 'signed char'}}
+  printf("%lld", sc); // expected-warning{{format specifies type 'long long' but the argument has type 'signed char'}}
+  printf("%ld", uc); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned char'}}
+  printf("%lld", uc); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned char'}}
+  printf("%llx", i); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'int'}}
+
+  // ill formed spec for floats
+  printf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}}
+  sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+
+  // for %hhd and `short` they are compatible by promotions but more likely misuse
+  printf("%hd", ss); // no-warning
+  printf("%hhd", ss); // expected-warning{{format specifies type 'char' but the argument has type 'short'}}
+  printf("%hu", us); // no-warning
+  printf("%hhu", ss); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}}
+
+  // floats & integers are not compatible
+  printf("%f", i); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
+  printf("%f", sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+  printf("%f", uc); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}}
+  printf("%f", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
+  printf("%f", ss); // expected-warning{{format specifies type 'double' but the argument has type 'short'}}
+  printf("%f", us); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned short'}}
+
+  // character literals
+  // In C language engineering practice, printing a character literal with %hhd or %d is common, but %hd may be misuse.
+  printf("%hhu", 'a'); // no-warning
+  printf("%hhd", 'a'); // no-warning
+  printf("%hd", 'a'); // expected-warning{{format specifies type 'short' but the argument has type 'char'}}
+  printf("%hu", 'a'); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'char'}}
+  printf("%d", 'a'); // no-warning
+  printf("%u", 'a'); // no-warning
+  
+  // pointers
+  printf("%s", i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
+}
Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-sc

[PATCH] D132568: [clang][Sema] check default argument promotions for printf

2022-08-31 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe3bd67eddf65: [clang][Sema] check default argument 
promotions for printf (authored by inclyc).

Changed prior to commit:
  https://reviews.llvm.org/D132568?vs=457153&id=457157#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132568/new/

https://reviews.llvm.org/D132568

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/FormatString.h
  clang/lib/AST/FormatString.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-freebsd.c
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -819,13 +819,7 @@
 
   Unclear type relationship between a format specifier and its argument
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf";>N2562
-  
-Partial
-  Clang supports diagnostics checking format specifier validity, but
-  does not yet account for all of the changes in this paper, especially
-  regarding length modifiers like h and hh.
-
-  
+  Clang 16
 
 
 
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -830,3 +830,57 @@
   printf_arg2("foo", "%s string %i\n", "aaa", 123);
   printf_arg2("%s string\n", "foo", "bar"); // expected-warning{{data argument not used by format string}}
 }
+
+void test_promotion(void) {
+  // Default argument promotions for *printf in N2562
+  // https://github.com/llvm/llvm-project/issues/57102
+  // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf
+  int i;
+  signed char sc;
+  unsigned char uc;
+  char c;
+  short ss;
+  unsigned short us;
+
+  printf("%hhd %hd %d %hhd %hd %d", i, i, i, sc, sc, sc); // no-warning
+  printf("%hhd %hd %d %hhd %hd %d", uc, uc, uc, c, c, c); // no-warning
+
+  // %ld %lld %llx
+  printf("%ld", i); // expected-warning{{format specifies type 'long' but the argument has type 'int'}}
+  printf("%lld", i); // expected-warning{{format specifies type 'long long' but the argument has type 'int'}}
+  printf("%ld", sc); // expected-warning{{format specifies type 'long' but the argument has type 'signed char'}}
+  printf("%lld", sc); // expected-warning{{format specifies type 'long long' but the argument has type 'signed char'}}
+  printf("%ld", uc); // expected-warning{{format specifies type 'long' but the argument has type 'unsigned char'}}
+  printf("%lld", uc); // expected-warning{{format specifies type 'long long' but the argument has type 'unsigned char'}}
+  printf("%llx", i); // expected-warning{{format specifies type 'unsigned long long' but the argument has type 'int'}}
+
+  // ill formed spec for floats
+  printf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}}
+  sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+
+  // for %hhd and `short` they are compatible by promotions but more likely misuse
+  printf("%hd", ss); // no-warning
+  printf("%hhd", ss); // expected-warning{{format specifies type 'char' but the argument has type 'short'}}
+  printf("%hu", us); // no-warning
+  printf("%hhu", ss); // expected-warning{{format specifies type 'unsigned char' but the argument has type 'short'}}
+
+  // floats & integers are not compatible
+  printf("%f", i); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
+  printf("%f", sc); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
+  printf("%f", uc); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}}
+  printf("%f", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
+  printf("%f", ss); // expected-warning{{format specifies type 'double' but the argument has type 'short'}}
+  printf("%f", us); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned short'}}
+
+  // character literals
+  // In C language engineering practice, printing a character literal with %hhd or %d is common, but %hd may be misuse.
+  printf("%hhu", 'a'); // no-warning
+  printf("%hhd", 'a'); // no-warning
+  printf("%hd", 'a'); // expected-warning{{format specifies type 'short' but the argument has type 'char'}}
+  printf("%hu", 'a'); // expected-warning{{format specifies type 'unsigned short' but the argument has type 'char'}}
+  printf("%d", 'a'); // no-warning
+  printf("%u", 'a'); // no-warning
+  
+  // pointers
+  printf("%s", i); // expected-warning{{forma

[PATCH] D133085: [clang] trim trailing space in format tests. NFC

2022-08-31 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
inclyc added a reviewer: clang-language-wg.
Herald added a project: All.
inclyc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Found in https://reviews.llvm.org/D132568


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133085

Files:
  clang/test/FixIt/format.m
  clang/test/FixIt/format.mm
  clang/test/Sema/format-strings-scanf.c

Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-scanf.c
+++ clang/test/Sema/format-strings-scanf.c
@@ -12,7 +12,7 @@
   unsigned int : (int)0,   \
   unsigned short : (short)0,   \
   unsigned char : (signed char)0))
-typedef __SSIZE_TYPE__ ssize_t; 
+typedef __SSIZE_TYPE__ ssize_t;
 
 typedef __PTRDIFF_TYPE__ ptrdiff_t;
 #define __UNSIGNED_PTRDIFF_TYPE__  \
@@ -224,13 +224,13 @@
 
   ptrdiff_t p2 = 0;
   scanf("%td", &p2); // No warning.
-  
+
   double d2 = 0.;
   scanf("%td", &d2); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
 
   ptrdiff_t p3 = 0;
   scanf("%tn", &p3); // No warning.
-  
+
   double d3 = 0.;
   scanf("%tn", &d3); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
 }
Index: clang/test/FixIt/format.mm
===
--- clang/test/FixIt/format.mm
+++ clang/test/FixIt/format.mm
@@ -19,11 +19,11 @@
 
   NSLog(@"%C", wchar_data);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
Index: clang/test/FixIt/format.m
===
--- clang/test/FixIt/format.m
+++ clang/test/FixIt/format.m
@@ -37,7 +37,7 @@
   // CHECK: fix-it:"{{.*}}":{34:11-34:13}:"%s"
 }
 
-void test_object_correction (id x) {  
+void test_object_correction (id x) {
   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'id'}}
   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'id'}}
   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'id'}}
@@ -108,7 +108,7 @@
   NSLog(@"%c", c); // no-warning
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
 
-  
+
   NSLog(@"%s", s); // expected-warning{{format specifies type 'char *' but the argument has type 'signed char'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
 
@@ -197,11 +197,11 @@
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
 
   typedef unsigned short unichar;
-  
+
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", data ? 0x2F : 0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)("
@@ -239,7 +239,7 @@
 
   printf("%zd", 0.f); // expected-warning-re{{format specifies type 'ssize_t' (aka '{{.+}}') but the argument has type 'float'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
-  
+
   short x;
 #if !defined(__ANDROID__) && !defined(__Fuchsia__)
   printf("%zn", &x); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'short *'}}
@@ -266,7 +266,7 @@
 
   printf("%tu", 0.f); // expected-warning-re{{format specifies type 'unsigned ptrdiff_t' (aka '{{.+}}') but the argument has type 'float'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
-  
+
   ptrdiff_t p2 = 0;
   printf("%td", p2);  // No warning.
 
___
cfe-commits mailing list
cfe-commit

[PATCH] D133085: [clang] trim trailing space in format tests. NFC

2022-08-31 Thread YingChi Long via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5ee51e815425: [clang] trim trailing space in format tests. 
NFC (authored by inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133085/new/

https://reviews.llvm.org/D133085

Files:
  clang/test/FixIt/format.m
  clang/test/FixIt/format.mm
  clang/test/Sema/format-strings-scanf.c

Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-scanf.c
+++ clang/test/Sema/format-strings-scanf.c
@@ -12,7 +12,7 @@
   unsigned int : (int)0,   \
   unsigned short : (short)0,   \
   unsigned char : (signed char)0))
-typedef __SSIZE_TYPE__ ssize_t; 
+typedef __SSIZE_TYPE__ ssize_t;
 
 typedef __PTRDIFF_TYPE__ ptrdiff_t;
 #define __UNSIGNED_PTRDIFF_TYPE__  \
@@ -224,13 +224,13 @@
 
   ptrdiff_t p2 = 0;
   scanf("%td", &p2); // No warning.
-  
+
   double d2 = 0.;
   scanf("%td", &d2); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
 
   ptrdiff_t p3 = 0;
   scanf("%tn", &p3); // No warning.
-  
+
   double d3 = 0.;
   scanf("%tn", &d3); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}
 }
Index: clang/test/FixIt/format.mm
===
--- clang/test/FixIt/format.mm
+++ clang/test/FixIt/format.mm
@@ -19,11 +19,11 @@
 
   NSLog(@"%C", wchar_data);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'wchar_t'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:16-[[@LINE-1]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
Index: clang/test/FixIt/format.m
===
--- clang/test/FixIt/format.m
+++ clang/test/FixIt/format.m
@@ -37,7 +37,7 @@
   // CHECK: fix-it:"{{.*}}":{34:11-34:13}:"%s"
 }
 
-void test_object_correction (id x) {  
+void test_object_correction (id x) {
   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'id'}}
   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'id'}}
   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'id'}}
@@ -108,7 +108,7 @@
   NSLog(@"%c", c); // no-warning
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
 
-  
+
   NSLog(@"%s", s); // expected-warning{{format specifies type 'char *' but the argument has type 'signed char'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
 
@@ -197,11 +197,11 @@
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
 
   typedef unsigned short unichar;
-  
+
   NSLog(@"%C", 0x260300);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
-  
+
   NSLog(@"%C", data ? 0x2F : 0x260300); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)("
@@ -239,7 +239,7 @@
 
   printf("%zd", 0.f); // expected-warning-re{{format specifies type 'ssize_t' (aka '{{.+}}') but the argument has type 'float'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
-  
+
   short x;
 #if !defined(__ANDROID__) && !defined(__Fuchsia__)
   printf("%zn", &x); // expected-warning-re{{format specifies type 'ssize_t *' (aka '{{.+}}') but the argument has type 'short *'}}
@@ -266,7 +266,7 @@
 
   printf("%tu", 0.f); // expected-warning-re{{format specifies type 'unsigned ptrdiff_t' (aka '{{.+}}') but the argument has type 'float'}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%f"
-  
+
   ptrdiff_t p2 = 0;
   printf("%td", p2);  // No warning.
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.o

[PATCH] D133085: [clang] trim trailing space in format tests. NFC

2022-08-31 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

In D133085#3763198 , @ChuanqiXu wrote:

> Do you have commit access? If you have, I remember LLVM encourages to land 
> such fixes directly without reviewed. (+ @aaron.ballman to make sure)

Thanks! I'm just not sure whether these changes are necessary or not. :)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133085/new/

https://reviews.llvm.org/D133085

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133085: [clang] trim trailing space in format tests. NFC

2022-09-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Thank you for your patience and detailed explanation! Sorry for waste your time 
though (


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133085/new/

https://reviews.llvm.org/D133085

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133197: [clang] Fix crash when parsing scanf format string with missing arguments

2022-09-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a reviewer: aaron.ballman.
inclyc accepted this revision.
inclyc added a subscriber: aaron.ballman.
inclyc added a comment.
This revision is now accepted and ready to land.

Thanks @serge-sans-paille! Basically LGTM. Maybe we need to backport this patch 
though? @aaron.ballman


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133197/new/

https://reviews.llvm.org/D133197

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133248: [clang] Fix crash upon stray coloncolon token in C2x mode

2022-09-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Parse/ParseDecl.cpp:5340
+if (!getLangOpts().CPlusPlus)
+  return false;
 if (NextToken().is(tok::kw_new) ||// ::new

Maybe we can make a new `error` diagnostic definition and fire that here?



Comment at: clang/test/Parser/c2x-attributes.c:146
+// Ensure that '::' outside of attributes does not crash and is not treated as 
scope
+double n::v; // expected-error {{expected ';' after top level declarator}}

Could we improve this diagnostic message? 
```
expected ';' after top level declarator}
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133248/new/

https://reviews.llvm.org/D133248

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132952: [Sema] disable -Wvla for function array parameters

2022-09-04 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Sema/warn-vla.c:8-12
+void test2(int n, int v[n]) { // c99 no-warning
+#if __STDC_VERSION__ < 199901L
+// expected-warning@-2{{variable length arrays are a C99 feature}}
+#endif
 }

aaron.ballman wrote:
> The diagnostic there is rather unfortunate because we're not using a 
> variable-length array in this case.
Emm, I'm not clear about whether we should consider this a VLA, and generates 
`-Wvla-extensions`. Is `v[n]` literally a variable-length array? (in source 
code) So it seems to me that we should still report c89 incompatibility 
warnings?



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132952/new/

https://reviews.llvm.org/D132952

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D132952: [Sema] disable -Wvla for function array parameters

2022-09-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

> Yeah, that's a different way of delineating than I was thinking originally 
> and it's worth more thought. I was thinking the separation would be "this is 
> a VLA" (for people who want to avoid all VLA stack allocations due to the 
> security concerns) and "this is a portability concern" (for people who want 
> to port to older language standards, C++, other compilers).

I think it is a good idea to separate `-Wvla` into `-Wvla-portability`(warnings 
on portability) and `-Wvla-stack` (warnings on stack allocations, security 
issue). Report `-Wvla-portability` if compilers implementations in practice 
don't support any `vla` syntax especially in C89 mode and report `-Wvla-stack` 
if it causes stack allocations.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D132952/new/

https://reviews.llvm.org/D132952

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a project: All.
inclyc updated this revision to Diff 459034.
inclyc added a comment.
inclyc added reviewers: aaron.ballman, clang-language-wg.
inclyc published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Apply clang-format


https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm made very
clear that it is an UB having type definitions with in offsetof. After
this patch clang will reject any type definitions in __builtin_offsetof.

Fixes https://github.com/llvm/llvm-project/issues/57065

I'm not sure this is a correct bug fix, because adding a new bool state
to Parser just for supporting this seems ugly. I've tried creating a new
DeclaratorContext, though.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133574

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // expected-error{{'struct B' cannot be defined in '__builtin_offsetof'}}
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16254,7 +16254,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinOffsetOf) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17027,6 +17027,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinOffsetOf && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,9 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
+InBuiltInOffsetOfBase = true;
 TypeResult Ty = ParseTypeName();
+InBuiltInOffsetOfBase = false;
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC == DeclSpecContext::DSC_type_specifier,
 DSC == DeclSpecContext::DSC_template_param ||
 DSC == DeclSpecContext::DSC_template_type_arg,
-&SkipBody);
+&SkipBody, InBuiltInOffsetOfBase);
 
 // If ActOnTag said the type was dependent, try again with the
 // less common call.
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3273,7 +3273,8 @@
  bool &IsDependent, SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody = nullptr);
+ SkipBodyInfo *SkipBody = nullptr,
+ boo

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459037.
inclyc added a comment.

Add release notes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // expected-error{{'struct B' cannot be defined in '__builtin_offsetof'}}
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16254,7 +16254,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinOffsetOf) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17027,6 +17027,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinOffsetOf && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,9 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
+InBuiltInOffsetOfBase = true;
 TypeResult Ty = ParseTypeName();
+InBuiltInOffsetOfBase = false;
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC == DeclSpecContext::DSC_type_specifier,
 DSC == DeclSpecContext::DSC_template_param ||
 DSC == DeclSpecContext::DSC_template_type_arg,
-&SkipBody);
+&SkipBody, InBuiltInOffsetOfBase);
 
 // If ActOnTag said the type was dependent, try again with the
 // less common call.
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3273,7 +3273,8 @@
  bool &IsDependent, SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody = nullptr);
+ SkipBodyInfo *SkipBody = nullptr,
+ bool IsWithinOffsetOf = false);
 
   Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
 unsigned TagSpec, SourceLocation TagLoc,
Index: clang/include/clang/Parse/Parser.h
===
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -246,6 +246,9 @@
   /// function call.
   bool CalledSignatureHelp = false;
 
+  /// Parsing a type within __builtin_offsetof.
+  bool InBuiltInOffsetOfBase = false;
+
   /// The "depth" of the template parameters c

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459039.
inclyc added a comment.

Use double backquotes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // expected-error{{'struct B' cannot be defined in '__builtin_offsetof'}}
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16254,7 +16254,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinOffsetOf) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17027,6 +17027,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinOffsetOf && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,9 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
+InBuiltInOffsetOfBase = true;
 TypeResult Ty = ParseTypeName();
+InBuiltInOffsetOfBase = false;
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC == DeclSpecContext::DSC_type_specifier,
 DSC == DeclSpecContext::DSC_template_param ||
 DSC == DeclSpecContext::DSC_template_type_arg,
-&SkipBody);
+&SkipBody, InBuiltInOffsetOfBase);
 
 // If ActOnTag said the type was dependent, try again with the
 // less common call.
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3273,7 +3273,8 @@
  bool &IsDependent, SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody = nullptr);
+ SkipBodyInfo *SkipBody = nullptr,
+ bool IsWithinOffsetOf = false);
 
   Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
 unsigned TagSpec, SourceLocation TagLoc,
Index: clang/include/clang/Parse/Parser.h
===
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -246,6 +246,9 @@
   /// function call.
   bool CalledSignatureHelp = false;
 
+  /// Parsing a type within __builtin_offsetof.
+  bool InBuiltInOffsetOfBase = false;
+
   /// The "depth" of the template paramete

[PATCH] D133609: [Sema] compat warning of using deduced type in non-type template parameter

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a subscriber: kristof.beyls.
Herald added a project: All.
inclyc added reviewers: aaron.ballman, mizvekov, clang-language-wg.
inclyc published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Seems we are missing C++20 compatibility warning of using deduced type
(e.g. some template class) as a non-type template parameter. Before this
patch the following code crashes clang.

  template
  struct DC {};
  
  template // using deduced type, but considered as "auto" type
  auto test() {}

It triggered warn_cxx14_compat_template_nontype_parm_auto_type. However
there is no such "auto" type at all.

Using deduced type within non-type template parameter was introduced in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0732r2.pdf.

This patch create a new compatibility diagnostic message for this.

Fixes: https://github.com/llvm/llvm-project/issues/57643


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133609

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/SemaCXX/template-nontype-args-compat.cpp


Index: clang/test/SemaCXX/template-nontype-args-compat.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/template-nontype-args-compat.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -Wpre-c++20-compat -std=c++20 -verify=cpp20 
%s 
+
+namespace DeducedClass {
+template
+struct DC {};
+
+template // cpp20-warning{{non-type template parameters declared with 
'DC' are incompatible with C++ standards before C++20}}
+auto test() {}
+} // namespace DeducedClass
Index: clang/lib/Sema/SemaTemplate.cpp
===
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -1532,9 +1532,17 @@
   CheckValidDeclSpecifiers();
 
   if (TInfo->getType()->isUndeducedType()) {
-Diag(D.getIdentifierLoc(),
- diag::warn_cxx14_compat_template_nontype_parm_auto_type)
-  << QualType(TInfo->getType()->getContainedAutoType(), 0);
+if (TInfo->getType()->getContainedAutoType()) {
+  // template
+  Diag(D.getIdentifierLoc(),
+   diag::warn_cxx14_compat_template_nontype_parm_auto_type)
+  << QualType(TInfo->getType()->getContainedAutoType(), 0);
+} else {
+  // template
+  Diag(D.getIdentifierLoc(),
+   diag::warn_cxx17_compat_template_nontype_parm_deduced_class)
+  << TInfo->getType();
+}
   }
 
   assert(S->isTemplateParamScope() &&
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4833,6 +4833,10 @@
   "non-type template parameter of type %0 is incompatible with "
   "C++ standards before C++20">,
   DefaultIgnore, InGroup;
+def warn_cxx17_compat_template_nontype_parm_deduced_class : Warning<
+  "non-type template parameters declared with %0 are incompatible with C++ "
+  "standards before C++20">,
+  DefaultIgnore, InGroup;
 def warn_cxx14_compat_template_nontype_parm_auto_type : Warning<
   "non-type template parameters declared with %0 are incompatible with C++ "
   "standards before C++17">,
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -95,6 +95,9 @@
   `Issue 57169 `_
 - Clang configuration files are now read through the virtual file system
   rather than the physical one, if these are different.
+- Fix `Issue 57643 `_.
+  Missing C++20 compatibility warning of deduced type as non-type template
+  parameters.
 
 
 Improvements to Clang's diagnostics


Index: clang/test/SemaCXX/template-nontype-args-compat.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/template-nontype-args-compat.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -Wpre-c++20-compat -std=c++20 -verify=cpp20 %s 
+
+namespace DeducedClass {
+template
+struct DC {};
+
+template // cpp20-warning{{non-type template parameters declared with 'DC' are incompatible with C++ standards before C++20}}
+auto test() {}
+} // namespace DeducedClass
Index: clang/lib/Sema/SemaTemplate.cpp
===
--- clang/lib/Sema/SemaTemplate.cpp
+++ clang/lib/Sema/SemaTemplate.cpp
@@ -1532,9 +1532,17 @@
   CheckValidDeclSpecifiers();
 
   if (TInfo->getType()->isUndeducedType()) {
-Diag(D.getIdentifierLoc(),
- diag::warn_cxx14_compat_template_nontype_parm_auto_type)
-  << QualType(TInfo->getType()->getContainedAutoType(), 0);
+if (TInfo->getType()->ge

[PATCH] D133609: [Sema] compat warning of using deduced type in non-type template parameter

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/SemaCXX/template-nontype-args-compat.cpp:1
+// RUN: %clang_cc1 -fsyntax-only -Wpre-c++20-compat -std=c++20 -verify=cpp20 
%s 
+

I cannot find other tests of compatibility warnings though. Is it necessary to 
add such tests here? (in subsequent patches)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133609/new/

https://reviews.llvm.org/D133609

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459248.
inclyc added a comment.

Use RAII object to maintain the Parser state

> have you explored making a new DeclSpecContext and modifying 
> isDefiningTypeSpecifierContext()? I think that would likely be a cleaner 
> approach.

Emm, I've tried passing a DeclaratorContext into `ParseTypeName()`

  SourceLocation TypeLoc = Tok.getLocation();
  InBuiltInOffsetOfBaseRAIIObject InOffsetof(*this, true);
  TypeResult Ty = ParseTypeName(nullptr, /*Context=???*/); 

But defining a new DeclaratorContext I have to complete a bunch of `case`
statements.

  // Parser.h
  static bool isTypeSpecifier(DeclSpecContext DSC);
  static AllowDefiningTypeSpec isDefiningTypeSpecifierContext(DeclSpecContext 
DSC, bool IsCPlusPlus);
  static bool isOpaqueEnumDeclarationContext(DeclSpecContext DSC);
  /* ... */

And I think it is somehow strange to determine these properties within
__builtin_offsetof()? I'm not sure if it is really appropriate to define a
special context for a built-in function. This place should only need to
forbidden definitions, right?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Parse/RAIIObjectsForParser.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // expected-error{{'struct B' cannot be defined in '__builtin_offsetof'}}
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16254,7 +16254,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinOffsetOf) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17027,6 +17027,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinOffsetOf && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,6 +2579,7 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
+InBuiltInOffsetOfBaseRAIIObject InOffsetof(*this, true);
 TypeResult Ty = ParseTypeName();
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC == DeclSpecContext::DSC_type_specifier,
 DSC == DeclSpecContext::DSC_template_param ||
 DSC == DeclSpecContext::DSC_template_type_arg,
-&SkipBody);
+&SkipBody, InBuiltInOffsetOfBase);
 
 // If ActOnTag said the type was dependent, try again with the
 // less common call.
Index: clang/include/clang/Sema/Sema.h

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459458.
inclyc added a comment.

Use declaration context


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof directly
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -3584,6 +3584,7 @@
   [[fallthrough]];
 case DeclaratorContext::TypeName:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   Error = 15; // Generic
   break;
 case DeclaratorContext::File:
@@ -3695,6 +3696,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   DiagID = diag::err_type_defined_in_type_specifier;
   break;
 case DeclaratorContext::Prototype:
@@ -4784,6 +4786,7 @@
 case DeclaratorContext::FunctionalCast:
 case DeclaratorContext::RequiresExpr:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // Don't infer in these contexts.
   break;
 }
@@ -5836,6 +5839,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // FIXME: We may want to allow parameter packs in block-literal contexts
   // in the future.
   S.Diag(D.getEllipsisLoc(),
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16254,7 +16254,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinBuiltinOffsetof) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17027,6 +17027,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinBuiltinOffsetof && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,8 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
-TypeResult Ty = ParseTypeName();
+TypeResult Ty =
+ParseTypeName(/*Range*/ nullptr, DeclaratorContext::OffsetOf);
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459633.
inclyc added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof directly
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -3584,6 +3584,7 @@
   [[fallthrough]];
 case DeclaratorContext::TypeName:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   Error = 15; // Generic
   break;
 case DeclaratorContext::File:
@@ -3695,6 +3696,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   DiagID = diag::err_type_defined_in_type_specifier;
   break;
 case DeclaratorContext::Prototype:
@@ -4784,6 +4786,7 @@
 case DeclaratorContext::FunctionalCast:
 case DeclaratorContext::RequiresExpr:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // Don't infer in these contexts.
   break;
 }
@@ -5836,6 +5839,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // FIXME: We may want to allow parameter packs in block-literal contexts
   // in the future.
   S.Diag(D.getEllipsisLoc(),
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16257,7 +16257,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinBuiltinOffsetof) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17030,6 +17030,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinBuiltinOffsetof && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,8 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
-TypeResult Ty = ParseTypeName();
+TypeResult Ty =
+ParseTypeName(/*Range=*/nullptr, DeclaratorContext::OffsetOf);
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC ==

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 459634.
inclyc added a comment.

git-clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/Parser/declarators.c
  clang/test/Sema/offsetof.c

Index: clang/test/Sema/offsetof.c
===
--- clang/test/Sema/offsetof.c
+++ clang/test/Sema/offsetof.c
@@ -70,3 +70,16 @@
   return __builtin_offsetof(Array, array[*(int*)0]); // expected-warning{{indirection of non-volatile null pointer}} expected-note{{__builtin_trap}}
 }
 
+// Reject definitions in __builtin_offsetof
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
+int test_definition(void) {
+  return __builtin_offsetof(struct A // expected-error{{'struct A' cannot be defined in '__builtin_offsetof'}} 
+  { 
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof directly
+{
+  int c;
+  int d;
+} x;
+  }, a);
+}
Index: clang/test/Parser/declarators.c
===
--- clang/test/Parser/declarators.c
+++ clang/test/Parser/declarators.c
@@ -80,10 +80,6 @@
 struct test10 { int a; } static test10x;
 struct test11 { int a; } const test11x;
 
-// PR6216
-void test12(void) {
-  (void)__builtin_offsetof(struct { char c; int i; }, i);
-}
 
 // rdar://7608537
 struct test13 { int a; } (test13x);
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -3584,6 +3584,7 @@
   [[fallthrough]];
 case DeclaratorContext::TypeName:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   Error = 15; // Generic
   break;
 case DeclaratorContext::File:
@@ -3695,6 +3696,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   DiagID = diag::err_type_defined_in_type_specifier;
   break;
 case DeclaratorContext::Prototype:
@@ -4784,6 +4786,7 @@
 case DeclaratorContext::FunctionalCast:
 case DeclaratorContext::RequiresExpr:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // Don't infer in these contexts.
   break;
 }
@@ -5836,6 +5839,7 @@
 case DeclaratorContext::TemplateArg:
 case DeclaratorContext::TemplateTypeArg:
 case DeclaratorContext::Association:
+case DeclaratorContext::OffsetOf:
   // FIXME: We may want to allow parameter packs in block-literal contexts
   // in the future.
   S.Diag(D.getEllipsisLoc(),
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16257,7 +16257,7 @@
  SourceLocation ScopedEnumKWLoc,
  bool ScopedEnumUsesClassTag, TypeResult UnderlyingType,
  bool IsTypeSpecifier, bool IsTemplateParamOrArg,
- SkipBodyInfo *SkipBody) {
+ SkipBodyInfo *SkipBody, bool IsWithinBuiltinOffsetof) {
   // If this is not a definition, it must have a name.
   IdentifierInfo *OrigName = Name;
   assert((Name != nullptr || TUK == TUK_Definition) &&
@@ -17030,6 +17030,12 @@
cast_or_null(PrevDecl));
   }
 
+  if (IsWithinBuiltinOffsetof && TUK == TUK_Definition) {
+Diag(New->getLocation(), diag::err_type_defined_in_offsetof)
+<< Context.getTagDeclType(New);
+Invalid = true;
+  }
+
   // C++11 [dcl.type]p3:
   //   A type-specifier-seq shall not define a class or enumeration [...].
   if (getLangOpts().CPlusPlus && (IsTypeSpecifier || IsTemplateParamOrArg) &&
Index: clang/lib/Parse/ParseExpr.cpp
===
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -2579,7 +2579,8 @@
   }
   case tok::kw___builtin_offsetof: {
 SourceLocation TypeLoc = Tok.getLocation();
-TypeResult Ty = ParseTypeName();
+TypeResult Ty =
+ParseTypeName(/*Range=*/nullptr, DeclaratorContext::OffsetOf);
 if (Ty.isInvalid()) {
   SkipUntil(tok::r_paren, StopAtSemi);
   return ExprError();
Index: clang/lib/Parse/ParseDeclCXX.cpp
===
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -2030,7 +2030,7 @@
 DSC ==

[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-14 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/include/clang/Parse/Parser.h:2311
 case DeclSpecContext::DSC_association:
+case DeclSpecContext::DSC_offsetof:
   return true;

aaron.ballman wrote:
> Is this correct? I don't think we can deduce the type from `offsetof` through 
> CTAD, can we?
> 
> https://godbolt.org/z/Kab6ahYe7
> 
> (This might be a good test case to add assuming we don't already have that 
> coverage.)
Emm, these checks just return as the same as "type_specifier". Because that's 
what we passed into "ParsingTypename" before.



Comment at: clang/test/Sema/offsetof.c:79
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof 
directly
+{

aaron.ballman wrote:
> I think this is defensible. The wording in the standard is "If the specified 
> type defines a new type or if the specified member is a bit-field, the 
> behavior is undefined." and the specified type in this case is `struct A`; 
> that `struct A` happens to also define `struct B` is immaterial.
> 
> However, the intent behind the change to the rule is to support older 
> implementations of `offsetof` to protect them from having to deal with a case 
> like: `offsetof(struct S { int a, b }, b);` where `offsetof` is a macro and 
> thus the comma between `a` and `b` is treated as a separator. So there's a 
> part of me that wonders if we want to also support diagnosing this case. But 
> then we'd have to look at the declarator context more recursively to see 
> whether any of the contexts on the stack are an `offsetof` context and that 
> might be tricky.
> 
> Thoughts?
FWIW, gcc seems just rejects all definitions in this context. (Perhaps during 
Parsing the statements). If we add a bool state to the Parser (just using RAII 
object as before) struct B will trigger diagnostic error because the state 
"ParsingOffsetof" is passed into inner declaration.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-14 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Sema/offsetof.c:79
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof 
directly
+{

aaron.ballman wrote:
> inclyc wrote:
> > aaron.ballman wrote:
> > > I think this is defensible. The wording in the standard is "If the 
> > > specified type defines a new type or if the specified member is a 
> > > bit-field, the behavior is undefined." and the specified type in this 
> > > case is `struct A`; that `struct A` happens to also define `struct B` is 
> > > immaterial.
> > > 
> > > However, the intent behind the change to the rule is to support older 
> > > implementations of `offsetof` to protect them from having to deal with a 
> > > case like: `offsetof(struct S { int a, b }, b);` where `offsetof` is a 
> > > macro and thus the comma between `a` and `b` is treated as a separator. 
> > > So there's a part of me that wonders if we want to also support 
> > > diagnosing this case. But then we'd have to look at the declarator 
> > > context more recursively to see whether any of the contexts on the stack 
> > > are an `offsetof` context and that might be tricky.
> > > 
> > > Thoughts?
> > FWIW, gcc seems just rejects all definitions in this context. (Perhaps 
> > during Parsing the statements). If we add a bool state to the Parser (just 
> > using RAII object as before) struct B will trigger diagnostic error because 
> > the state "ParsingOffsetof" is passed into inner declaration.
> GCC accepts currently: https://godbolt.org/z/oEvzjW6Ee but you're correct 
> regarding switching back to an RAII object being an easier way to address the 
> nested declarations.
> 
> Let me think on this situation a bit
> GCC accepts currently

C++: https://godbolt.org/z/fon8e7dzf 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D133574: [C2x] reject type definitions in offsetof

2022-09-14 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Sema/offsetof.c:79
+int a;
+struct B // no-error, struct B is not defined within __builtin_offsetof 
directly
+{

inclyc wrote:
> aaron.ballman wrote:
> > inclyc wrote:
> > > aaron.ballman wrote:
> > > > I think this is defensible. The wording in the standard is "If the 
> > > > specified type defines a new type or if the specified member is a 
> > > > bit-field, the behavior is undefined." and the specified type in this 
> > > > case is `struct A`; that `struct A` happens to also define `struct B` 
> > > > is immaterial.
> > > > 
> > > > However, the intent behind the change to the rule is to support older 
> > > > implementations of `offsetof` to protect them from having to deal with 
> > > > a case like: `offsetof(struct S { int a, b }, b);` where `offsetof` is 
> > > > a macro and thus the comma between `a` and `b` is treated as a 
> > > > separator. So there's a part of me that wonders if we want to also 
> > > > support diagnosing this case. But then we'd have to look at the 
> > > > declarator context more recursively to see whether any of the contexts 
> > > > on the stack are an `offsetof` context and that might be tricky.
> > > > 
> > > > Thoughts?
> > > FWIW, gcc seems just rejects all definitions in this context. (Perhaps 
> > > during Parsing the statements). If we add a bool state to the Parser 
> > > (just using RAII object as before) struct B will trigger diagnostic error 
> > > because the state "ParsingOffsetof" is passed into inner declaration.
> > GCC accepts currently: https://godbolt.org/z/oEvzjW6Ee but you're correct 
> > regarding switching back to an RAII object being an easier way to address 
> > the nested declarations.
> > 
> > Let me think on this situation a bit
> > GCC accepts currently
> 
> C++: https://godbolt.org/z/fon8e7dzf 
```
: In function 'int main()':
:3:3: error: types may not be defined within '__builtin_offsetof'
3 |   {
  |   ^
:6:5: error: types may not be defined within '__builtin_offsetof'
6 | {
  | ^
Compiler returned: 1
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133574/new/

https://reviews.llvm.org/D133574

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a project: All.
inclyc edited the summary of this revision.
inclyc updated this revision to Diff 449023.
inclyc added a comment.
inclyc added reviewers: mizvekov, rsmith, aaron.ballman.
inclyc added a project: clang.
inclyc added a subscriber: clang.
inclyc published this revision for review.
Herald added a subscriber: cfe-commits.

add newline


This patch enhances clang's ability to check compile-time determinable
string literals as format strings, and can give FixIt hints at literals
(unlike gcc). Issue https://github.com/llvm/llvm-project/issues/55805
mentiond two compile-time string cases. And this patch partially fixes
one.

  constexpr const char* foo() {
return "%s %d";
  }
  int main() {
 printf(foo(), "abc", "def");
 return 0;
  }

This patch enables clang check format string for this:

  :4:24: warning: format specifies type 'int' but the argument has type 
'const char *' [-Wformat]
printf(foo(), "abc", "def");
   ~ ^
  :2:42: note: format string is defined here
  constexpr const char *foo() { return "%s %d"; }
   ^~
   %s
  1 warning generated.

Signed-off-by: YingChi Long 


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D130906

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -105,7 +105,8 @@
   // expected-note@-1{{treat the string as an argument to avoid this}}
   printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}}
   printf(0 ? "yes %s" : "no %d", 1); // no-warning
-  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}}
+  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
 
   printf(0 ? "yes" : "no %d", 1); // no-warning
   printf(0 ? "yes %d" : "no", 1); // expected-warning{{data argument not used by format string}}
@@ -259,8 +260,7 @@
   printf(s2); // no-warning
   printf(s3); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
-  printf(s4); // expected-warning{{not a string literal}}
-  // expected-note@-1{{treat the string as an argument to avoid this}}
+  printf(s4);
   printf(s5); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
 }
@@ -621,7 +621,8 @@
 
   // Make sure that the "format string is defined here" note is not emitted
   // when the original string is within the argument expression.
-  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}}
+  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}} \
+  // expected-note {{format string is defined here}}
 
   const char kFormat17[] = "%hu"; // expected-note{{format string is defined here}}}
   printf(kFormat17, (int[]){0}); // expected-warning{{format specifies type 'unsigned short' but the argument}}
Index: clang/test/Sema/format-strings-scanf.c
===

[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Sema/format-strings-scanf.c:235
   scanf(0 ? "%s" : "%d", i); // no warning
-  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char 
*'}}
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char 
*'}} \
+ // expected-note{{format string is defined here}}

These new notes are FixIt hints, looks much better than before.



Comment at: clang/test/Sema/format-strings.c:263
   // expected-note@-1{{treat the string as an argument to avoid this}}
-  printf(s4); // expected-warning{{not a string literal}}
-  // expected-note@-1{{treat the string as an argument to avoid this}}
+  printf(s4);
   printf(s5); // expected-warning{{not a string literal}}

Here, s4 is declared as `char * const` and initialized as `const char`, so 
warning generates at the declaration of  `s4` is sufficient? Since modify 
characters in string literal causes UB.

```
Initializing 'char *const' with an expression of type 'const char[6]' discards 
qualifiers
```

Currently the checker in this patch just qualifies `"hello"` as a string 
literal, and does not report `-Wformat-nonliteral` as before


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Sema/SemaChecking.cpp:8507
+if (Result.Val.isLValue()) {
+  auto *LVE = Result.Val.getLValueBase().dyn_cast();
+  if (LVE && LVE->getStmtClass() == Stmt::StringLiteralClass) {

tbaeder wrote:
> I think you should be able to unify the two `if` statements.
> 
> Can you not `dyn_cast_or_null(Result.Val.getLValueBase())` 
> here instead of casting to `Expr*` and checking the `StmtClass`?
`LValueBase` seems to be a wrapper of a pointer that has its own dyn_cast 
method.

I have changed code here like this, but it cannot compile
```
auto *MaybeStringLiteral =
dyn_cast_or_null(Result.Val.getLValueBase());
if (MaybeStringLiteral) {
  return checkFormatStringExpr(S, MaybeStringLiteral, Args, APK, format_idx,
   firstDataArg, Type, CallType,
   /*InFunctionCall*/ false, CheckedVarArgs,
   UncoveredArg, Offset);
}
```

```
/llvm-project/llvm/include/llvm/Support/Casting.h:64:53: error: type 
'clang::StringLiteral *' cannot be used prior to '::' because it has no members
  static inline bool doit(const From &Val) { return To::classof(&Val); }
```



Comment at: clang/test/Sema/format-strings-scanf.c:235
   scanf(0 ? "%s" : "%d", i); // no warning
-  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char 
*'}}
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char 
*'}} \
+ // expected-note{{format string is defined here}}

tbaeder wrote:
> inclyc wrote:
> > These new notes are FixIt hints, looks much better than before.
> Can you show some sample output?
Source:
```
// sample.cpp
#include 

int main() {
  int *i;
  scanf(1 ? "%s %d" : "%d", i);
}
```

previous version:
```
sample.cpp:5:29: warning: format specifies type 'char *' but the argument has 
type 'int *' [-Wformat]
  scanf(1 ? "%s %d" : "%d", i);
 ~~ ^
 %d
sample.cpp:5:18: warning: more '%' conversions than data arguments 
[-Wformat-insufficient-args]
  scanf(1 ? "%s %d" : "%d", i);
~^
2 warnings generated.
```

this patch highlights ` cond ? T : F` expressions:

```
sample.cpp:5:29: warning: format specifies type 'char *' but the argument has 
type 'int *' [-Wformat]
  scanf(1 ? "%s %d" : "%d", i);
~~  ^
sample.cpp:5:14: note: format string is defined here
  scanf(1 ? "%s %d" : "%d", i);
 ^~
 %d
sample.cpp:5:9: warning: more '%' conversions than data arguments 
[-Wformat-insufficient-args]
  scanf(1 ? "%s %d" : "%d", i);
^~
sample.cpp:5:18: note: format string is defined here
  scanf(1 ? "%s %d" : "%d", i);
~^
2 warnings generated.
```



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449191.
inclyc added a comment.

Make if statements concise and add comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -105,7 +105,8 @@
   // expected-note@-1{{treat the string as an argument to avoid this}}
   printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}}
   printf(0 ? "yes %s" : "no %d", 1); // no-warning
-  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}}
+  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
 
   printf(0 ? "yes" : "no %d", 1); // no-warning
   printf(0 ? "yes %d" : "no", 1); // expected-warning{{data argument not used by format string}}
@@ -259,8 +260,7 @@
   printf(s2); // no-warning
   printf(s3); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
-  printf(s4); // expected-warning{{not a string literal}}
-  // expected-note@-1{{treat the string as an argument to avoid this}}
+  printf(s4);
   printf(s5); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
 }
@@ -621,7 +621,8 @@
 
   // Make sure that the "format string is defined here" note is not emitted
   // when the original string is within the argument expression.
-  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}}
+  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}} \
+  // expected-note {{format string is defined here}}
 
   const char kFormat17[] = "%hu"; // expected-note{{format string is defined here}}}
   printf(kFormat17, (int[]){0}); // expected-warning{{format specifies type 'unsigned short' but the argument}}
Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-scanf.c
+++ clang/test/Sema/format-strings-scanf.c
@@ -232,9 +232,11 @@
 
 void check_conditional_literal(char *s, int *i) {
   scanf(0 ? "%s" : "%d", i); // no warning
-  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}}
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i); // no warning
-  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}}
+  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}} \
+// expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i, s); // expected-warning{{data argument not used}}
   scanf(1 ? "%d %s" : "%d", i, s); // no warning
   scanf(i ? "%d %s" : "%d", i, s); // no warning
Index: clang/lib/Sema/SemaChecking.cpp
===

[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Sema/format-strings-scanf.c:236
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char 
*'}} \
+ // expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i); // no warning

```
// long macro
#include 

#define SOME_STRANGE_MACRO(a, b) ((0) ? (a) : (b))

int main() {
  int *i;
  scanf(SOME_STRANGE_MACRO("%d", "%d %s"), i);
}
```

previous:
```
sample.cpp:7:39: warning: more '%' conversions than data arguments 
[-Wformat-insufficient-args]
  scanf(SOME_STRANGE_MACRO("%d", "%d %s"), i);
 ~^
sample.cpp:3:48: note: expanded from macro 'SOME_STRANGE_MACRO'
#define SOME_STRANGE_MACRO(a, b) ((0) ? (a) : (b))
   ^
1 warning generated.
```

now:

```
sample.cpp:7:9: warning: more '%' conversions than data arguments 
[-Wformat-insufficient-args]
  scanf(SOME_STRANGE_MACRO("%d", "%d %s"), i);
^
sample.cpp:3:34: note: expanded from macro 'SOME_STRANGE_MACRO'
#define SOME_STRANGE_MACRO(a, b) ((0) ? (a) : (b))
 ^
sample.cpp:7:39: note: format string is defined here
  scanf(SOME_STRANGE_MACRO("%d", "%d %s"), i);
 ~^
sample.cpp:3:48: note: expanded from macro 'SOME_STRANGE_MACRO'
#define SOME_STRANGE_MACRO(a, b) ((0) ? (a) : (b))
   ^
1 warning generated.
```

I think it is better to underline the buggy expression, if this sucks maybe we 
can check if this is constexpr **after** checking conditional operator ` ? :`  
or somehow other statement classes ?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-01 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449195.
inclyc added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -105,7 +105,8 @@
   // expected-note@-1{{treat the string as an argument to avoid this}}
   printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}}
   printf(0 ? "yes %s" : "no %d", 1); // no-warning
-  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}}
+  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
 
   printf(0 ? "yes" : "no %d", 1); // no-warning
   printf(0 ? "yes %d" : "no", 1); // expected-warning{{data argument not used by format string}}
@@ -259,8 +260,7 @@
   printf(s2); // no-warning
   printf(s3); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
-  printf(s4); // expected-warning{{not a string literal}}
-  // expected-note@-1{{treat the string as an argument to avoid this}}
+  printf(s4);
   printf(s5); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
 }
@@ -621,7 +621,8 @@
 
   // Make sure that the "format string is defined here" note is not emitted
   // when the original string is within the argument expression.
-  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}}
+  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}} \
+  // expected-note {{format string is defined here}}
 
   const char kFormat17[] = "%hu"; // expected-note{{format string is defined here}}}
   printf(kFormat17, (int[]){0}); // expected-warning{{format specifies type 'unsigned short' but the argument}}
Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-scanf.c
+++ clang/test/Sema/format-strings-scanf.c
@@ -232,9 +232,11 @@
 
 void check_conditional_literal(char *s, int *i) {
   scanf(0 ? "%s" : "%d", i); // no warning
-  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}}
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i); // no warning
-  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}}
+  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}} \
+// expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i, s); // expected-warning{{data argument not used}}
   scanf(1 ? "%d %s" : "%d", i, s); // no warning
   scanf(i ? "%d %s" : "%d", i, s); // no warning
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/li

[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Sema/SemaChecking.cpp:8507
+if (Result.Val.isLValue()) {
+  auto *LVE = Result.Val.getLValueBase().dyn_cast();
+  if (LVE && LVE->getStmtClass() == Stmt::StringLiteralClass) {

tbaeder wrote:
> tbaeder wrote:
> > inclyc wrote:
> > > tbaeder wrote:
> > > > I think you should be able to unify the two `if` statements.
> > > > 
> > > > Can you not 
> > > > `dyn_cast_or_null(Result.Val.getLValueBase())` here 
> > > > instead of casting to `Expr*` and checking the `StmtClass`?
> > > `LValueBase` seems to be a wrapper of a pointer that has its own dyn_cast 
> > > method.
> > > 
> > > I have changed code here like this, but it cannot compile
> > > ```
> > > auto *MaybeStringLiteral =
> > > dyn_cast_or_null(Result.Val.getLValueBase());
> > > if (MaybeStringLiteral) {
> > >   return checkFormatStringExpr(S, MaybeStringLiteral, Args, APK, 
> > > format_idx,
> > >firstDataArg, Type, CallType,
> > >/*InFunctionCall*/ false, 
> > > CheckedVarArgs,
> > >UncoveredArg, Offset);
> > > }
> > > ```
> > > 
> > > ```
> > > /llvm-project/llvm/include/llvm/Support/Casting.h:64:53: 
> > > error: type 'clang::StringLiteral *' cannot be used prior to '::' because 
> > > it has no members
> > >   static inline bool doit(const From &Val) { return To::classof(&Val); }
> > > ```
> > Ah, shame. This ends up calling `dyn_cast` on a `llvm::Pointerunion` as far 
> > as I can see, which seems to return `nullptr` in case the cast is 
> > unsuccessful anyway, so you could try just exploiting that: 
> > https://llvm.org/doxygen/classllvm_1_1PointerUnion.html#a9147352f78d98ee246f25d3300e0aaba
> What about this? I.e. usong `StringLiteral*` directly in the `dyn_cast` call?
```
FAILED: tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaChecking.cpp.o 
/usr/lib/llvm/14/bin/clang++ -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GNU_SOURCE 
-D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS 
-I/build/tools/clang/lib/Sema -I/clang/lib/Sema 
-I/clang/include -I/build/tools/clang/include 
-I/build/include -I/llvm/include -fPIC 
-fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time 
-Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter 
-Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic 
-Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough 
-Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor 
-Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion 
-Wmisleading-indentation -fdiagnostics-color -fno-common -Woverloaded-virtual 
-Wno-nested-anon-types -g  -fno-exceptions -fno-rtti -std=c++14 -MD -MT 
tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaChecking.cpp.o -MF 
tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaChecking.cpp.o.d -o 
tools/clang/lib/Sema/CMakeFiles/obj.clangSema.dir/SemaChecking.cpp.o -c 
/clang/lib/Sema/SemaChecking.cpp
In file included from /clang/lib/Sema/SemaChecking.cpp:14:
In file included from /clang/include/clang/AST/APValue.h:18:
In file included from /llvm/include/llvm/ADT/APFloat.h:19:
In file included from /llvm/include/llvm/ADT/ArrayRef.h:15:
/llvm/include/llvm/ADT/STLExtras.h:199:42: error: implicit 
instantiation of undefined template 'llvm::FirstIndexOfType'
: std::integral_constant::value> {};
 ^
/llvm/include/llvm/ADT/STLExtras.h:199:42: note: in instantiation 
of template class 'llvm::FirstIndexOfType' requested here
/llvm/include/llvm/ADT/STLExtras.h:199:42: note: in instantiation 
of template class 'llvm::FirstIndexOfType' requested here
/llvm/include/llvm/ADT/STLExtras.h:199:42: note: in instantiation 
of template class 'llvm::FirstIndexOfType' requested here
/llvm/include/llvm/ADT/PointerUnion.h:230:30: note: in 
instantiation of template class 'llvm::FirstIndexOfType' requested here
return F.Val.getInt() == FirstIndexOfType::value;
 ^
/llvm/include/llvm/ADT/PointerUnion.h:248:27: note: in 
instantiation of function template specialization 
'llvm::CastInfoPointerUnionImpl::isPossible' requested here
return Impl::template isPossible(f);
  ^
/llvm/include/llvm/Support/Casting.h:312:19: note: in 
instantiation of member function 'llvm::CastInfo>::isPossible' requested here
if (!Derived::isPossible(f))
  ^
/llvm/include/llvm/Support/Casting.h:407:23: note: in 
instantiation of member function 'llvm::DefaultDoCastIfPossible, 
llvm::CastInfo>>::doCastIfPossible' requested here
return ForwardTo::doCastIfPossible(const_cast(f));
  ^
/clang/include/clang/AST/APValue.h:167:37: note: in instantiation 
of function template specialization 'llvm::PointerUnion::dyn_cast' requested 
here
T dyn_cast() const { return Ptr.dyn_cast(); }
 

[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449236.
inclyc added a comment.

update comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/format-strings-scanf.c
  clang/test/Sema/format-strings.c
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/test/Sema/format-strings.c
===
--- clang/test/Sema/format-strings.c
+++ clang/test/Sema/format-strings.c
@@ -105,7 +105,8 @@
   // expected-note@-1{{treat the string as an argument to avoid this}}
   printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}}
   printf(0 ? "yes %s" : "no %d", 1); // no-warning
-  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}}
+  printf(0 ? "yes %d" : "no %s", 1); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
 
   printf(0 ? "yes" : "no %d", 1); // no-warning
   printf(0 ? "yes %d" : "no", 1); // expected-warning{{data argument not used by format string}}
@@ -259,8 +260,7 @@
   printf(s2); // no-warning
   printf(s3); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
-  printf(s4); // expected-warning{{not a string literal}}
-  // expected-note@-1{{treat the string as an argument to avoid this}}
+  printf(s4);
   printf(s5); // expected-warning{{not a string literal}}
   // expected-note@-1{{treat the string as an argument to avoid this}}
 }
@@ -621,7 +621,8 @@
 
   // Make sure that the "format string is defined here" note is not emitted
   // when the original string is within the argument expression.
-  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}}
+  printf(1 ? "yes %d" : "no %d"); // expected-warning{{more '%' conversions than data arguments}} \
+  // expected-note {{format string is defined here}}
 
   const char kFormat17[] = "%hu"; // expected-note{{format string is defined here}}}
   printf(kFormat17, (int[]){0}); // expected-warning{{format specifies type 'unsigned short' but the argument}}
Index: clang/test/Sema/format-strings-scanf.c
===
--- clang/test/Sema/format-strings-scanf.c
+++ clang/test/Sema/format-strings-scanf.c
@@ -232,9 +232,11 @@
 
 void check_conditional_literal(char *s, int *i) {
   scanf(0 ? "%s" : "%d", i); // no warning
-  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}}
+  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}} \
+ // expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i); // no warning
-  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}}
+  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}} \
+// expected-note{{format string is defined here}}
   scanf(0 ? "%d %d" : "%d", i, s); // expected-warning{{data argument not used}}
   scanf(1 ? "%d %s" : "%d", i, s); // no warning
   scanf(i ? "%d %s" : "%d", i, s); // no warning
Index: clang/lib/Sema/SemaChecking.cpp
===
---

[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449510.
inclyc added a comment.

Now only checks functions calls


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8473,6 +8473,9 @@
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E);
+
 // Determine if an expression is a string literal or constant string.
 // If this function returns false on the arguments to a function expecting a
 // format string, we will usually need to emit a warning.
@@ -8713,7 +8716,11 @@
 }
   }
 }
-
+if (auto *SLE = maybeConstEvalStringLiteral(S.Context, E))
+  return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg,
+   Type, CallType, /*InFunctionCall*/ false,
+   CheckedVarArgs, UncoveredArg, Offset,
+   IgnoreStringsWithoutSpecifiers);
 return SLCT_NotALiteral;
   }
   case Stmt::ObjCMessageExprClass: {
@@ -8823,6 +8830,20 @@
   }
 }
 
+// If this expression can be evaluated at compile-time,
+// check if the result is a StringLiteral and return it
+// otherwise return nullptr
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E) {
+  Expr::EvalResult Result;
+  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
+auto *LVE = Result.Val.getLValueBase().dyn_cast();
+if (LVE && LVE->getStmtClass() == Stmt::StringLiteralClass)
+  return LVE;
+  }
+  return nullptr;
+}
+
 Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
   return llvm::StringSwitch(Format->getType()->getName())
   .Case("scanf", FST_Scanf)
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -62,6 +62,8 @@
   enum without a fixed underlying type is set to a value outside the range of
   the enumeration's values. Fixes
   `Issue 50055: `_.
+- Clang will now check compile-time determinable string literals as format strings.
+  This fixes `Issue 55805: `_.
 
 Non-comprehensive list of changes in this release
 -
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449511.
inclyc added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8473,6 +8473,9 @@
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E);
+
 // Determine if an expression is a string literal or constant string.
 // If this function returns false on the arguments to a function expecting a
 // format string, we will usually need to emit a warning.
@@ -8713,7 +8716,11 @@
 }
   }
 }
-
+if (auto *SLE = maybeConstEvalStringLiteral(S.Context, E))
+  return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg,
+   Type, CallType, /*InFunctionCall*/ false,
+   CheckedVarArgs, UncoveredArg, Offset,
+   IgnoreStringsWithoutSpecifiers);
 return SLCT_NotALiteral;
   }
   case Stmt::ObjCMessageExprClass: {
@@ -8823,6 +8830,20 @@
   }
 }
 
+// If this expression can be evaluated at compile-time,
+// check if the result is a StringLiteral and return it
+// otherwise return nullptr
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E) {
+  Expr::EvalResult Result;
+  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
+auto *LVE = Result.Val.getLValueBase().dyn_cast();
+if (LVE && LVE->getStmtClass() == Stmt::StringLiteralClass)
+  return LVE;
+  }
+  return nullptr;
+}
+
 Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
   return llvm::StringSwitch(Format->getType()->getName())
   .Case("scanf", FST_Scanf)
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -61,6 +61,8 @@
   enum without a fixed underlying type is set to a value outside the range of
   the enumeration's values. Fixes
   `Issue 50055: `_.
+- Clang will now check compile-time determinable string literals as format strings.
+  This fixes `Issue 55805: `_.
 
 Non-comprehensive list of changes in this release
 -
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

The previous version of this patch checked constant string literals before 
checking various types of statements, while the current version only checks for 
compile-time evaluation literals after function calls, and now other regression 
tests remain as they are.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-02 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449517.
inclyc added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8473,6 +8473,9 @@
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E);
+
 // Determine if an expression is a string literal or constant string.
 // If this function returns false on the arguments to a function expecting a
 // format string, we will usually need to emit a warning.
@@ -8713,7 +8716,11 @@
 }
   }
 }
-
+if (auto *SLE = maybeConstEvalStringLiteral(S.Context, E))
+  return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg,
+   Type, CallType, /*InFunctionCall*/ false,
+   CheckedVarArgs, UncoveredArg, Offset,
+   IgnoreStringsWithoutSpecifiers);
 return SLCT_NotALiteral;
   }
   case Stmt::ObjCMessageExprClass: {
@@ -8823,6 +8830,20 @@
   }
 }
 
+// If this expression can be evaluated at compile-time,
+// check if the result is a StringLiteral and return it
+// otherwise return nullptr
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E) {
+  Expr::EvalResult Result;
+  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
+auto *LVE = Result.Val.getLValueBase().dyn_cast();
+if (isa_and_nonnull(LVE))
+  return LVE;
+  }
+  return nullptr;
+}
+
 Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
   return llvm::StringSwitch(Format->getType()->getName())
   .Case("scanf", FST_Scanf)
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -61,6 +61,8 @@
   enum without a fixed underlying type is set to a value outside the range of
   the enumeration's values. Fixes
   `Issue 50055: `_.
+- Clang will now check compile-time determinable string literals as format strings.
+  This fixes `Issue 55805: `_.
 
 Non-comprehensive list of changes in this release
 -
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-04 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Thank you!  I already have the commit access, I can commit this myself ^_^


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-04 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 449947.
inclyc added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8473,6 +8473,9 @@
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E);
+
 // Determine if an expression is a string literal or constant string.
 // If this function returns false on the arguments to a function expecting a
 // format string, we will usually need to emit a warning.
@@ -8713,7 +8716,11 @@
 }
   }
 }
-
+if (const auto *SLE = maybeConstEvalStringLiteral(S.Context, E))
+  return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg,
+   Type, CallType, /*InFunctionCall*/ false,
+   CheckedVarArgs, UncoveredArg, Offset,
+   IgnoreStringsWithoutSpecifiers);
 return SLCT_NotALiteral;
   }
   case Stmt::ObjCMessageExprClass: {
@@ -8823,6 +8830,20 @@
   }
 }
 
+// If this expression can be evaluated at compile-time,
+// check if the result is a StringLiteral and return it
+// otherwise return nullptr
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E) {
+  Expr::EvalResult Result;
+  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
+const auto *LVE = Result.Val.getLValueBase().dyn_cast();
+if (isa_and_nonnull(LVE))
+  return LVE;
+  }
+  return nullptr;
+}
+
 Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
   return llvm::StringSwitch(Format->getType()->getName())
   .Case("scanf", FST_Scanf)
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -67,6 +67,8 @@
   enum without a fixed underlying type is set to a value outside the range of
   the enumeration's values. Fixes
   `Issue 50055: `_.
+- Clang will now check compile-time determinable string literals as format strings.
+  This fixes `Issue 55805: `_.
 
 Non-comprehensive list of changes in this release
 -
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-04 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf417583f319b: [clang] format string checking for 
conpile-time evaluated str literal (authored by inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -163,3 +163,48 @@
   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
 }
 }
+#if __cplusplus >= 201103L
+namespace evaluated {
+
+constexpr const char *basic() { 
+  return 
+"%s %d"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *correct_fmt() { 
+  return 
+"%d %d";
+}
+
+constexpr const char *string_linebreak() { 
+  return 
+"%d %d"
+"%d %s"; // expected-note {{format string is defined here}}
+}
+
+/*non-constexpr*/ const char *not_literal() { 
+  return 
+"%d %d"
+"%d %s";
+}
+
+constexpr const char *inner_call() {
+  return "%d %s"; // expected-note {{format string is defined here}}
+}
+
+constexpr const char *wrap_constexpr() {
+  return inner_call();
+}
+
+
+void f() {
+  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(correct_fmt(), 1, 2);
+  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
+  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+}
+
+
+}
+#endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8473,6 +8473,9 @@
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E);
+
 // Determine if an expression is a string literal or constant string.
 // If this function returns false on the arguments to a function expecting a
 // format string, we will usually need to emit a warning.
@@ -8713,7 +8716,11 @@
 }
   }
 }
-
+if (const auto *SLE = maybeConstEvalStringLiteral(S.Context, E))
+  return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg,
+   Type, CallType, /*InFunctionCall*/ false,
+   CheckedVarArgs, UncoveredArg, Offset,
+   IgnoreStringsWithoutSpecifiers);
 return SLCT_NotALiteral;
   }
   case Stmt::ObjCMessageExprClass: {
@@ -8823,6 +8830,20 @@
   }
 }
 
+// If this expression can be evaluated at compile-time,
+// check if the result is a StringLiteral and return it
+// otherwise return nullptr
+static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
+   const Expr *E) {
+  Expr::EvalResult Result;
+  if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) {
+const auto *LVE = Result.Val.getLValueBase().dyn_cast();
+if (isa_and_nonnull(LVE))
+  return LVE;
+  }
+  return nullptr;
+}
+
 Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) {
   return llvm::StringSwitch(Format->getType()->getName())
   .Case("scanf", FST_Scanf)
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -67,6 +67,8 @@
   enum without a fixed underlying type is set to a value outside the range of
   the enumeration's values. Fixes
   `Issue 50055: `_.
+- Clang will now check compile-time determinable string literals as format strings.
+  This fixes `Issue 55805: `_.
 
 Non-comprehensive list of changes in this release
 -
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-04 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

In D130906#3699335 , @aaron.ballman 
wrote:

> In D130906#3699323 , @inclyc wrote:
>
>> Thank you!  I already have the commit access, I can commit this myself ^_^
>
> Excellent! Feel free to land when you're ready. :-)

Sorry I haven't noticed this yet, should I revert changes and commit again?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130906: [clang] format string checking for conpile-time evaluated str literal

2022-08-04 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Last question, issue https://github.com/llvm/llvm-project/issues/55805 
mentioned another case, some `initListExpr` evaulated as 
"StringLiteral"(`Array` in fact, but maybe able to consider as a literal), 
should we implement this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130906/new/

https://reviews.llvm.org/D130906

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a project: All.
inclyc added reviewers: aaron.ballman, rsmith, mizvekov, tbaeder.
inclyc added a project: clang.
inclyc added a subscriber: clang.
inclyc published this revision for review.
Herald added a subscriber: cfe-commits.

this patch enhances clang check format strings defined in list
initialization expressions. Before this patch clang just thought these
expressions are not string literal.

Example:

  constexpr const char *foo() { return "%s %d"; }
  
  struct Bar {
static constexpr char value[] = {'%', 's', '%', 'd', '\0'};
  };
  
  constexpr const char *foobar() { return Bar::value; }
  
  constexpr const char *fbar() { return foobar(); }
  
  int main() {
printf(foo(), "abc", "def");
printf(Bar::value, "abc", "def");
printf(foobar(), "abc", "def");
printf(fbar(), "abc", "def");
return 0;
  }

Diagnostics after this patch:

  :14:24: warning: format specifies type 'int' but the argument has 
type 'const char *' [-Wformat]
printf(foo(), "abc", "def");
   ~ ^
  :3:42: note: format string is defined here
  constexpr const char *foo() { return "%s %d"; }
   ^~
   %s
  :15:29: warning: format specifies type 'int' but the argument has 
type 'const char *' [-Wformat]
printf(Bar::value, "abc", "def");
  ^
  :16:27: warning: format specifies type 'int' but the argument has 
type 'const char *' [-Wformat]
printf(foobar(), "abc", "def");
^
  :17:29: warning: format specifies type 'int' but the argument has 
type 'const char *' [-Wformat]
printf(fbar(), "abc", "def");
  ^
  4 warnings generated.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall

[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450494.
inclyc added a comment.

typo fix


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can be
@@ -8535,18 +8535

[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450495.
inclyc added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can be
@@ -8535,18 +8535,18 @@

[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450496.
inclyc added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can be
@@ -8535,18 +8535,18 @@

[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

There are too many things changed in this patch, I think the function of 
displaying the evaluation results, `FIXME` warning, these can be done in 
subsequent patches.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450528.
inclyc added a comment.

Use isa<> to check Expr class


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can

[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450530.
inclyc added a comment.

rebase && qualify `const`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can be

[PATCH] D131277: clang: fix typo availbility

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc accepted this revision.
inclyc added a comment.
This revision is now accepted and ready to land.

LGTM. Could you please provide your real name and email address, like Name 
 ? So that I can commit this for you. Also feel free to ask for 
commit access.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131277/new/

https://reviews.llvm.org/D131277

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131258: [Sema] Merge variable template specializations

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Modules/merge-var-template-spec-cxx-modules.cpp:45
+export import var_def;
\ No newline at end of file


Missing newline



Comment at: clang/test/Modules/merge-var-template-spec.cpp:68
+#endif // VAR2_H
\ No newline at end of file


Missing newline


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131258/new/

https://reviews.llvm.org/D131258

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131277: clang: fix typo availbility

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

In D131277#3704510 , @sloorush wrote:

> @inclyc, Here is my real name and email address in the requested format:
>
> Aarush Bhat 
>
> I would love to get commit access. What exactly is the process? Do I have to 
> email as mentioned in 
> https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access?

Don't worry! Just feel free to send the email to Lattner, he is very fine.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131277/new/

https://reviews.llvm.org/D131277

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131277: clang: fix typo availbility

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa6cb8419b175: clang: fix typo availbility (authored by 
sloorush, committed by inclyc).

Changed prior to commit:
  https://reviews.llvm.org/D131277?vs=450339&id=450565#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131277/new/

https://reviews.llvm.org/D131277

Files:
  clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp


Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
===
--- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -494,7 +494,7 @@
   serializeObject(
   Obj, "location",
   serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
-  serializeObject(Obj, "availbility",
+  serializeObject(Obj, "availability",
   serializeAvailability(Record.Availability));
   serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
   serializeArray(Obj, "declarationFragments",


Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
===
--- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -494,7 +494,7 @@
   serializeObject(
   Obj, "location",
   serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
-  serializeObject(Obj, "availbility",
+  serializeObject(Obj, "availability",
   serializeAvailability(Record.Availability));
   serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
   serializeArray(Obj, "declarationFragments",
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131277: clang: fix typo availbility

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Copied from github comments:

Thanks for working on this, changes on serialization may still cause issue 
related to backward compatibility. Even though this patch passed all regression 
tests,  if in the future some one reports clang must give `availbility` (typo), 
we may have to revert this change.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131277/new/

https://reviews.llvm.org/D131277

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-06 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 450569.
inclyc added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

Files:
  clang/lib/Sema/SemaChecking.cpp
  clang/test/SemaCXX/format-strings.cpp

Index: clang/test/SemaCXX/format-strings.cpp
===
--- clang/test/SemaCXX/format-strings.cpp
+++ clang/test/SemaCXX/format-strings.cpp
@@ -166,6 +166,14 @@
 #if __cplusplus >= 201103L
 namespace evaluated {
 
+struct InitList {
+  static constexpr char value[] = {'%', 's', '%', 'd', '\0'}; // no note here because this is not literal
+};
+
+constexpr const char *init_list_func() { return InitList::value; }
+
+constexpr const char *init_list_func_wrap() { return init_list_func(); }
+
 constexpr const char *basic() { 
   return 
 "%s %d"; // expected-note {{format string is defined here}}
@@ -199,12 +207,15 @@
 
 void f() {
   printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
-  printf(correct_fmt(), 1, 2);
+  printf(correct_fmt(), 1, 2); // no warning
   printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
   printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}
   printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(InitList::value, 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
+  printf(init_list_func_wrap(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}
 }
 
 
-}
+} // namespace evaluated
 #endif
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -8469,25 +8469,26 @@
 Sema &S, const FormatStringLiteral *FExpr, const Expr *OrigFormatExpr,
 ArrayRef Args, Sema::FormatArgumentPassingKind APK,
 unsigned format_idx, unsigned firstDataArg, Sema::FormatStringType Type,
-bool inFunctionCall, Sema::VariadicCallType CallType,
+bool NoNote, Sema::VariadicCallType CallType,
 llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
 bool IgnoreStringsWithoutSpecifiers);
 
-static const Expr *maybeConstEvalStringLiteral(ASTContext &Context,
-   const Expr *E);
-
-// Determine if an expression is a string literal or constant string.
-// If this function returns false on the arguments to a function expecting a
-// format string, we will usually need to emit a warning.
-// True string literals are then checked by CheckFormatString.
 static StringLiteralCheckType
-checkFormatStringExpr(Sema &S, const Expr *E, ArrayRef Args,
-  Sema::FormatArgumentPassingKind APK, unsigned format_idx,
-  unsigned firstDataArg, Sema::FormatStringType Type,
-  Sema::VariadicCallType CallType, bool InFunctionCall,
-  llvm::SmallBitVector &CheckedVarArgs,
-  UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset,
-  bool IgnoreStringsWithoutSpecifiers = false) {
+checkVarDecl(Sema &S, const Expr *E, ArrayRef Args,
+ Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+ unsigned firstDataArg, Sema::FormatStringType Type,
+ Sema::VariadicCallType CallType, bool NoNote,
+ llvm::SmallBitVector &CheckedVarArgs,
+ UncoveredArgHandler &UncoveredArg, llvm::APSInt Offset, QualType T,
+ const VarDecl *VD, bool IgnoreStringsWithoutSpecifiers);
+
+static StringLiteralCheckType checkFormatStringExprEvaluated(
+Sema &S, const Expr *E, ArrayRef Args,
+Sema::FormatArgumentPassingKind APK, unsigned format_idx,
+unsigned firstDataArg, Sema::FormatStringType Type,
+Sema::VariadicCallType CallType, bool NoNote,
+llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg,
+llvm::APSInt Offset, bool IgnoreStringsWithoutSpecifiers = false) {
   if (S.isConstantEvaluated())
 return SLCT_NotALiteral;
 tryAgain:
@@ -8510,8 +8511,7 @@
   case Stmt::ConditionalOperatorClass: {
 // The expression is a literal if both sub-expressions were, and it was
 // completely checked only if both sub-expressions were checked.
-const AbstractConditionalOperator *C =
-cast(E);
+const AbstractConditionalOperator *C = cast(E);
 
 // Determine whether it is necessary to check both sub-expressions, for
 // example, because the condition expression is a constant that can be
@@ -8535,18 +8535,1

[PATCH] D130394: [clang][CodeGen] Factor out Swift ABI hooks (NFCI)

2022-08-07 Thread YingChi Long via Phabricator via cfe-commits
inclyc accepted this revision.
inclyc added a comment.

(Not a serious review) It seems like that your patch has already been accepted, 
so that I can commit this patch for you.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130394/new/

https://reviews.llvm.org/D130394

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130394: [clang][CodeGen] Factor out Swift ABI hooks (NFCI)

2022-08-07 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG87dc7d4b619d: [clang][CodeGen] Factor out Swift ABI hooks 
(NFCI) (authored by barannikov88, committed by inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130394/new/

https://reviews.llvm.org/D130394

Files:
  clang/lib/CodeGen/ABIInfo.h
  clang/lib/CodeGen/SwiftCallingConv.cpp
  clang/lib/CodeGen/TargetInfo.cpp
  clang/lib/CodeGen/TargetInfo.h

Index: clang/lib/CodeGen/TargetInfo.h
===
--- clang/lib/CodeGen/TargetInfo.h
+++ clang/lib/CodeGen/TargetInfo.h
@@ -38,6 +38,7 @@
 class CallArgList;
 class CodeGenFunction;
 class CGBlockInfo;
+class SwiftABIInfo;
 
 /// TargetCodeGenInfo - This class organizes various target-specific
 /// codegeneration issues, like target-specific attributes, builtins and so
@@ -45,6 +46,12 @@
 class TargetCodeGenInfo {
   std::unique_ptr Info;
 
+protected:
+  // Target hooks supporting Swift calling conventions. The target must
+  // initialize this field if it claims to support these calling conventions
+  // by returning true from TargetInfo::checkCallingConvention for them.
+  std::unique_ptr SwiftInfo;
+
 public:
   TargetCodeGenInfo(std::unique_ptr Info);
   virtual ~TargetCodeGenInfo();
@@ -52,6 +59,12 @@
   /// getABIInfo() - Returns ABI info helper for the target.
   const ABIInfo &getABIInfo() const { return *Info; }
 
+  /// Returns Swift ABI info helper for the target.
+  const SwiftABIInfo &getSwiftABIInfo() const {
+assert(SwiftInfo && "Swift ABI info has not been initialized");
+return *SwiftInfo;
+  }
+
   /// setTargetAttributes - Provides a convenient hook to handle extra
   /// target-specific attributes for the given global.
   virtual void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
Index: clang/lib/CodeGen/TargetInfo.cpp
===
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -23,7 +23,6 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
-#include "clang/CodeGen/SwiftCallingConv.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -117,7 +116,9 @@
   return false;
 }
 
-ABIInfo::~ABIInfo() {}
+ABIInfo::~ABIInfo() = default;
+
+SwiftABIInfo::~SwiftABIInfo() = default;
 
 /// Does the given lowering require more than the given number of
 /// registers when expanded?
@@ -151,12 +152,16 @@
   return (intCount + fpCount > maxAllRegisters);
 }
 
-bool SwiftABIInfo::isLegalVectorTypeForSwift(CharUnits vectorSize,
- llvm::Type *eltTy,
- unsigned numElts) const {
+bool SwiftABIInfo::shouldPassIndirectly(ArrayRef ComponentTys,
+bool AsReturnValue) const {
+  return occupiesMoreThan(CGT, ComponentTys, /*total=*/4);
+}
+
+bool SwiftABIInfo::isLegalVectorType(CharUnits VectorSize, llvm::Type *EltTy,
+ unsigned NumElts) const {
   // The default implementation of this assumes that the target guarantees
   // 128-bit SIMD support but nothing more.
-  return (vectorSize.getQuantity() > 8 && vectorSize.getQuantity() <= 16);
+  return (VectorSize.getQuantity() > 8 && VectorSize.getQuantity() <= 16);
 }
 
 static CGCXXABI::RecordArgABI getRecordArgABI(const RecordType *RT,
@@ -814,7 +819,7 @@
 // This is a very simple ABI that relies a lot on DefaultABIInfo.
 //===--===//
 
-class WebAssemblyABIInfo final : public SwiftABIInfo {
+class WebAssemblyABIInfo final : public ABIInfo {
 public:
   enum ABIKind {
 MVP = 0,
@@ -827,7 +832,7 @@
 
 public:
   explicit WebAssemblyABIInfo(CodeGen::CodeGenTypes &CGT, ABIKind Kind)
-  : SwiftABIInfo(CGT), defaultInfo(CGT), Kind(Kind) {}
+  : ABIInfo(CGT), defaultInfo(CGT), Kind(Kind) {}
 
 private:
   ABIArgInfo classifyReturnType(QualType RetTy) const;
@@ -845,22 +850,16 @@
 
   Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
 QualType Ty) const override;
-
-  bool shouldPassIndirectlyForSwift(ArrayRef scalars,
-bool asReturnValue) const override {
-return occupiesMoreThan(CGT, scalars, /*total*/ 4);
-  }
-
-  bool isSwiftErrorInRegister() const override {
-return false;
-  }
 };
 
 class WebAssemblyTargetCodeGenInfo final : public TargetCodeGenInfo {
 public:
   explicit WebAssemblyTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
 WebAssemblyABIInfo::ABIKind K)
-  : TargetCodeGenInfo(std::make_unique(CGT, K)) {}
+  : TargetCodeGenInfo(std::make_unique(CGT, K)) {
+   

[PATCH] D130394: [clang][CodeGen] Factor out Swift ABI hooks (NFCI)

2022-08-07 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

I think in fact you are now fully qualified to apply for commit access. Don't 
worry, Lattner generally trusts all developers willing to contribute to LLVM.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130394/new/

https://reviews.llvm.org/D130394

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a project: All.
inclyc added reviewers: aaron.ballman, gribozavr2.
inclyc added a subscriber: clang.
inclyc added a reviewer: NoQ.
inclyc published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Crash input:

  template bool b = __is_constructible(Ts...);
  bool x = b<>;

See https://godbolt.org/z/q39W78hsK.

Fixes https://github.com/llvm/llvm-project/issues/57008


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131423

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp


Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...);
+bool x = b<>;
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5304,6 +5304,8 @@
 //   variable t:
 //
 // T t(create()...);
+if (Args.empty())
+  return false;
 assert(!Args.empty());
 
 // Precondition: T and all types in the parameter pack Args shall be


Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...);
+bool x = b<>;
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5304,6 +5304,8 @@
 //   variable t:
 //
 // T t(create()...);
+if (Args.empty())
+  return false;
 assert(!Args.empty());
 
 // Precondition: T and all types in the parameter pack Args shall be
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

GCC MSVC ICC seems to have some different behavior, clang after introducing 
this patch will think there is no problem with the code and output binary 
files, and `x` evaluates to `false`

https://godbolt.org/z/hvbqTYMsx


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131466: [clang] add APValue type check in `TryPrintAsStringLiteral`

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc created this revision.
Herald added a project: All.
inclyc added reviewers: rsmith, aaron.ballman, shafik.
inclyc updated this revision to Diff 451047.
inclyc added a comment.
inclyc edited the summary of this revision.
inclyc published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

.


Fixes https://github.com/llvm/llvm-project/issues/57013

https://reviews.llvm.org/D115031 improved printing of non-type template
parameter args. But checking if the end of Inits is 0 without checking
if APValue is an integer, causes clang to segfault. This patch adds
the code to check the type. (May not be a proper bugfix.)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D131466

Files:
  clang/lib/AST/APValue.cpp


Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');


Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131466: [clang] add APValue type check in `TryPrintAsStringLiteral`

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 451049.
inclyc edited the summary of this revision.
inclyc added a comment.

Address reviewer's comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131466/new/

https://reviews.llvm.org/D131466

Files:
  clang/lib/AST/APValue.cpp


Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.


Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc reclaimed this revision.
inclyc added a comment.

It seems  that we are missing checks about if there is no enough parameter to 
intrinsic template `__is_constructible` here, and we should report an error. 
[WIP]


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-08 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 451056.
inclyc added a comment.

check argument number before evaulating


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp


Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...);
+bool x = b<>;
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5427,11 +5427,31 @@
 }
 }
 
+static bool CheckTypeTraitArgNumber(TypeTrait Kind, size_t N) {
+  if (Kind <= UTT_Last)
+return N == 1;
+  if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
+return N == 2;
+  switch (Kind) {
+  case clang::BTT_ReferenceBindsToTemporary:
+  case clang::TT_IsConstructible:
+  case clang::TT_IsNothrowConstructible:
+  case clang::TT_IsTriviallyConstructible: {
+return N >= 1;
+  }
+  default:
+llvm_unreachable("not a TT");
+  }
+}
+
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
   QualType ResultType = Context.getLogicalOperationType();
 
+  if (!CheckTypeTraitArgNumber(Kind, Args.size()))
+return ExprError();
+
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
*this, Kind, KWLoc, Args[0]->getType()))
 return ExprError();


Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...);
+bool x = b<>;
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5427,11 +5427,31 @@
 }
 }
 
+static bool CheckTypeTraitArgNumber(TypeTrait Kind, size_t N) {
+  if (Kind <= UTT_Last)
+return N == 1;
+  if (Kind <= BTT_Last && Kind != BTT_ReferenceBindsToTemporary)
+return N == 2;
+  switch (Kind) {
+  case clang::BTT_ReferenceBindsToTemporary:
+  case clang::TT_IsConstructible:
+  case clang::TT_IsNothrowConstructible:
+  case clang::TT_IsTriviallyConstructible: {
+return N >= 1;
+  }
+  default:
+llvm_unreachable("not a TT");
+  }
+}
+
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
   QualType ResultType = Context.getLogicalOperationType();
 
+  if (!CheckTypeTraitArgNumber(Kind, Args.size()))
+return ExprError();
+
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
*this, Kind, KWLoc, Args[0]->getType()))
 return ExprError();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5445
+  }
+}
+

tbaeder wrote:
> This function copies the two conditions for the if-statements from 
> `evaluateTypeTrait()`. Is just doing it in `evaluateTypeTrait()` too late? 
> Duplicating that seems bad.
`evaluateTypeTrait()` should return evaluate result, i.e. bool value `true` / 
`false`, if we do this in `evaluateTypeTrait()` , how can we express that we 
encountered some error? I think it is reasonable to split these conditions here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5445
+  }
+}
+

inclyc wrote:
> tbaeder wrote:
> > This function copies the two conditions for the if-statements from 
> > `evaluateTypeTrait()`. Is just doing it in `evaluateTypeTrait()` too late? 
> > Duplicating that seems bad.
> `evaluateTypeTrait()` should return evaluate result, i.e. bool value `true` / 
> `false`, if we do this in `evaluateTypeTrait()` , how can we express that we 
> encountered some error? I think it is reasonable to split these conditions 
> here.
Do you think we should add a condition checks to the evaluate function 
`evaluateTypeTrait()` and return `false` if it is not satisfied?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131466: [clang] add APValue type check in `TryPrintAsStringLiteral`

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 451195.
inclyc added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131466/new/

https://reviews.llvm.org/D131466

Files:
  clang/lib/AST/APValue.cpp
  clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp


Index: clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
+// expected-no-diagnostics
+
+// Reported by: https://github.com/llvm/llvm-project/issues/57013
+// The following code should not crash clang
+struct X {
+  char arr[2];
+  constexpr X() {}
+  constexpr void modify() {
+arr[0] = 0;
+  }
+};
+constexpr X f(X t) {
+t.modify();
+return t;
+}
+auto x = f(X());
Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.


Index: clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
+// expected-no-diagnostics
+
+// Reported by: https://github.com/llvm/llvm-project/issues/57013
+// The following code should not crash clang
+struct X {
+  char arr[2];
+  constexpr X() {}
+  constexpr void modify() {
+arr[0] = 0;
+  }
+};
+constexpr X f(X t) {
+t.modify();
+return t;
+}
+auto x = f(X());
Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131466: [clang] add APValue type check in `TryPrintAsStringLiteral`

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp:7
+struct X {
+  char arr[2];
+  constexpr X() {}

The `ArrayRef Inits` points to here does not ends with `Int`, so 
`!Inits.back().getInt()` gets assertion failed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131466/new/

https://reviews.llvm.org/D131466

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131314: [clang] format string checks for `InitListExpr`

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

In D131314#3710331 , @aaron.ballman 
wrote:

> In D131314#3707131 , @inclyc wrote:
>
>> ping
>
> FWIW, we usually only ping a review that hasn't had any activity in a week or 
> more (it's not uncommon for reviews to sit for a few days while people think 
> about them or reviewers are busy on other stuff).
>
> I've not had the chance to do an in-depth review yet, but I have two thoughts 
> I can share early on. I think you can simplify the patch a little bit by 
> treating a string literal and an initializer list the same way (using an 
> iterator to walk over the elements) instead of ginning up a fake 
> `StringLiteral` AST node (that's a very heavy handed way to implement this). 
> However, even with that simplification, I'm not certain the use cases for the 
> diagnostic happen enough to warrant this large of a change in how we process 
> format strings. I had encouraged such a diagnostic given the equivalence of 
> the construct with string literals, but I was imagining that the support 
> would be a few lines of code rather than anything substantial like this. 
> Perhaps you can find a way to make the changes less invasive, but if not, I 
> think we may want to hold off on this change until a user files an issue 
> pointing out some real world code that would be easier to fix if they had 
> such a diagnostic.

Clang seems to depend class `FormatStringLiteral`  when performing format 
string checking, which has its `SourceLocation`, a wrapped pointer. With these 
information we can generate FixIt Hints directly on source codes. In previous 
version, we probably haven't even considered checking the format string 
evaluated from `InitListExpr` (just consider it is not a string literal). I've 
tried adding some ways to treat them as equals before, but it seems more 
invasive than this patch. Actually, I don't think any user would ever define a 
format string like `{'%', 'd', 0}` (That's exactly the reason I split format 
string checks in two patches). So maybe we should abandon this patch because 
there are no  enough benefits to apply this?

> but it seems more invasive than this patch.

It may be necessary to separate out the existing parts that check for 
formatting strings and related location information, because `InitListExpr` may 
not have proper information of source code location that can be determined 
during the format string checking.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131314/new/

https://reviews.llvm.org/D131314

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
inclyc planned changes to this revision.
inclyc added inline comments.



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5431
+static bool CheckTypeTraitArgNumber(TypeTrait Kind, size_t N) {
+  if (Kind <= UTT_Last)
+return N == 1;

I think we should report a warning or an error if this function fails.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131466: [clang] add APValue type check in `TryPrintAsStringLiteral`

2022-08-09 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG55d3b79d159b: [clang] add APValue type check in 
`TryPrintAsStringLiteral` (authored by inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131466/new/

https://reviews.llvm.org/D131466

Files:
  clang/lib/AST/APValue.cpp
  clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp


Index: clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
+// expected-no-diagnostics
+
+// Reported by: https://github.com/llvm/llvm-project/issues/57013
+// The following code should not crash clang
+struct X {
+  char arr[2];
+  constexpr X() {}
+  constexpr void modify() {
+arr[0] = 0;
+  }
+};
+constexpr X f(X t) {
+t.modify();
+return t;
+}
+auto x = f(X());
Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.


Index: clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/try-print-as-string-literal-type-check.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
+// expected-no-diagnostics
+
+// Reported by: https://github.com/llvm/llvm-project/issues/57013
+// The following code should not crash clang
+struct X {
+  char arr[2];
+  constexpr X() {}
+  constexpr void modify() {
+arr[0] = 0;
+  }
+};
+constexpr X f(X t) {
+t.modify();
+return t;
+}
+auto x = f(X());
Index: clang/lib/AST/APValue.cpp
===
--- clang/lib/AST/APValue.cpp
+++ clang/lib/AST/APValue.cpp
@@ -637,10 +637,10 @@
 return false;
 
   // Nothing we can do about a sequence that is not null-terminated
-  if (!Inits.back().getInt().isZero())
+  if (!Inits.back().isInt() || !Inits.back().getInt().isZero())
 return false;
-  else
-Inits = Inits.drop_back();
+
+  Inits = Inits.drop_back();
 
   llvm::SmallString<40> Buf;
   Buf.push_back('"');
@@ -655,6 +655,8 @@
   }
 
   for (auto &Val : Inits) {
+if (!Val.isInt())
+  return false;
 int64_t Char64 = Val.getInt().getExtValue();
 if (!isASCII(Char64))
   return false; // Bye bye, see you in integers.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-10 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

@aaron.ballman @shafik  (Help wanted). These type traits will not cause clang 
to crash if current patch applied, but the `bool x` in that test case will 
evaluate to `false`.  I think the problem behind the github issue is that we 
don't check the number of arguments for builtin type trait like 
`__is_constructible`

I wanted to ask what is our expected behavior for this, give an error like 
using `std::is_constructible` or just consider `__is_constructible` should 
always have a bool value? Should we report a warning but compile translation 
unit, or report an error and terminate?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-17 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:3-4
+
+while(1) {}; // expected-error {{expected identifier or '('}} \
+ // expected-note {{while loop outside of functions}}
+

mizvekov wrote:
> How about just making the error be the same thing the note would say?
> 
> 
OK, so just create a new error directly, and then report the error when 
encountering the `while` token?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 445455.
inclyc edited the summary of this revision.
inclyc added a comment.

Now it only generates 1 error encountering token "while"

  ./local/while_loop_outside_func.cpp:1:1: error: while loop outside of function
  while (true) {
  ^
  1 error generated.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp


Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of function}} \
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of function}} \
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(1) {}; // expected-error {{while loop outside of function}} \
+
+// without semicolon
+while(1) {} // expected-error {{while loop outside of function}} \
+
+void some_fn();
+
+void some_fn() {
+while(1) {};
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), 
diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_function : Error<
+  "while loop outside of function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %select{identifier|name}0">;


Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of function}} \
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of function}} \
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+void some_fn() {
+while(true) {}

[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 445458.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp


Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of function}}
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of function}}
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(1) {}; // expected-error {{while loop outside of function}}
+
+// without semicolon
+while(1) {} // expected-error {{while loop outside of function}}
+
+void some_fn();
+
+void some_fn() {
+while(1) {};
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), 
diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_function : Error<
+  "while loop outside of function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %select{identifier|name}0">;


Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of function}}
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of function}}
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+

[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:8
+
+void some_fn();
+

mizvekov wrote:
> Can you add a few more test cases showing how error recovery is performing 
> here?
> 
> Have we parsed this function declaration at all, or were we skipping until 
> the next ';'?
> 
> What happens if there are (multiple) statements in the loop's block?
> 
> How do we handle a `do ... while()` loop instead?
> 
> Does it make a difference if the loop contains a block or a (possibly empty) 
> single statement?
For this occasion, 

```
// RUN: %clang_cc1 -fsyntax-only -verify %s

while(true) {}; // expected-error {{while loop outside of function}}

// without semicolon
while(true) {} // expected-error {{while loop outside of function}}


while(true) {
// some statements
int some_var = 3;
some_var += 2;
}

while(true) 
{
// some statements
int some_var = 3;
some_var += 2;
}

do {
int some_var = 1;
some_var += 3;
} 
while(true);

void someFunction() {
while(true) {};
}

class SomeClass {
public:
while(true) {}
void some_fn() {
while(true) {}
}
};

```

```
./clang/test/Parser/while-loop-outside-function.cpp:3:1: error: while loop 
outside of function
while(true) {}; // expected-error {{while loop outside of function}}
^
./clang/test/Parser/while-loop-outside-function.cpp:6:1: error: while loop 
outside of function
while(true) {} // expected-error {{while loop outside of function}}
^
./clang/test/Parser/while-loop-outside-function.cpp:9:1: error: while loop 
outside of function
while(true) {
^
./clang/test/Parser/while-loop-outside-function.cpp:15:1: error: while loop 
outside of function
while(true) 
^
./clang/test/Parser/while-loop-outside-function.cpp:22:1: error: expected 
unqualified-id
do {
^
./clang/test/Parser/while-loop-outside-function.cpp:26:1: error: while loop 
outside of function
while(true);
^
./clang/test/Parser/while-loop-outside-function.cpp:34:5: error: expected 
member name or ';' after declaration specifiers
while(true) {}
^
7 errors generated.
```

The parser generates the newly added error for every "top-level" declarator. 
For `do ... while(...)` loops it generates two errors. I think ideally only one 
error should be reported, only generating an error at the latter while token, 
without generating a "noise" at the preceding `do`. And, this patch doesn't 
seem to produce good results where classes, structs, etc. are also not part of 
the function body.

At first, when I solved this issue, I thought he only needed to report the 
appearance of the top-level while loop, without considering do-while, in a 
class, or in a structure. So the current code is only in Parser, this error is 
reported when the `while` token is encountered parsing declarators.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:3
+
+while(1) {}; // expected-error {{while loop outside of function}}
+

mizvekov wrote:
> You could break this down further into more lines to test exactly where the 
> error is placed. Id expect it to be placed at the `while` keyword.
Passes this test case, I will submit this in the next patch.

```
// RUN: %clang_cc1 -fsyntax-only -verify %s

while(1) {}; // expected-error {{while loop outside of function}}


while(1) // expected-error {{while loop outside of function}}
{

}

while(1) { // expected-error {{while loop outside of function}}

}

while(1) { // expected-error {{while loop outside of function}}

};

while(1) // expected-error {{while loop outside of function}}
{

}

while(1) { // expected-error {{while loop outside of function}}

};

// without semicolon
while(1) {} // expected-error {{while loop outside of function}}

void some_fn();

void some_fn() {
while(1) {};
}
```


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:8
+
+void some_fn();
+

mizvekov wrote:
> inclyc wrote:
> > mizvekov wrote:
> > > Can you add a few more test cases showing how error recovery is 
> > > performing here?
> > > 
> > > Have we parsed this function declaration at all, or were we skipping 
> > > until the next ';'?
> > > 
> > > What happens if there are (multiple) statements in the loop's block?
> > > 
> > > How do we handle a `do ... while()` loop instead?
> > > 
> > > Does it make a difference if the loop contains a block or a (possibly 
> > > empty) single statement?
> > For this occasion, 
> > 
> > ```
> > // RUN: %clang_cc1 -fsyntax-only -verify %s
> > 
> > while(true) {}; // expected-error {{while loop outside of function}}
> > 
> > // without semicolon
> > while(true) {} // expected-error {{while loop outside of function}}
> > 
> > 
> > while(true) {
> > // some statements
> > int some_var = 3;
> > some_var += 2;
> > }
> > 
> > while(true) 
> > {
> > // some statements
> > int some_var = 3;
> > some_var += 2;
> > }
> > 
> > do {
> > int some_var = 1;
> > some_var += 3;
> > } 
> > while(true);
> > 
> > void someFunction() {
> > while(true) {};
> > }
> > 
> > class SomeClass {
> > public:
> > while(true) {}
> > void some_fn() {
> > while(true) {}
> > }
> > };
> > 
> > ```
> > 
> > ```
> > ./clang/test/Parser/while-loop-outside-function.cpp:3:1: error: while loop 
> > outside of function
> > while(true) {}; // expected-error {{while loop outside of function}}
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:6:1: error: while loop 
> > outside of function
> > while(true) {} // expected-error {{while loop outside of function}}
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:9:1: error: while loop 
> > outside of function
> > while(true) {
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:15:1: error: while loop 
> > outside of function
> > while(true) 
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:22:1: error: expected 
> > unqualified-id
> > do {
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:26:1: error: while loop 
> > outside of function
> > while(true);
> > ^
> > ./clang/test/Parser/while-loop-outside-function.cpp:34:5: error: expected 
> > member name or ';' after declaration specifiers
> > while(true) {}
> > ^
> > 7 errors generated.
> > ```
> > 
> > The parser generates the newly added error for every "top-level" 
> > declarator. For `do ... while(...)` loops it generates two errors. I think 
> > ideally only one error should be reported, only generating an error at the 
> > latter while token, without generating a "noise" at the preceding `do`. 
> > And, this patch doesn't seem to produce good results where classes, 
> > structs, etc. are also not part of the function body.
> > 
> > At first, when I solved this issue, I thought he only needed to report the 
> > appearance of the top-level while loop, without considering do-while, in a 
> > class, or in a structure. So the current code is only in Parser, this error 
> > is reported when the `while` token is encountered parsing declarators.
> I see, thanks for the explanations.
> 
> I think this patch is a very simple change that brings some improvement, and 
> apparently it does not regress anything or cause any unfortunate error 
> recovery.
> 
> You don't really need to improve these other cases in the same patch, I am 
> just checking that this was all considered :-)
> 
> But please do add these test cases to the patch!
Do you think we need to change something more to accurately report `while` / 
`do-while` / `for`  loops, and only report errors outside of a reasonable 
control flow?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [Clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:8
+
+void some_fn();
+

inclyc wrote:
> mizvekov wrote:
> > inclyc wrote:
> > > mizvekov wrote:
> > > > Can you add a few more test cases showing how error recovery is 
> > > > performing here?
> > > > 
> > > > Have we parsed this function declaration at all, or were we skipping 
> > > > until the next ';'?
> > > > 
> > > > What happens if there are (multiple) statements in the loop's block?
> > > > 
> > > > How do we handle a `do ... while()` loop instead?
> > > > 
> > > > Does it make a difference if the loop contains a block or a (possibly 
> > > > empty) single statement?
> > > For this occasion, 
> > > 
> > > ```
> > > // RUN: %clang_cc1 -fsyntax-only -verify %s
> > > 
> > > while(true) {}; // expected-error {{while loop outside of function}}
> > > 
> > > // without semicolon
> > > while(true) {} // expected-error {{while loop outside of function}}
> > > 
> > > 
> > > while(true) {
> > > // some statements
> > > int some_var = 3;
> > > some_var += 2;
> > > }
> > > 
> > > while(true) 
> > > {
> > > // some statements
> > > int some_var = 3;
> > > some_var += 2;
> > > }
> > > 
> > > do {
> > > int some_var = 1;
> > > some_var += 3;
> > > } 
> > > while(true);
> > > 
> > > void someFunction() {
> > > while(true) {};
> > > }
> > > 
> > > class SomeClass {
> > > public:
> > > while(true) {}
> > > void some_fn() {
> > > while(true) {}
> > > }
> > > };
> > > 
> > > ```
> > > 
> > > ```
> > > ./clang/test/Parser/while-loop-outside-function.cpp:3:1: error: while 
> > > loop outside of function
> > > while(true) {}; // expected-error {{while loop outside of function}}
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:6:1: error: while 
> > > loop outside of function
> > > while(true) {} // expected-error {{while loop outside of function}}
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:9:1: error: while 
> > > loop outside of function
> > > while(true) {
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:15:1: error: while 
> > > loop outside of function
> > > while(true) 
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:22:1: error: expected 
> > > unqualified-id
> > > do {
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:26:1: error: while 
> > > loop outside of function
> > > while(true);
> > > ^
> > > ./clang/test/Parser/while-loop-outside-function.cpp:34:5: error: expected 
> > > member name or ';' after declaration specifiers
> > > while(true) {}
> > > ^
> > > 7 errors generated.
> > > ```
> > > 
> > > The parser generates the newly added error for every "top-level" 
> > > declarator. For `do ... while(...)` loops it generates two errors. I 
> > > think ideally only one error should be reported, only generating an error 
> > > at the latter while token, without generating a "noise" at the preceding 
> > > `do`. And, this patch doesn't seem to produce good results where classes, 
> > > structs, etc. are also not part of the function body.
> > > 
> > > At first, when I solved this issue, I thought he only needed to report 
> > > the appearance of the top-level while loop, without considering do-while, 
> > > in a class, or in a structure. So the current code is only in Parser, 
> > > this error is reported when the `while` token is encountered parsing 
> > > declarators.
> > I see, thanks for the explanations.
> > 
> > I think this patch is a very simple change that brings some improvement, 
> > and apparently it does not regress anything or cause any unfortunate error 
> > recovery.
> > 
> > You don't really need to improve these other cases in the same patch, I am 
> > just checking that this was all considered :-)
> > 
> > But please do add these test cases to the patch!
> Do you think we need to change something more to accurately report `while` / 
> `do-while` / `for`  loops, and only report errors outside of a reasonable 
> control flow?
Right now this patch is far from perfect, ideally it should report various 
types of loops (as mentioned above) and also in a non-control flow context, 
such as class members, typedefs, etc. (I don't know how to do this, sorry)


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 445668.
inclyc retitled this revision from "[Clang] add a diagnostic note 'while loop 
outside functions' at global scope" to "[clang] add a diagnostic note 'while 
loop outside functions' at global scope".

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp

Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of a function}}
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of a function}}
+
+
+while(true) { // expected-error {{while loop outside of a function}}
+// some statements
+int some_var = 3;
+some_var += 2;
+}
+
+while(true) // expected-error {{while loop outside of a function}}
+{
+// some statements
+int some_var = 3;
+some_var += 2;
+}
+
+do { // expected-error {{expected unqualified-id}}
+int some_var = 1;
+some_var += 3;
+} 
+while(true); // expected-error {{while loop outside of a function}}
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}}
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// basic
+while(1) {}; // expected-error {{while loop outside of a function}}
+
+
+// without semicolon
+while(1) {} // expected-error {{while loop outside of a function}}
+
+// empty statement without semicolon
+while(1) // expected-error {{while loop outside of a function}}
+{
+
+}
+
+// empty statement without semicolon, inline l_paren
+while(1) { // expected-error {{while loop outside of a function}}
+
+}
+
+// empty statement, inline l_paren
+while(1) { // expected-error {{while loop outside of a function}}
+
+};
+
+// empty statement without semicolon
+while(1) // expected-error {{while loop outside of a function}}
+{
+
+}
+
+// empty statement
+while(1) { // expected-error {{while loop outside of a function}}
+
+};
+
+// some statements
+while(1) { // expected-error {{while loop outside of a function}}
+int some_var = 0;
+};
+
+
+// some statements
+while(1)  // expected-error {{while loop outside of a function}}
+{
+int some_var = 0;
+}
+
+// recovery
+void some_fn();
+
+void some_fn() {
+while(1) {};
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_of_a_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identif

[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-19 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 445712.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp

Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of a function}}
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of a function}}
+
+while(true)  // expected-error {{while loop outside of a function}}
+{
+// some statements
+int some_var = 3;
+some_var += 2;
+}
+
+do { // expected-error {{expected unqualified-id}}
+int some_var = 1;
+some_var += 3;
+} 
+while(true); // expected-error {{while loop outside of a function}}
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}}
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// basic
+while(1) {}; // expected-error {{while loop outside of a function}}
+
+
+// location?
+while(1) // expected-error {{while loop outside of a function}}
+{};
+
+// empty statement without semicolon
+while(1) // expected-error {{while loop outside of a function}}
+{}
+
+// some statements
+while(1)  // expected-error {{while loop outside of a function}}
+{
+int some_var = 0;
+}
+
+// recovery
+void some_fn();
+
+void some_fn() {
+while(1) {};
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_of_a_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_of_a_function : Error<
+  "while loop outside of a function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %select{identifier|name}0">;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mai

[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-19 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 445771.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp

Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while(true) {}; // expected-error {{while loop outside of a function}}
+
+// without semicolon
+while(true) {} // expected-error {{while loop outside of a function}}
+
+while(true)  // expected-error {{while loop outside of a function}}
+{
+// some statements
+int some_var = 3;
+some_var += 2;
+}
+
+do { // expected-error {{expected unqualified-id}}
+int some_var = 1;
+some_var += 3;
+} 
+while(true); // expected-error {{while loop outside of a function}}
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}}
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// basic
+while(1) {}; // expected-error {{while loop outside of a function}}
+
+
+// location?
+while(1) // expected-error {{while loop outside of a function}}
+{};
+
+// empty statement without semicolon
+while(1) // expected-error {{while loop outside of a function}}
+{}
+
+// some statements
+while(1)  // expected-error {{while loop outside of a function}}
+{
+int some_var = 0;
+}
+
+// recovery
+void some_fn();
+
+void some_fn() {
+while(1) {};
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_of_a_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_of_a_function : Error<
+  "while loop outside of a function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %select{identifier|name}0">;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mai

[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-20 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Is the build error related to this patch?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-20 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

Could you please review the latest patch ? I have removed some redundant test 
cases mentioned above


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-21 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 446690.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp

Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while // expected-error {{while loop outside of a function}}
+(true) {};
+
+// without semicolon
+while // expected-error {{while loop outside of a function}}
+(true) {}
+
+do { // expected-error {{expected unqualified-id}}
+int some_var = 1;
+some_var += 3;
+} 
+while // expected-error {{while loop outside of a function}}
+(true); 
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}}
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while // expected-error {{while loop outside of a function}}
+(1) {};
+
+// without semicolon
+while // expected-error {{while loop outside of a function}}
+(1) {}
+
+int overload_return(); // expected-note {{previous declaration is here}}
+
+void overload_return() // expected-error {{conflicting types for 'overload_return'}}
+{ 
+while(1) {};
+while(1);
+}
+
+while // expected-error {{while loop outside of a function}}
+(1); 
+
+void correct();
+
+void correct() {
+while(1) {};
+while(1);
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_of_a_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_of_a_function : Error<
+  "while loop outside of a function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %select{identifier|name}0">;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [clang] add a diagnostic note 'while loop outside functions' at global scope

2022-07-21 Thread YingChi Long via Phabricator via cfe-commits
inclyc marked 2 inline comments as not done.
inclyc added inline comments.



Comment at: clang/test/Parser/while-loop-outside-function.c:3
+
+while // expected-error {{while loop outside of a function}}
+(1) {};

Thanks a lot for your suggestion, I replaced this statement with two lines to 
test if the diagnostics are correctly given at the token `while`.

The C++ test cases is also changed like this.



Comment at: clang/test/Parser/while-loop-outside-function.c:10
+
+int overload_return(); // expected-note {{previous declaration is here}}
+

This test case checks whether the program can correctly diagnose other errors 
after reporting our newly added error



Comment at: clang/test/Parser/while-loop-outside-function.c:24
+void correct() {
+while(1) {};
+while(1);

Should not give diagnostic information at these 2 lines of correct statements


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129573: [clang] better error message for while loops outside of control flow

2022-07-24 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGedaae251cca0: [clang] better error message for while loops 
outside of control flow (authored by inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129573/new/

https://reviews.llvm.org/D129573

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/test/Parser/while-loop-outside-function.c
  clang/test/Parser/while-loop-outside-function.cpp

Index: clang/test/Parser/while-loop-outside-function.cpp
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while // expected-error {{while loop outside of a function}}
+(true) {};
+
+// without semicolon
+while // expected-error {{while loop outside of a function}}
+(true) {}
+
+do { // expected-error {{expected unqualified-id}}
+int some_var = 1;
+some_var += 3;
+} 
+while // expected-error {{while loop outside of a function}}
+(true); 
+
+void someFunction() {
+while(true) {};
+}
+
+class SomeClass {
+public:
+while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}}
+void some_fn() {
+while(true) {}
+}
+};
Index: clang/test/Parser/while-loop-outside-function.c
===
--- /dev/null
+++ clang/test/Parser/while-loop-outside-function.c
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+while // expected-error {{while loop outside of a function}}
+(1) {};
+
+// without semicolon
+while // expected-error {{while loop outside of a function}}
+(1) {}
+
+int overload_return(); // expected-note {{previous declaration is here}}
+
+void overload_return() // expected-error {{conflicting types for 'overload_return'}}
+{ 
+while(1) {};
+while(1);
+}
+
+while // expected-error {{while loop outside of a function}}
+(1); 
+
+void correct();
+
+void correct() {
+while(1) {};
+while(1);
+}
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -6344,23 +6344,27 @@
diag::err_expected_member_name_or_semi)
   << (D.getDeclSpec().isEmpty() ? SourceRange()
 : D.getDeclSpec().getSourceRange());
-} else if (getLangOpts().CPlusPlus) {
-  if (Tok.isOneOf(tok::period, tok::arrow))
-Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
-  else {
-SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
-if (Tok.isAtStartOfLine() && Loc.isValid())
-  Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-else
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_unqualified_id)
-  << getLangOpts().CPlusPlus;
-  }
 } else {
-  Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
-   diag::err_expected_either)
-  << tok::identifier << tok::l_paren;
+  if (Tok.getKind() == tok::TokenKind::kw_while) {
+Diag(Tok, diag::err_while_loop_outside_of_a_function);
+  } else if (getLangOpts().CPlusPlus) {
+if (Tok.isOneOf(tok::period, tok::arrow))
+  Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);
+else {
+  SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();
+  if (Tok.isAtStartOfLine() && Loc.isValid())
+Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+  else
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_unqualified_id)
+<< getLangOpts().CPlusPlus;
+}
+  } else {
+Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),
+ diag::err_expected_either)
+<< tok::identifier << tok::l_paren;
+  }
 }
 D.SetIdentifier(nullptr, Tok.getLocation());
 D.setInvalidType(true);
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -538,6 +538,8 @@
   "cannot use %select{dot|arrow}0 operator on a type">;
 def err_expected_unqualified_id : Error<
   "expected %select{identifier|unqualified-id}0">;
+def err_while_loop_outside_of_a_function : Error<
+  "while loop outside of a function">; 
 def err_brackets_go_after_unqualified_id : Error<
   "brackets are not allowed here; to declare an array, "
   "place the brackets after the %s

[PATCH] D133248: [clang] Fix crash upon stray coloncolon token in C2x mode

2022-10-18 Thread YingChi Long via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG94e8bd002c81: [clang] Fix crash upon stray coloncolon token 
in C2x mode (authored by Jialun Hu , committed by 
inclyc).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133248/new/

https://reviews.llvm.org/D133248

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Parser/c2x-attributes.c


Index: clang/test/Parser/c2x-attributes.c
===
--- clang/test/Parser/c2x-attributes.c
+++ clang/test/Parser/c2x-attributes.c
@@ -141,3 +141,6 @@
 struct [[]] S4 *s; // expected-error {{an attribute list cannot appear here}}
 struct S5 {};
 int c = sizeof(struct [[]] S5); // expected-error {{an attribute list cannot 
appear here}}
+
+// Ensure that '::' outside of attributes does not crash and is not treated as 
scope
+double n::v; // expected-error {{expected ';' after top level declarator}}
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -2080,9 +2080,9 @@
 }
 
 if (!getLangOpts().CPlusPlus) {
-  // If we're in C, we can't have :: tokens at all (the lexer won't return
-  // them).  If the identifier is not a type, then it can't be scope 
either,
-  // just early exit.
+  // If we're in C, the only place we can have :: tokens is C2x
+  // attribute which is parsed elsewhere. If the identifier is not a type,
+  // then it can't be scope either, just early exit.
   return false;
 }
 
Index: clang/lib/Parse/ParseDecl.cpp
===
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -5411,6 +5411,8 @@
 return isDeclarationSpecifier(AllowImplicitTypename);
 
   case tok::coloncolon:   // ::foo::bar
+if (!getLangOpts().CPlusPlus)
+  return false;
 if (NextToken().is(tok::kw_new) ||// ::new
 NextToken().is(tok::kw_delete))   // ::delete
   return false;
Index: clang/include/clang/Parse/Parser.h
===
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -866,10 +866,11 @@
   bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
 
   bool MightBeCXXScopeToken() {
-return Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
-   (Tok.is(tok::annot_template_id) &&
-NextToken().is(tok::coloncolon)) ||
-   Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super);
+return getLangOpts().CPlusPlus &&
+   (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+(Tok.is(tok::annot_template_id) &&
+ NextToken().is(tok::coloncolon)) ||
+Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super));
   }
   bool TryAnnotateOptionalCXXScopeToken(bool EnteringContext = false) {
 return MightBeCXXScopeToken() && TryAnnotateCXXScopeToken(EnteringContext);
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -251,6 +251,7 @@
 - Address the thread identification problems in coroutines.
   `Issue 47177 `_
   `Issue 47179 `_
+- Fix a crash upon stray coloncolon token in C2x mode.
 
 Improvements to Clang's diagnostics
 ^^^


Index: clang/test/Parser/c2x-attributes.c
===
--- clang/test/Parser/c2x-attributes.c
+++ clang/test/Parser/c2x-attributes.c
@@ -141,3 +141,6 @@
 struct [[]] S4 *s; // expected-error {{an attribute list cannot appear here}}
 struct S5 {};
 int c = sizeof(struct [[]] S5); // expected-error {{an attribute list cannot appear here}}
+
+// Ensure that '::' outside of attributes does not crash and is not treated as scope
+double n::v; // expected-error {{expected ';' after top level declarator}}
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -2080,9 +2080,9 @@
 }
 
 if (!getLangOpts().CPlusPlus) {
-  // If we're in C, we can't have :: tokens at all (the lexer won't return
-  // them).  If the identifier is not a type, then it can't be scope either,
-  // just early exit.
+  // If we're in C, the only place we can have :: tokens is C2x
+  // attribute which is parsed elsewhere. If the identifier is not a type,
+  // then it can't be scope either, just early exit.
   return false

[PATCH] D133248: [clang] Fix crash upon stray coloncolon token in C2x mode

2022-10-18 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

In D133248#3865010 , @SuibianP wrote:

> @aaron.ballman Thanks for the guidance! I have rectified the parentheses and 
> appended to the release notes. Please feel free to point out any additional 
> issues with the Differential.
>
> If all is good, I would like to have the patch attributed to `Jialun Hu 
> `.

Thanks @SuibianP ! I've committed this for you.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D133248/new/

https://reviews.llvm.org/D133248

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D137043: [clang] add implicit include for Linux/gnu compatibility

2022-10-30 Thread YingChi Long via Phabricator via cfe-commits
inclyc added a comment.

> That is OK for glibc system because glibc includes this file manually. But 
> with other libc (e.g. musl), which does not manually include this, clang will 
> fail but GCC can get it compiled.

FWIW currently we cannot build libedit using clang on x86_64-unknown-linux-musl 
and to fix this issue, they have a workaround here 
https://patchwork.ozlabs.org/project/buildroot/patch/1452127277-9538-1-git-send-email-sergio.pr...@e-labworks.com/
 which manually defined `__STDC_ISO_10646__`

Reproducer:

  #include 
  // #include 
  
  int main() {
  printf("%d", __STDC_ISO_10646__);
  }

GCC accepted this code but clang complained `use of undeclared identifier 
'__STDC_ISO_10646__'`

  test.c:5:15: error: use of undeclared identifier '__STDC_ISO_10646__'
  printf("%d", __STDC_ISO_10646__);
   ^
  1 error generated.

Note that glibc includes `stdc-predefs.h` at the source-code level, so this 
problem cannot be reproduced on the glibc-based systems. (The header `stdio.h` 
actually #includes `stdc-predefs.h` in glibc!)

However if we do not #include `stdio.h`, different behaviors can be seen on 
glibc platforms.

  int main() {
return __STDC_ISO_10646__;
  }

See https://godbolt.org/z/Gd9Kbn766.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137043/new/

https://reviews.llvm.org/D137043

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-11 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 451931.
inclyc added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/include/clang/Basic/TypeTraits.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TypeTraits.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp

Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5430,6 +5430,8 @@
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();
   QualType ResultType = Context.getLogicalOperationType();
 
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -4581,6 +4581,21 @@
   } while (!T.isNull() && T->isVariablyModifiedType());
 }
 
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+  if (Arity && N != Arity) {
+Diag(Loc, diag::err_type_trait_arity)
+<< Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+return false;
+  }
+
+  if (!Arity && N == 0) {
+Diag(Loc, diag::err_type_trait_arity)
+<< 1 << 1 << 1 << (int)N << SourceRange(Loc);
+return false;
+  }
+  return true;
+}
+
 /// Build a sizeof or alignof expression given a type operand.
 ExprResult
 Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3724,14 +3724,6 @@
   }
 }
 
-static unsigned TypeTraitArity(tok::TokenKind kind) {
-  switch (kind) {
-default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
-  }
-}
-
 /// Parse the built-in type-trait pseudo-functions that allow
 /// implementation of the TR1/C++11 type traits templates.
 ///
@@ -3745,7 +3737,6 @@
 ///
 ExprResult Parser::ParseTypeTrait() {
   tok::TokenKind Kind = Tok.getKind();
-  unsigned Arity = TypeTraitArity(Kind);
 
   SourceLocation Loc = ConsumeToken();
 
@@ -3780,18 +3771,6 @@
 
   SourceLocation EndLoc = Parens.getCloseLocation();
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
   return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
 }
 
Index: clang/lib/Basic/TypeTraits.cpp
===
--- clang/lib/Basic/TypeTraits.cpp
+++ clang/lib/Basic/TypeTraits.cpp
@@ -55,6 +55,15 @@
 #include "clang/Basic/TokenKinds.def"
 };
 
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
 const char *clang::getTraitName(TypeTrait T) {
   assert(T <= TT_Last && "invalid enum value!");
   return TypeTraitNames[T];
@@ -84,3 +93,8 @@
   assert(T <= UETT_Last && "invalid enum value!");
   return UnaryExprOrTypeTraitSpellings[T];
 }
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+  assert(T <= TT_Last && "invalid enum value!");
+  return TypeTraitArities[T];
+}
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5552,6 +5552,8 @@
   bool isQualifiedMemberAccess(Expr *E);
   QualType CheckAddressOfOpe

[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-11 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 451932.
inclyc added a comment.

rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/include/clang/Basic/TypeTraits.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TypeTraits.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp

Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5430,6 +5430,8 @@
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();
   QualType ResultType = Context.getLogicalOperationType();
 
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -4581,6 +4581,21 @@
   } while (!T.isNull() && T->isVariablyModifiedType());
 }
 
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+  if (Arity && N != Arity) {
+Diag(Loc, diag::err_type_trait_arity)
+<< Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+return false;
+  }
+
+  if (!Arity && N == 0) {
+Diag(Loc, diag::err_type_trait_arity)
+<< 1 << 1 << 1 << (int)N << SourceRange(Loc);
+return false;
+  }
+  return true;
+}
+
 /// Build a sizeof or alignof expression given a type operand.
 ExprResult
 Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3724,14 +3724,6 @@
   }
 }
 
-static unsigned TypeTraitArity(tok::TokenKind kind) {
-  switch (kind) {
-default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
-  }
-}
-
 /// Parse the built-in type-trait pseudo-functions that allow
 /// implementation of the TR1/C++11 type traits templates.
 ///
@@ -3745,7 +3737,6 @@
 ///
 ExprResult Parser::ParseTypeTrait() {
   tok::TokenKind Kind = Tok.getKind();
-  unsigned Arity = TypeTraitArity(Kind);
 
   SourceLocation Loc = ConsumeToken();
 
@@ -3780,18 +3771,6 @@
 
   SourceLocation EndLoc = Parens.getCloseLocation();
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
   return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
 }
 
Index: clang/lib/Basic/TypeTraits.cpp
===
--- clang/lib/Basic/TypeTraits.cpp
+++ clang/lib/Basic/TypeTraits.cpp
@@ -55,6 +55,15 @@
 #include "clang/Basic/TokenKinds.def"
 };
 
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
 const char *clang::getTraitName(TypeTrait T) {
   assert(T <= TT_Last && "invalid enum value!");
   return TypeTraitNames[T];
@@ -84,3 +93,8 @@
   assert(T <= UETT_Last && "invalid enum value!");
   return UnaryExprOrTypeTraitSpellings[T];
 }
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+  assert(T <= TT_Last && "invalid enum value!");
+  return TypeTraitArities[T];
+}
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5552,6 +5552,8 @@
   bool isQualifiedMemberAccess(Expr *E);
   QualType CheckAddressOfOperand(ExprR

[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-11 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Parse/ParseExprCXX.cpp:3783
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)

Before this patch, we check the `Arity` here, so using type traits with 
unexpected number of arguments does not crash clang

See https://godbolt.org/z/afGxvqdEh



Comment at: clang/lib/Sema/SemaExprCXX.cpp:5433
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();

Moves to here.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-11 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Basic/TypeTraits.cpp:64
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};

shafik wrote:
> @aaron.ballman do we really have to include this three times? We are defining 
> different macros so shouldn't we be able to include is just once? 
> 
> I see we do this in several other places but a few we don't.
I've tried 

```
#define TYPE_TRAIT(N, I, K) N,
#include "clang/Basic/TokenKinds.def"
```

But using enum `TypeTrait` as array index seems to have incorrect mapping.



Comment at: clang/lib/Parse/ParseExprCXX.cpp:3789
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)

shafik wrote:
> Why doesn't this catch our case but moving the check into `evaluateTypeTrait` 
> does?
In this case:

```
template bool b = __is_constructible(Ts...); // Parser: 1 argument 
`Ts`, no problem
bool x = b<>; // After template template instantiation tree transformation: 0 
argument, but missing checks!
```

`Ts...` is considered as 1 argument in Parsing, so passed this check.

> Why doesn't this catch our case but moving the check into `evaluateTypeTrait` 
> does?

This patch moved the check to `Sema::BuildTypeTrait`, this function will be 
invoked by tree transformation procedure.

>  invoked by tree transformation procedure

In fact: `clang::TreeTransform<(anonymous 
namespace)::TemplateInstantiator>::TransformTypeTraitExpr(clang::TypeTraitExpr*)
 SemaTemplateInstantiate.cpp`). 

I think it is not a good idea to move the check into  `evaluateTypeTrait`, 
because this function might be designed to return the final evaluation result, 
we should perform the check _before_ this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-11 Thread YingChi Long via Phabricator via cfe-commits
inclyc added inline comments.



Comment at: clang/lib/Basic/TypeTraits.cpp:64
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};

inclyc wrote:
> shafik wrote:
> > @aaron.ballman do we really have to include this three times? We are 
> > defining different macros so shouldn't we be able to include is just once? 
> > 
> > I see we do this in several other places but a few we don't.
> I've tried 
> 
> ```
> #define TYPE_TRAIT(N, I, K) N,
> #include "clang/Basic/TokenKinds.def"
> ```
> 
> But using enum `TypeTrait` as array index seems to have incorrect mapping.
> @aaron.ballman do we really have to include this three times? We are defining 
> different macros so shouldn't we be able to include is just once? 
> 
> I see we do this in several other places but a few we don't.

Type trait definitions in `#include "clang/Basic/TokenKinds.def"` may not be 
sorted by the number of arguments.

Example:

```
#define TYPE_TRAIT_1(some_stuff)
#define TYPE_TRAIT_N(some_stuff)
#define TYPE_TRAIT_2(some_stuff)
```

Might be necessary to include this 3 times to get sorted layouts, like

`[1, 1, 1, 2, 2, 2, 0, 0]`


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 452120.
inclyc added a comment.

move implemention of CheckTypeTraitArity into SemaExprCXX, since type traits 
are C++ specific language extension


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/include/clang/Basic/TypeTraits.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TypeTraits.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp

Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5427,9 +5427,26 @@
 }
 }
 
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+  if (Arity && N != Arity) {
+Diag(Loc, diag::err_type_trait_arity)
+<< Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+return false;
+  }
+
+  if (!Arity && N == 0) {
+Diag(Loc, diag::err_type_trait_arity)
+<< 1 << 1 << 1 << (int)N << SourceRange(Loc);
+return false;
+  }
+  return true;
+}
+
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();
   QualType ResultType = Context.getLogicalOperationType();
 
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3724,14 +3724,6 @@
   }
 }
 
-static unsigned TypeTraitArity(tok::TokenKind kind) {
-  switch (kind) {
-default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
-  }
-}
-
 /// Parse the built-in type-trait pseudo-functions that allow
 /// implementation of the TR1/C++11 type traits templates.
 ///
@@ -3745,7 +3737,6 @@
 ///
 ExprResult Parser::ParseTypeTrait() {
   tok::TokenKind Kind = Tok.getKind();
-  unsigned Arity = TypeTraitArity(Kind);
 
   SourceLocation Loc = ConsumeToken();
 
@@ -3780,18 +3771,6 @@
 
   SourceLocation EndLoc = Parens.getCloseLocation();
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
   return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
 }
 
Index: clang/lib/Basic/TypeTraits.cpp
===
--- clang/lib/Basic/TypeTraits.cpp
+++ clang/lib/Basic/TypeTraits.cpp
@@ -55,6 +55,15 @@
 #include "clang/Basic/TokenKinds.def"
 };
 
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
 const char *clang::getTraitName(TypeTrait T) {
   assert(T <= TT_Last && "invalid enum value!");
   return TypeTraitNames[T];
@@ -84,3 +93,8 @@
   assert(T <= UETT_Last && "invalid enum value!");
   return UnaryExprOrTypeTraitSpellings[T];
 }
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+  assert(T <= TT_Last && "invalid enum value!");
+  return TypeTraitArities[T];
+}
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5552,6 +5552,8 @@
   bool isQualifiedMemberAccess(Expr *E);
   QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
 
+  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+
   ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
 SourceLocation OpLoc,
 Unary

[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 452198.
inclyc added a comment.

add release notes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/TypeTraits.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TypeTraits.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp

Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5427,9 +5427,26 @@
 }
 }
 
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+  if (Arity && N != Arity) {
+Diag(Loc, diag::err_type_trait_arity)
+<< Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+return false;
+  }
+
+  if (!Arity && N == 0) {
+Diag(Loc, diag::err_type_trait_arity)
+<< 1 << 1 << 1 << (int)N << SourceRange(Loc);
+return false;
+  }
+  return true;
+}
+
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();
   QualType ResultType = Context.getLogicalOperationType();
 
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3724,14 +3724,6 @@
   }
 }
 
-static unsigned TypeTraitArity(tok::TokenKind kind) {
-  switch (kind) {
-default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
-  }
-}
-
 /// Parse the built-in type-trait pseudo-functions that allow
 /// implementation of the TR1/C++11 type traits templates.
 ///
@@ -3745,7 +3737,6 @@
 ///
 ExprResult Parser::ParseTypeTrait() {
   tok::TokenKind Kind = Tok.getKind();
-  unsigned Arity = TypeTraitArity(Kind);
 
   SourceLocation Loc = ConsumeToken();
 
@@ -3780,18 +3771,6 @@
 
   SourceLocation EndLoc = Parens.getCloseLocation();
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
   return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
 }
 
Index: clang/lib/Basic/TypeTraits.cpp
===
--- clang/lib/Basic/TypeTraits.cpp
+++ clang/lib/Basic/TypeTraits.cpp
@@ -55,6 +55,15 @@
 #include "clang/Basic/TokenKinds.def"
 };
 
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
 const char *clang::getTraitName(TypeTrait T) {
   assert(T <= TT_Last && "invalid enum value!");
   return TypeTraitNames[T];
@@ -84,3 +93,8 @@
   assert(T <= UETT_Last && "invalid enum value!");
   return UnaryExprOrTypeTraitSpellings[T];
 }
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+  assert(T <= TT_Last && "invalid enum value!");
+  return TypeTraitArities[T];
+}
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5552,6 +5552,8 @@
   bool isQualifiedMemberAccess(Expr *E);
   QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
 
+  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+
   ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
 SourceLocation OpLoc,
 UnaryExprOrTypeTrait ExprKind,
Index: clang/include/clang/Basic/TypeTra

[PATCH] D131423: [clang] fix frontend crash when evaluating type trait

2022-08-12 Thread YingChi Long via Phabricator via cfe-commits
inclyc updated this revision to Diff 452199.
inclyc added a comment.

.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131423/new/

https://reviews.llvm.org/D131423

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/TypeTraits.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Basic/TypeTraits.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp

Index: clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/type-trait-eval-crash-issue-57008.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only %s -verify
+
+// Shouldn't crash here
+// Reported by https://github.com/llvm/llvm-project/issues/57008
+template bool b = __is_constructible(Ts...); // expected-error{{type trait requires 1 or more arguments}}
+bool x = b<>; // expected-note{{in instantiation of variable template specialization}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -5427,9 +5427,26 @@
 }
 }
 
+bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) {
+  if (Arity && N != Arity) {
+Diag(Loc, diag::err_type_trait_arity)
+<< Arity << 0 << (Arity > 1) << (int)N << SourceRange(Loc);
+return false;
+  }
+
+  if (!Arity && N == 0) {
+Diag(Loc, diag::err_type_trait_arity)
+<< 1 << 1 << 1 << (int)N << SourceRange(Loc);
+return false;
+  }
+  return true;
+}
+
 ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
 ArrayRef Args,
 SourceLocation RParenLoc) {
+  if (!CheckTypeTraitArity(getTypeTraitArity(Kind), KWLoc, Args.size()))
+return ExprError();
   QualType ResultType = Context.getLogicalOperationType();
 
   if (Kind <= UTT_Last && !CheckUnaryTypeTraitTypeCompleteness(
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -3724,14 +3724,6 @@
   }
 }
 
-static unsigned TypeTraitArity(tok::TokenKind kind) {
-  switch (kind) {
-default: llvm_unreachable("Not a known type trait");
-#define TYPE_TRAIT(N,Spelling,K) case tok::kw_##Spelling: return N;
-#include "clang/Basic/TokenKinds.def"
-  }
-}
-
 /// Parse the built-in type-trait pseudo-functions that allow
 /// implementation of the TR1/C++11 type traits templates.
 ///
@@ -3745,7 +3737,6 @@
 ///
 ExprResult Parser::ParseTypeTrait() {
   tok::TokenKind Kind = Tok.getKind();
-  unsigned Arity = TypeTraitArity(Kind);
 
   SourceLocation Loc = ConsumeToken();
 
@@ -3780,18 +3771,6 @@
 
   SourceLocation EndLoc = Parens.getCloseLocation();
 
-  if (Arity && Args.size() != Arity) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << Arity << 0 << (Arity > 1) << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
-  if (!Arity && Args.empty()) {
-Diag(EndLoc, diag::err_type_trait_arity)
-  << 1 << 1 << 1 << (int)Args.size() << SourceRange(Loc);
-return ExprError();
-  }
-
   return Actions.ActOnTypeTrait(TypeTraitFromTokKind(Kind), Loc, Args, EndLoc);
 }
 
Index: clang/lib/Basic/TypeTraits.cpp
===
--- clang/lib/Basic/TypeTraits.cpp
+++ clang/lib/Basic/TypeTraits.cpp
@@ -55,6 +55,15 @@
 #include "clang/Basic/TokenKinds.def"
 };
 
+static constexpr const unsigned TypeTraitArities[] = {
+#define TYPE_TRAIT_1(Spelling, Name, Key) 1,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_2(Spelling, Name, Key) 2,
+#include "clang/Basic/TokenKinds.def"
+#define TYPE_TRAIT_N(Spelling, Name, Key) 0,
+#include "clang/Basic/TokenKinds.def"
+};
+
 const char *clang::getTraitName(TypeTrait T) {
   assert(T <= TT_Last && "invalid enum value!");
   return TypeTraitNames[T];
@@ -84,3 +93,8 @@
   assert(T <= UETT_Last && "invalid enum value!");
   return UnaryExprOrTypeTraitSpellings[T];
 }
+
+unsigned clang::getTypeTraitArity(TypeTrait T) {
+  assert(T <= TT_Last && "invalid enum value!");
+  return TypeTraitArities[T];
+}
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5552,6 +5552,8 @@
   bool isQualifiedMemberAccess(Expr *E);
   QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
 
+  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+
   ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo,
 SourceLocation OpLoc,
 UnaryExprOrTypeTrait ExprKind,
Index: clang/include/clang/Basic/TypeTraits.h
==

  1   2   >